OC+5-Foundation續&copy&單例模式singleton

NSFileManger的介紹和用法(文件操作)

1、NSFileManager的介紹
     NSFileManager:用來管理文件系統的,進行常見的文件或文件夾操作(拷貝、剪切、創建等)
     NSFileManager使用了單例模式singleton,使用defaultManager方法可以獲得那個單例對象

2、NSFileManager的基本使用(常見的判斷)
      NSString *filePath = @"/Users/ZacharyUE/Desktop/str.plist;//先給一個路徑
        NSString *filePath2 = @"/Users/ZacharyUE/Desktop";
       
//NSFileManager  用於判斷
       
//創建文件管理對象,單例對象(在程序運行期間,只有一個對象存在)
       
NSFileManager *fm = [NSFileManager defaultManager];
       
//1)判斷文件是否存在
       
BOOL isYES = [fm fileExistsAtPath:filePath];
       
NSLog(@"%d", isYES);
       
//2)判斷是否是一個目錄
       
if (isYES) {
           
BOOL isDir;
            [fm
fileExistsAtPath:filePath2 isDirectory:&isDir];
           
if (isDir) {
               
NSLog(@"這是一個目錄");
            }
else {
               
NSLog(@"不是一個目錄");
            }
        }
       
//3)判斷文件是否可讀
        isYES = [fm
isReadableFileAtPath:filePath];
       
NSLog(@"%d", isYES);
       
//4)是否可寫
        isYES = [fm
isWritableFileAtPath:filePath2];
       
NSLog(@"%d", isYES);
       
//5)是否可刪除
        isYES = [fm
isDeletableFileAtPath:filePath];
        NSLog(@"%d", isYES);


3、NSFileManager用法深入1
     -NSFileManager的文件訪問
       //創建文件對象
        NSFileManager *fm = [NSFileManager defaultManager];
        NSString *filePath = @"/Users/ZacharyUE/Desktop/str.plist;    //文件路徑
        NSString *dirPath = @"/Users/ZacharyUE/Desktop/儒釋道;         //目錄路徑
        //1)何如獲取文件的信息(屬性)
       
NSDictionary *dic = [fm attributesOfItemAtPath:filePath error:nil];
       
NSLog(@"%@", dic);
       
NSLog(@"%@, %@", [dic objectForKey:@"NSFileOwnerAccountName"], dic[@"NSFileOwnerAccountName"]);//字典通過key獲取值,兩種方式
       
//2)獲取指定目錄下文件及子目錄
       
//使用遞歸的方式  獲取當前目錄及子目錄下的所有文件及文件夾
       
NSArray *arr = [fm subpathsAtPath:dirPath];
       
//這種方法不是使用遞歸的方式實現
        arr = [fm
subpathsOfDirectoryAtPath:dirPath error:nil];
       
NSLog(@"%@", arr);
       
//3)獲取指定目錄下的子目錄(不在獲取後代路徑,即不在獲取子目錄下的信息)
        arr = [fm
contentsOfDirectoryAtPath:dirPath error:nil];
        NSLog(@"%@", arr);


4、NSFileManager用法深入2
       //第一步,必須有文件管理對象
       
NSFileManager *fm = [NSFileManager defaultManager];
      
//如何創建目錄(路徑:/Users/ZacharyUE/Desktop/dir)
        NSString *createDirPath = @"/Users/ZacharyUE/Desktop/dir";
       
/*
         createDirectoryAtPath:@"
路徑" withIntermediateDirectories:YES/NO
         YES/NO:
會把缺失文件夾補上來,後者如果上級文件夾確實,會報錯
         attributes:
屬性的字典 error:錯誤對象
        */

       
BOOL isYES = [fm createDirectoryAtPath:createDirPath withIntermediateDirectories:NO attributes:nil error:nil];
       
if (isYES) {
           
NSLog(@"%d", isYES);
        }

//如何創建文件
        NSString *str = @"shi最棒的!";//寫入到@"/Users/ZacharyUE/Desktop/dir/me.txt";
        //以下的createDirPath = @"/Users/ZacharyUE/Desktop/dir/me.txt";
        //1writeToFile
       
//2createFileAtPath
       
/*
            createFileAtPath:@"
路徑" contents:NSData類型的數據 attributes:文件的屬性的字典
        
創建NSData:是一個處理二進制數據的類
        
NSString--------NSData
         */

       
NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding];
       
BOOL isYES = [fm createFileAtPath:createDirPath contents:data attributes:nil];
        NSLog(@"%d", isYES);

//如何copy文件
       
NSString *copyPath = @"/Users/ZacharyUE/Desktop/dir/xxx/me.txt";
       
BOOL isYES = [fm copyItemAtPath:createDirPath toPath:copyPath error:nil];
        NSLog(@"%d", isYES);

//如何移動文件
       
NSString *movePath = @"/Users/ZacharyUE/Desktop/dir/aaa/me.txt";
        [fm moveItemAtPath:createDirPath toPath:movePath error:nil];

//如何刪除文件,@"/Users/ZacharyUE/Desktop/dir/me.txt"
        [fm removeItemAtPath:createDirPath error:nil];

5、NSFileManager文件下載的思路
     1)發送請求給服務器,要求下載某個文件
     2)服務器發出響應,返回文件數據
     3)手機客戶端利用NSData來存放服務器返回的文件數據
     4)利用NSFileManager將NSData裏面的文件數據寫到新的文件中

6、iOS沙盒(sandbox)機制
   每個iOS應用都有自己的應用沙盒,應用沙盒就是文件系統目錄,與其他應用的文件系統隔離,iOS系統不允許訪問其他應用的應用沙盒。
   在iOS8中已經開放訪問(extension),對幾個固定系統區域的擴展機制。
   應用沙盒一般包含幾個文件目錄:應用程序包、Documents、Libaray(子目錄Caches和Preferences)、tmp
   應用程序包:包含所有的資源文件和可執行文件。
   Documents:保存應用運行時生成的需要持久化的數據,iTunes會自動備份該目錄。
   tmp:保存應用運行時所需的零時數據,使用完後相應地文件從該目錄刪除。未運行時,系統也可能清除該目錄的文件,iTunes不會同步該目錄。iPhone重啓時,該目錄下的文件會丟失。
   Libaray:存儲程序的默認設置和其它狀態信息,iTunes會自動備份該目錄。
   Libaray/Caches:存儲緩存文件,iTunes不會備份此目錄,此目錄下文件不會在應用退出時刪除。
   Libaray/Preference:保存應用的所有偏好設置(配置信息\SQLite),iOS的Settings(設置)應用會在該目錄中查找應用的設置信息,iTunes會自動備份該目錄。

//沙盒路徑獲取方法:
       
//1)沙盒的路徑
       
NSString *sandBoxPath = NSHomeDirectory();
       
NSLog(@"sandBoxPath = %@", sandBoxPath);//Mac下,用戶根目錄
       
//2tmp路徑
       
NSString *tmpPath = NSTemporaryDirectory();
       
NSLog(@"tmpPath = %@", tmpPath);
       
//2Documents路徑
      
// NSSearchPathForDirectoriesInDomains(要查找的目錄, 是否使用主目錄, YES/NO是否獲取全路徑)
       
NSArray *arr = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
       
NSLog(@"%@", arr);
       
//4Librarycaches同理
        arr =
NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
       
NSLog(@"%@", arr);
       
//5preferences路徑,在Libaray的基礎上,拼接/Preferences
        NSString *filePath = [arr lastObject];
        //stringByAppendingPathComponent用於拼接,也可以創建文件:@“Preferences/a.txt"
        NSString *str = [filePath stringByAppendingPathComponent:@"Preferences"];
        NSLog(@"%@", str);


7、常見的結構體
1)NSPoint和CGPoint的使用()
     /* Points. */
     //二維平面的一個點
struct CGPoint {
    CGFloat x;
    CGFloat y;
};
typedef struct CGPoint CGPoint;//NSPoint是CGPoint的別名,沒區別

CGPoint c1;//c1CGPoint結構體類型的變量
        c1.
x = 10;
        c1.
y = 10;
       
CGPoint c2 = {10, 10};
       
//OC特有的賦值
       
CGPoint c3 = CGPointMake(10, 10);
        NSPoint c4 = NSMakePoint(5, 5);


2)NSSize和CGSize的使用(大小)
      /* Sizes. */
     //表示平面的面積
struct CGSize {
    CGFloat width;//寬
    CGFloat height;//高
};
typedef struct CGSize CGSize;

//同理,也有特有的賦值方式,形式與上面類似CGSizeMake和NSMakeSize
3)NSRect和CGRect的使用(矩形)
/* Rectangles. */
//表示從左上角某個點開始的矩形區域
struct CGRect {
    CGPoint origin;//開始點
    CGSize size;//大小
};
typedef struct CGRect CGRect;

CGRect r1;
        r1.origin.x = 0;
        r1.origin.y = 0;
        r1.size.width = 200;
        r1.size.height = 80;
       
        CGRect r2 = {{0, 0}, {10, 20}};
        //OC特有賦值方式
        CGRect r3 = CGRectMake(0, 0, 30, 80);
        NSRect r4 = NSMakeRect(0, 0, 89, 90);
      //快捷查看值的方法,轉換爲字符串
        NSLog(@"r4 = %@", NSStringFromRect(r4));
     //同理,上面的Size和Point都可以
4)常見結構體的使用注意
  蘋果官方推薦使用CG開頭



8、NSNumber的使用
   1)NSNumber的介紹和使用
     OC中處理數字的一個類
     NSArray和NSDictionary中只能存放OC對象,需要先將基本類型包裝成對象,這樣就可以存放到數組或字典
   2)NSNumber的創建
            int a = 10;
       
        NSNumber *intObj = [NSNumber numberWithInt:a];//其他類型同理
        NSArray *array = [NSArray arrayWithObjects:intObj, nil];
        NSLog(@"%@", array);
   3)從NSNumber對象中獲取到基本數據類型
         float b =2.3f;
       
NSNumber *floatObj = [NSNumber numberWithFloat:b];
        [array
addObject:floatObj];
       
NSLog(@"%@", array);
       
       
//數組的第一個元素和第二個元素相加
       
//1)取出數組的元素
       
//2)把數組元素轉換爲基本數據類型
       
NSNumber *n1 = array[0];
       
int a1 = [n1 intValue];//獲取對象的整形值
       
       
NSNumber *n2 = array[1];
       
float b1 = [n2 floatValue];
        a1 = a1 + b1;
        NSLog(@"%d", a1);

 簡寫形式@(變量名)@數值@YES,都是把變量、數值或YES包裝成對象

9、NSValue的介紹和使用
     NSNumber是NSValue的子類,NSValue主要是把指針,CGRect結構體等包裝成OC對象,以便存儲。
     (int/float/char/pointers/structures/object ids)
     NSValue類的目標:允許以上數據類型的數據結構能夠被添加到集合裏,如NSArray和NSDictionary
     爲了方便結構體和NSValue的轉換,Foundation提供了一下方法:
     1)存儲結構體到集合
      + (NSValue *)valueWithPoint:(NSPoint)point;
     + (NSValue *)valueWithSize:(NSSize)size;
     + (NSValue *)valueWithRect:(NSRect)rect;

      //創建一個結構體變量,保存一個點
       
CGPoint p1 = CGPointMake(10, 10);
       
//將結構體包裝爲NSValue對象
       
NSValue *pointObj = [NSValue valueWithPoint:p1];
       
NSMutableArray *array = [NSMutableArray arrayWithObjects:pointObj, nil];
       
NSLog(@"%@", array);
       
       
//創建一個結構體,保存Size
       
CGSize s1 = CGSizeMake(20, 20);
       
NSValue *sizeObj = [NSValue valueWithSize:s1];
        [array
addObject:sizeObj];
       
NSLog(@"%@", array);
       
//創建一個結構體,保存Rect
       
CGRect r1 = CGRectMake(1, 1, 22, 33);
        [array
addObject:[NSValue valueWithRect:r1]];
        NSLog(@"%@", array);
     2)從NSValue對象取出之前包裝的結構體
     - (NSPoint)pointValue;
     - (NSSize)sizeValue;
     - (NSRect)rectValue;
     
      //取最後的值
       
NSValue *lastValue = [array lastObject];
       
NSRect r2 = [lastValue rectValue];
        NSLog(@"%@", NSStringFromRect(r2)); //轉換爲字符串

//自定義結構體
typedef struct data {
   
int year;
   
int month;
   
int day;
} MYData;

//定義結構體變量
       
MYData md = {2015, 9, 3};
       
//將自定義結構體包裝成NSValue對象
       
//@encode(MYData) 作用,把MYData類型生成一個常量字符串描述
       
NSValue *mdObj = [NSValue valueWithBytes:&md objCType:@encode(MYData)];
       
//保存自定義結構體,到數組
       
NSMutableArray *arr = [NSMutableArray arrayWithObjects:mdObj, nil];
       
//從數組取出NSValue對象
       
MYData md1;
       [[arr objectAtIndex:0] getValue:&md1];//getValue獲取的值,保存到md1
        //從對象中,取出結構體變量的值
        NSLog(@"%d-%d-%d", md1.year, md1.month, md1.day);



10、NSDate的介紹和使用
1)NSDate的介紹和使用
NSDate可以表示時間,可以進行一些常見的日期、時間處理。一個NSDate對象就代表一個時間,[NSDate date]返回的就是當前時間。
//NSDate OC中提供日期時間處理的一個類
       
//1)獲取當前時間
       
NSDate *d1 = [NSDate date];//創建一個日期時間對象對象
       
//北京東八區,打印的時間(格林威治時間)+8 = 現在時間
        NSLog(@"%@", d1);

        //2)格式化顯示時間
       
NSDateFormatter *formatter = [NSDateFormatter new];
       
//設置日期的顯示格式
       
//yyyy:年份  MM:月份    dd:天數
       
//HH:24小時制  hh:12小時制
       
//mm:分鐘數    ss:秒數
        formatter.
dateFormat = @"yyyyMMdd HH:mm:ss";
       
NSString *dateStr = [formatter stringFromDate:d1];
        NSLog(@"%@", dateStr);

         //3)計算時間
           
//1、計算明天的此刻時間(24小時之後的時間)
       
NSTimeInterval t = 60 * 60 * 24;
       
NSDate *tom = [NSDate dateWithTimeIntervalSinceNow:t];
       
       
NSDateFormatter *formatter = [NSDateFormatter new];//格式化顯示
        formatter.
dateFormat = @"yyyy-MM-dd hh:mm:ss";
       
NSString *str = [formatter stringFromDate:tom];
       
NSLog(@"%@", str);
           
//2、計算昨天的此刻時間(-t24小時之前的時間)
       
NSDate *yest = [NSDate dateWithTimeIntervalSinceNow:-t];
        str = [formatter
stringFromDate:yest];
       
NSLog(@"%@", str);
           
//也可以用當前時間,進行加減時間
       
NSDate *now = [NSDate date];
       
NSDate *yest2 = [now addTimeInterval:-t];//該方法已經被放逐了
        str = [formatter
stringFromDate:yest2];
        NSLog(@"%@", str);

         //4)日期時間對象的使用
           
//1NSCalendar 日期類,可以幫助快速獲取年月日 時分秒的信息
       
NSDate *d = [NSDate date];
       
//創建日期對象
       
NSCalendar *cal = [NSCalendar currentCalendar];
       
//參數:獲取日期的哪個單元(可以多個單元,|)         當前日期對象
       
NSDateComponents *com = [cal components:NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay fromDate:d];
       
NSLog(@"%ld-%ld-%ld", com.year, com.month, com.day);
            //2、時間差方法:components:<#(NSCalendarUnit)#> fromDate:<#(nonnull NSDate *)#> toDate:<#(nonnull NSDate *)#> options:<#(NSCalendarOptions)#>



11、集合對象的內存管理
1)集合內存管理
                   //創建對象
       
Person *p = [Person new]; //1
       
//定義數組,並且把P放到數組中
       
//規律:只要把對象放入數組,retainCount+1
        //NSArray *arr = [NSArray arrayWithObject:p];//2
        NSMutableArray *arr = [NSMutableArray array];
        [arr addObject:p];//2
//上面都是快速創建對象,會被加入自動釋放池。如果是[[NSArray alloc] init]、copy或new,則不會加入自動釋放池,則該對象不會被釋放,不會調用dealloc
        NSLog(@"p.retainCount = %lu", p.retainCount);
        [p
release];
       
//規律2:數組被銷燬時,對對象發送了一次release消息
       
//銷燬順序:數組先掛-----》數組向其中的對象也發送release
       
NSLog(@"p.retainCount = %lu", p.retainCount);
       
//結論:
       
//1)當對象被添加到數組中,對象的引用計數+1
       
//2)數組被銷燬時,對對象發送了一次release消息
        //3)數組被銷燬了,其中的對象不一定被銷燬    
2)集合內存管理總結
1、當調用alloc、new、copy(mutablecopy)方法產生一個新對象的時候,就必須在最後調用一次release或者autorelease。因爲不會加入自動釋放池。
2、retain和release必須成對出現
3、當一個對象添加集合,retain+1,retainCount+1
   當一個集合(快速創建)被銷燬,集合所有對象均被release一次,retainCount-1
   當一個對象從集合中移除,這個對象會被release一次,retainCount-1
4、普遍規律:當方法名是add\insert開頭   計數器+1
           當方法名是remove\delete開頭,計數器-1



12、copy概念及入門
1、copy概念
copy:複製,拷貝,是產生一個副本的過程。
對象拷貝的目的:要使用某個對象的數據,但是在修改對象的時候不影響原來的對象內容。源文件和副本文件,互不影響。
copy功能:一個對象可以調用copy或mutableCopy方法創建一個副本對象
        copy:創建不可變副本(如NSString)
        mutableCopy:創建可變副本(如NSMutableString)
copy功能的前提:1)淺拷貝copy:需要遵守NSCopy協議,實現copyWithZone:方法
                  @protocol NSCopying
- (id)copyWithZone:(nullable NSZone *)zone;
   @end   
              2)深拷貝mutableCopy:需要遵守NSMutableCopying協議,實現mutableCopyWithZone:方法
                                                 @protocol NSMutableCopying
- (id)mutableCopyWithZone:(nullable NSZone *)zone;
   @end
2、copy快速入門
不可變對象,copy      產生不可變對象
不可變對象,mutableCopy   產生可變對象
可變對象,copy         產生不可變對象
可變對象,mutableCopy   產生可變對象


13、copy與內存管理
淺拷貝:只是拷貝了地址,並沒有真正的分配新的內存空間(源對象引用計數+1,副本對象指向源對象,兩者一樣)
深拷貝:分配了新的內存空間(源對象引用計數不變,副本對象爲1)

14、@property中的copy關鍵字
1)MRC
     1、copy:只用於NSString和block
     2、retain:除NSString和block以外的對象
     3、assign:基本數據類型、枚舉、結構體(非OC對象)。當兩個對象互相引用時,一段assign,一段retain
2)ARC
     1、copy:只用於NSString和block
     2、strong:除NSString和block以外的對象
     3、weak:當兩個對象互相引用時,一段weak,一段strong
     4、assign:基本數據類型、枚舉、結構體(非OC對象)

@property (nonatomic, copy) NSString *name;
#import <Foundation/Foundation.h>
#import "Person.h"

int main(int argc, const char * argv[]) {
   
@autoreleasepool {
   
       
Person *p = [[Person alloc] init];

       
NSMutableString *str = [NSMutableString string];
        [str
appendString:@"xxx"];
        p.
name = str;
       
NSLog(@"%@", p.name);
       
//使用copy時,防止這種無理的賦值。name得到的只是str的副本,再改變str不會影響name
        [str
appendString:@"ooo"];
       
NSLog(@"%@", p.name);
       
       
       
       
       
        [p
release];
    }
   
return 0;
}


15、爲自定義的類實現copy操作
步驟:1、新建Person類
     2、爲Person類實現copy操作
          1)讓Person類遵守NSCopying協議
          2)實現copyWithZone方法,該方法返回一個對象的副本
          3)在copyWithZone方法中,創建一個新的對象,並設置該對象的數據與現有對象一致,且返回該對象
     3、創建Person對象,調用copy方法,查看地址
參數zone:表示空間,指定了zone,就可以指定新建對象對應的內存空間。如今開發中,zone幾乎可以忽略

例子:1、 @interface Dog : NSObject<NSCopying>
@property (nonatomic, assign) int tuiNum;
@property (nonatomic,assign) int speed;
@end

     2、 @implementation Dog
- (id)copyWithZone:(nullable NSZone *)zone {
   
   
    NSLog(@"copy完畢");
    //互不影響,需申請新空間
    Dog *d = [[Dog alloc] init];
    d.speed = self.speed;
    d.tuiNum = self.tuiNum;
    //返回新空間的地址
    return d;
}
@end

3、  
       
Dog *dog = [Dog new];
        dog.
speed = 230;
        dog.
tuiNum = 8;
       
//雖然重寫copyWithZone方法,依然調用copy。歷史原因
       
Dog *yellowDog = [dog copy];
        NSLog(@"%d,%d", yellowDog.speed, yellowDog.tuiNum);



16、簡單的單例模式實現
1)理解單例模式概念
單例模式(singleton):類的對象成爲系統中唯一的實例,提供一個訪問點,供客戶類共享資源
單例使用場景:1、類只能夠有一個實例,而且必須從一個爲人熟知的訪問點對其進行訪問,比如工廠方法
            2、這個唯一的實例只能通過子類化進行擴展,而且擴展的對象不會破壞客戶端代碼
2)單例模式的實現
1、SingletonTools單例工具類
#import <Foundation/Foundation.h>

@interface SingletonTools : NSObject<NSCopying>
@property (nonatomic, assign) int num;
@property (nonatomic, copy) NSString *text;
//單例的類,提供一個接入點
+(
instancetype)shareInstances;
//防止創建新的對象或者破壞該單例對象,需重寫以下方法
-(id)copyWithZone:(NSZone *)zone;
+(
id)allocWithZone:(NSZone *)zone;
-(
id)retain;
-(
NSUInteger)retainCount;
-(
oneway void)release;
-(
id)autorelease;
@end
-------------------------------------------------------------------------------
#import "SingletonTools.h"
//定義一個全局變量
static SingletonTools *instances = nil;//static增長使用週期,下次使用還有值
@implementation SingletonTools
//單例接入點方法
+(
instancetype)shareInstances {
   
//目的:保證對象必須唯一
   
if (instances == nil) {
       
//創建一個對象
       
instances = [[SingletonTools alloc] init];
       
return instances;
    }
   
return instances;
}

//防止創建新的對象或者破壞該單例對象,需重寫以下方法
-(
id)copyWithZone:(NSZone *)zone {
   
return self;
}
+(
id)allocWithZone:(NSZone *)zone {
   
//線程保護
   
@synchronized(self) {
       
if (instances == nil) {
           
//調用父類alloc
           
instances = [super allocWithZone:zone];
           
return instances;//此處有待考究,沒有關鎖,就退出了
        }
       
return instances;
    }
}
-(
id)retain {
   
return self;
}
-(
NSUInteger)retainCount {
    return  1;
}
-(
oneway void)release {
   
}
-(
id)autorelease {
   
return self;
}
@end



2、Person類
#import <Foundation/Foundation.h>

@interface Person : NSObject
-(
void) run;
@end
----------------------------------------------------------------------------------------
#import "Person.h"
#import
"SingletonTools.h"
@implementation Person
-(
void) run {
   
//創建單例對象
   
SingletonTools *st = [SingletonTools shareInstances];
    st.
num = 500;
    st.
text = @"xxxxx";
}
@end



3、Dog類
#import <Foundation/Foundation.h>

@interface Dog : NSObject
-(
void)run;
@end
--------------------------------------------------------------------------------------
#import "Dog.h"
#import
"SingletonTools.h"
@implementation Dog
-(
void)run {
   
SingletonTools *st = [SingletonTools shareInstances];
   
NSLog(@"%d,%@", st.num, st.text);
}

@end



4、main
#import <Foundation/Foundation.h>
#import
"Person.h"
#import
"Dog.h"

int main(int argc, const char * argv[]) {
   
@autoreleasepool {
       
Person *p = [Person new];
        [p
run];
       
       
Dog *d = [Dog new];
        [d
run];//通過單例,d也可以訪問p的數據
       
//而且在重寫方法後,並不需要在意在Dog類的run中是如何創建單例對象(快速或者alloc
       
//單例實現了兩個不相干的類的數據傳輸
    }
   
return 0;
}
Console:500,xxxxx
發佈了43 篇原創文章 · 獲贊 1 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章