iOS開發學習之OC(9) OC中的NSDictionary基本概念

分類:技術 時間:2016-10-06

一、NSDictionary基本概念

1.1什么是NSDictionary

  • NSDictionary翻譯過來叫做”字典”
  • 日常生活中,“字典”的作用:通過一個拼音或者漢字,就能找到對應的詳細解釋
  • NSDictionary的作用類似:通過一個key,就能找到對應的value
  • NSDictionary是不可變的, 一旦初始化完畢, 里面的內容就無法修改

1.2NSDictionary的創建

  • (instancetype)dictionary;
    • (instancetype)dictionaryWithObject:(id)object forKey:(id lt;NSCopyinggt;)key;
    • (instancetype)dictionaryWithObjectsAndKeys:(id)firstObject, ...;
    • (id)dictionaryWithContentsOfFile:(NSString *)path;
    • (id)dictionaryWithContentsOfURL:(NSURL *)url;
  • NSDictionary創建簡寫
    • 以前
      NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:@quot;lnjquot;, @quot;namequot;, @quot;12345678quot;, @quot;phonequot;, @quot;天朝quot;, @quot;addressquot;, nil];
    • 現在
      NSDictionary *dict = @{@quot;namequot;:@quot;lnjquot;, @quot;phonequot;:@quot;12345678quot;, @quot;addressquot;:@quot;天朝quot;};
  • NSDictionary獲取元素簡寫
    • 以前
      [dict objectForKey:@quot;name”];
    • 現在
      dict[@quot;name”];
  • 鍵值對集合的特點
    • 字典存儲的時候,必須是quot;鍵值對quot;的方式來存儲(同時鍵不要重復)
    • 鍵值對中存儲的數據是quot;無序的quot;.
    • 鍵值對集合可以根據鍵, 快速獲取數據.

1.3NSDictionary的遍歷

  • -(NSUInteger)count;
    • 返回字典的鍵值對數目
  • -(id)objectForKey:(id)aKey;

    • 根據key取出value
  • 快速遍歷

    NSDictionary *dict = @{@quot;namequot;:@quot;lnjquot;, @quot;phonequot;:@quot;12345678quot;, @quot;addressquot;:@quot;天朝quot;}; 
    for (NSString *key in dict) { 
         NSLog(@quot;key = %@, value = http://www.tuicool.com/articles/%@quot;, key, dict[key]);
    }
  • Block遍歷
    [dict enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString *obj, BOOL *stop) { NSLog(@quot;key = %@, value = http://www.tuicool.com/articles/%@quot;, key, obj); }];

    1.4NSDictionary文件操作

  • 將字典寫入文件中
    • -(BOOL)writeToFile:(NSString *)path atomically:(BOOL)useAuxiliaryFile;
    • -(BOOL)writeToURL:(NSURL *)url atomically:(BOOL)atomically;
    • 存結果是xml文件格式,但蘋果官方推薦為plist后綴。

示例:

NSDictionary *dict = @{@quot;namequot;:@quot;lnjquot;, @quot;phonequot;:@quot;12345678quot;, @quot;addressquot;:@quot;天朝quot;}; 
BOOL flag = [dict writeToFile:@quot;/Users/LNJ/Desktop/dict.plistquot; atomically:YES]; NSLog(@quot;flag = %iquot;, flag);
  • 從文件中讀取字典
NSDictionary *newDict = [NSDictionary dictionaryWithContentsOfFile:@quot;/Users/LNJ/Desktop/dict.plistquot;]; NSLog(@quot;newDict = %@quot;, newDict);

二、NSMutableDictionary基本概念

2.1NSMutableDictionary 基本概念

  • 什么是NSMutableDictionary
    • NSMutableDictionary是NSDictionary的子類
    • NSDictionary是不可變的,一旦初始化完畢后,它里面的內容就永遠是固定的,不能刪除里面的元素, 也不能再往里面添加元素
    • NSMutableDictionary是可變的,隨時可以往里面添加\更改\刪除元素

2.2NSMutableDictionary的常見操作

  • -(void)setObject:(id)anObject forKey:(id )aKey;
    • 添加一個鍵值對(會把aKey之前對應的值給替換掉)
  • -(void)removeObjectForKey:(id)aKey;
    • 通過aKey刪除對應的value
  • -(void)removeAllObjects;
    • 刪除所有的鍵值對

2.3NSMutableDictionary的簡寫

  • 設置鍵值對
    • 以前
      [dict setObject:@quot;Jackquot; forKey:@quot;name”];
    • 現在
      dict[@quot;namequot;] = @quot;Jackquot;;

2.4NSDictionary和NSArray對比

  • NSArray和NSDictionary的區別
    • NSArray是有序的,NSDictionary是無序的
    • NSArray是通過下標訪問元素,NSDictionary是通過key訪問元素
  • NSArray的用法
    • 創建
      @[@quot;Jackquot;, @quot;Rosequot;] (返回是不可變數組)
    • 訪問
      id d = array[1];
    • 賦值
      array[1] = @quot;jackquot;;
  • NSDictionary的用法 創建
    @{ @quot;namequot; : @quot;Jackquot;, @quot;phonequot; : @quot;10086quot; } (返回是不可變字典)
    • 訪問
      id d = dict[@quot;namequot;];
    • 賦值
      dict[@quot;namequot;] = @quot;jackquot;;

三、常見的結構體

3.1NSPoint和CGPoint

  • CGPoint和NSPoint是同義的
typedef CGPoint NSPoint;

CGPoint的定義struct CGPoint { 
  CGFloat x; 
  CGFloat y;
};
typedef struct CGPoint CGPoint;
typedef double CGFloat;
  • CGPoint代表的是二維平面中的一個點
    • 可以使用CGPointMake和NSMakePoint函數創建CGPoint

3.2NSSize和CGSize

  • CGSize和NSSize是同義的
typedef CGSize NSSize;

CGSize的定義struct CGSize { 
      CGFloat width; 
      CGFloat height;
};
typedef struct CGSize CGSize;
  • CGSize代表的是二維平面中的某個物體的尺寸(寬度和高度)
    • 可以使用CGSizeMake和NSMakeSize函數創建CGSize

3.3NSRect和的CGRect

  • CGRect和NSRect是同義的
typedef CGRect NSRect;
CGRect的定義struct CGRect { 
     CGPoint origin; 
     CGSize size;};
typedef struct CGRect CGRect;
  • CGRect代表的是二維平面中的某個物體的位置和尺寸
    • 可以使用CGRectMake和NSMakeRect函數創建CGRect

3.4常見的結構體使用注意

  • 蘋果官方推薦使用CG開頭的:
    • CGPoint
    • CGSize
    • CGRect

四、NSNumber

4.1NSNumber基本概念

  • NSArray\NSDictionary中只能存放OC對象,不能存放int\float\double等基本數據類
  • 如果真想把基本數據(比如int)放進數組或字典中,需要先將基本數據類型包裝成OC對象

    Paste_Image.png

  • NSNumber可以將基本數據類型包裝成對象,這樣就可以間接將基本數據類型存進NSArray\NSDictionary中

    Paste_Image.png

4.2NSNumber的創建

  • 以前
     (NSNumber *)numberWithInt:(int)value;
     (NSNumber *)numberWithDouble:(double)value;
     (NSNumber *)numberWithBool:(BOOL)value;
  • 現在
    @10;
    @10.5;
    @YES;
    @(num);

4.3從NSNumber對象中的到基本類型數據

- (char)charValue;
- (int)intValue;
- (long)longValue;
- (double)doubleValue;
- (BOOL)boolValue;
- (NSString *)stringValue;
- (NSComparisonResult)compare:(NSNumber *)otherNumber;
- (BOOL)isEqualToNumber:(NSNumber *)number;

五、NSValue

5.1NSValue基本概念

  • NSNumber是NSValue的子類, 但NSNumber只能包裝數字類型
  • NSValue可以包裝任意值
    • 因此, 可以用NSValue將結構體包裝后,加入NSArray\NSDictionary中

5.2常見結構體的包裝

  • 為了方便 結構體 和NSValue的轉換,Foundation提供了以下方法
  • 將結構體包裝成NSValue對象
  (NSValue *)valueWithPoint:(NSPoint)point;
  (NSValue *)valueWithSize:(NSSize)size;
  (NSValue *)valueWithRect:(NSRect)rect;
  • 從NSValue對象取出之前包裝的結構體
- (NSPoint)pointValue;
- (NSSize)sizeValue;
- (NSRect)rectValue;

5.3任意數據的包裝

  • NSValue提供了下列方法來包裝任意數據
  (NSValue *)valueWithBytes:(const void *)value objCType:(const char *)type;
  value參數 : 所包裝數據的地址
  type參數 : 用來描述這個數據類型的字符串, 用@encode指令來生成

- 從NSValue中取出所包裝的數據
- (void)getValue:(void *)value;

六、NSDate

6.1NSDate基本概念

  • NSDate可以用來表示時間, 可以進行一些常見的日期\時間處理
  • 一個NSDate對象就代表一個時間
  • [NSDate date]返回的就是當前時間
NSDate *now = [NSDate date]; 
NSLog(@quot;now = %@quot;, now); 
// 設置轉換后的目標日期時區 
NSTimeZone *zone = [NSTimeZone systemTimeZone]; 
// 得到源日期與世界標準時間的偏移量 
NSInteger interval = [zone secondsFromGMTForDate: date]; 
NSLog(@quot;interval = %luquot;, interval); 
// 在當前時間基礎上追加時區差值 
now = [now dateByAddingTimeInterval:interval]; 
NSLog(@quot;%@quot;, date);

6.2格式化日期

  • NSDate -gt; NSString
    // 1.創建時間 
    NSDate *now = [NSDate date]; 
    // 2.創建時間格式化 
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; 
    // 3.指定格式 
    formatter.dateFormat = @quot;yyyy-MM-dd HH:mm:ssquot;; 
    // 4.格式化時間 
    NSString *str = [formatter stringFromDate:now]; 
    NSLog(@quot;%@quot;, str);
  • NSString -gt; NSDate
NSString *str = @quot;2015-06-28 19:53:24quot;; 
NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; formatter.dateFormat = @quot;yyyy-MM-dd HH:mm:ssquot;; 
NSDate *date = [formatter dateFromString:str]; 
NSLog(@quot;%@quot;, date);

6.3日期時間對象

  • 結合NSCalendar和NSDate能做更多的日期\時間處理
  • 獲得NSCalendar對象
    NSCalendar *calendar = [NSCalendar currentCalendar];
  • 獲得年月日
    ```
  • (NSDateComponents )components:(NSCalendarUnit)unitFlags fromDate:(NSDate )date;
    ``
    NSDate *date = [NSDate date];
    // 1.創建日歷對象 
    NSCalendar *calendar = [NSCalendar currentCalendar]; 
    // 2.利用日歷對象獲取年月日時分秒 
    NSCalendarUnit type = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond; 
    NSDateComponents *cmps =[calendar components:type fromDate:date]; NSLog(@quot;year = %luquot;, cmps.year);
    NSLog(@quot;month = %luquot;, cmps.month); 
    NSLog(@quot;day = %luquot;, cmps.day); 
    NSLog(@quot;hour = %luquot;, cmps.hour); 
    NSLog(@quot;minute = %luquot;, cmps.minute); 
    NSLog(@quot;second = %luquot;, cmps.second); 
    NSLog(@quot;date = %@quot;, date);
  • 比較兩個日期的差距
- (NSDateComponents *)components:(NSCalendarUnit)unitFlags fromDate:(NSDate *)startingDate toDate:(NSDate *)resultDate options:(NSCalendarOptions)opts;
// 1.確定時間 
NSString *time1 = @quot;2015-06-23 12:18:15quot;; 
NSString *time2 = @quot;2015-06-28 10:10:10quot;; 
// 2.將時間轉換為
date NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; formatter.dateFormat = @quot;yyyy-MM-dd HH:mm:ssquot;; 
NSDate *date1 = [formatter dateFromString:time1]; 
NSDate *date2 = [formatter dateFromString:time2]; 
// 3.創建日歷 
NSCalendar *calendar = [NSCalendar currentCalendar]; 
NSCalendarUnit type = NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond; 
// 4.利用日歷對象比較兩個時間的差值 
NSDateComponents *cmps = [calendar components:type fromDate:date1 toDate:date2 options:0]; 
// 5.輸出結果 
NSLog(@quot;兩個時間相差%ld年%ld月%ld日%ld小時%ld分鐘%ld秒quot;, cmps.year, cmps.month, cmps.day, cmps.hour, cmps.minute, cmps.second);

七、NSFileManager

7.1NSFileManager介紹

  • 什么是NSFileManager
    • 顧名思義, NSFileManager是用來管理文件系統的
    • 它可以用來進行常見的文件\文件夾操作
  • NSFileManager使用了單例模式
    • 使用defaultManager方法可以獲得那個單例對象
      [NSFileManager defaultManager]
  • NSFileManager用法
  • -(BOOL)fileExistsAtPath:(NSString *)path;
    • path這個文件\文件夾是否存在
      NSFileManager *manager = [NSFileManager defaultManager]; 
      // 可以判斷文件 
      BOOL flag = [manager fileExistsAtPath:@quot;/Users/LNJ/Desktop/lnj.txtquot;]; NSLog(@quot;flag = %iquot;, flag); 
      // 可以判斷文件夾 
      flag = [manager fileExistsAtPath:@quot;/Users/LNJ/Desktop/未命名文件夾quot;]; NSLog(@quot;flag = %iquot;, flag);
  • -(BOOL)fileExistsAtPath:(NSString )path isDirectory:(BOOL )isDirectory;
    • path這個文件\文件夾是否存在, isDirectory代表是否為文件夾
      NSFileManager *manager = [NSFileManager defaultManager]; 
      BOOL directory = NO; 
      BOOL flag = [manager fileExistsAtPath:@quot;/Users/LNJ/Desktop/未命名文件夾quot; isDirectory:amp;directory]; 
      NSLog(@quot;flag = %i, directory = %iquot;, flag, directory);
  • -(BOOL)isReadableFileAtPath:(NSString *)path;
    • path這個文件\文件夾是否可讀
  • -(BOOL)isWritableFileAtPath:(NSString *)path;
    • path這個文件\文件夾是否可寫
    • 系統目錄不允許寫入
  • -(BOOL)isDeletableFileAtPath:(NSString *)path;
    • path這個文件\文件夾是否可刪除
    • 系統目錄不允許刪除

7.3NSFileManager的文件訪問

  • -(NSDictionary )attributesOfItemAtPath:(NSString )path error:(NSError **)error;
    • 獲得path這個文件\文件夾的屬性
      NSFileManager *manager = [NSFileManager defaultManager]; 
      NSDictionary *dict = [manager attributesOfItemAtPath:@quot;/Users/LNJ/Desktop/lnj.txtquot; error:nil]; 
      NSLog(@quot;dit = %@quot;, dict);
  • -(NSArray )contentsOfDirectoryAtPath:(NSString )path error:(NSError **)error;
    • 獲得path的當前子路徑
  • -(NSData )contentsAtPath:(NSString )path;
    • 獲得文件內容
      NSFileManager *manager = [NSFileManager defaultManager]; 
      NSArray *paths = [manager contentsOfDirectoryAtPath:@quot;/Users/LNJ/Desktop/quot; error:nil]; 
      NSLog(@quot;paths = %@quot;, paths);
  • -(NSArray )subpathsAtPath:(NSString )path;
  • -(NSArray )subpathsOfDirectoryAtPath:(NSString )path error:(NSError **)error; - 獲得path的所有子路徑
    NSFileManager *manager = [NSFileManager defaultManager]; 
    NSArray *paths = [manager subpathsAtPath:@quot;/Users/LNJ/Desktop/quot;]; NSLog(@quot;paths = %@quot;, paths);

7.4NSFileManager的文件操作

  • -(BOOL)copyItemAtPath:(NSString )srcPath toPath:(NSString )dstPath error:(NSError **)error;
    拷貝
  • -(BOOL)moveItemAtPath:(NSString )srcPath toPath:(NSString )dstPath error:(NSError **)error;
    • 移動(剪切)
  • -(BOOL)removeItemAtPath:(NSString )path error:(NSError * )error;
    • 刪除
  • -(BOOL)createDirectoryAtPath:(NSString )path withIntermediateDirectories:(BOOL)createIntermediates attributes:(NSDictionary )attributes error:(NSError **)error;
    • 創建文件夾(createIntermediates為YES代表自動創建中間的文件夾)
      NSFileManager *manager = [NSFileManager defaultManager]; 
      BOOL flag = [manager createDirectoryAtPath:@quot;/Users/LNJ/Desktop/testquot; withIntermediateDirectories:YES attributes:nil error:nil]; 
      NSLog(@quot;flag = %iquot;, flag);
  • -(BOOL)createFileAtPath:(NSString )path contents:(NSData )data attributes:(NSDictionary *)attr;
    • 創建文件(NSData是用來存儲二進制字節數據的)
      NSString *str = @quot;lnjquot;; 
      NSData *data = http://www.tuicool.com/articles/[str dataUsingEncoding:NSUTF8StringEncoding]; NSFileManager *manager = [NSFileManager defaultManager]; 
      BOOL flag = [manager createFileAtPath:@quot;/Users/LNJ/Desktop/abc.txtquot; contents:data attributes:nil]; 
      NSLog(@quot;flag = %iquot;, flag);

八、集合對象的內存管理

8.1集合對象的內存管理

  • 當一個對象加入到集合中,那么該對象的引用計數會 1
  • 當集合被銷毀的時候,集合會向集合中的元素發送release消息
NSMutableArray *arr = [[NSMutableArray alloc] init]; 

Person *p = [[Person alloc] init]; 
NSLog(@quot;retainCount = %luquot;, [p retainCount]); 
[arr addObject:p]; 
NSLog(@quot;retainCount = %luquot;, [p retainCount]);
[p release]; 
NSLog(@quot;retainCount = %luquot;, [p retainCount]); 
[arr release];
  • 當一個對象加入到集合中,那么該對象的引用計數會 1
  • 當把一個對象從集合中移除時,會向移除的元素發送release消息
NSMutableArray *arr = [[NSMutableArray alloc] init]; 
Person *p = [[Person alloc] init]; 
NSLog(@quot;retainCount = %luquot;, [p retainCount]); 
[arr addObject:p]; 
NSLog(@quot;retainCount = %luquot;, [p retainCount]); 
[arr removeObject:p]; 
NSLog(@quot;retainCount = %luquot;, [p retainCount]); [p release]; 
[arr release];

8.2集合對象內存管理總結

  • 1.官方內存管理原則
    • 1gt; 當調用alloc、new、copy(mutableCopy)方法產生一個新對象的時候,就必須在最后調用一次release或者autorelease
    • 2gt; 當調用retain方法讓對象的計數器 1,就必須在最后調用一次release或者autorelease
  • 2.集合的內存管理細節
    • 1gt; 當把一個對象添加到集合中時,這個對象會做了一次retain操作,計數器會 1
    • 2gt; 當一個集合被銷毀時,會對集合里面的所有對象做一次release操作,計數器會-1
    • 3gt; 當一個對象從集合中移除時,這個對象會一次release操作,計數器會-1
  • 3.普遍規律
    • 1gt; 如果方法名是add\insert開頭,那么被添加的對象,計數器會 1
    • 2gt; 如果方法名是remove\delete開頭,那么被移除的對象,計數器-1

九、Copy

9.1copy基本概念

  • 什么是copy
    • Copy的字面意思是“復制”、“拷貝”,是一個產生副本的過程
  • 常見的復制有:文件復制
    • 作用:利用一個源文件產生一個副本文件
  • 特點:
    • 修改源文件的內容,不會影響副本文件
    • 修改副本文件的內容,不會影響源文件
  • OC中的copy
    • 作用:利用一個源對象產生一個副本對象
  • 特點:修改源對象的屬性和行為,不會影響副本對象
    • 修改副本對象的屬性和行為,不會影響源對象

9.2Copy的使用

  • 如何使用copy功能
    • 一個對象可以調用copy或mutableCopy方法來創建一個副本對象
      -copy : 創建的是不可變副本(如NSString、NSArray、NSDictionary)
    • mutableCopy :創建的是可變副本(如NSMutableString、NSMutableArray、NSMutableDictionary)
  • 使用copy功能的前提
    • copy : 需要遵守NSCopying協議,實現copyWithZone:方法
@protocol NSCopying
- (id)copyWithZone:(NSZone *)zone;
@end
  • 使用mutableCopy的前提
    • 需要遵守NSMutableCopying協議,實現mutableCopyWithZone:方法
@protocol NSMutableCopying
- (id)mutableCopyWithZone:(NSZone *)zone;
@end

9.2深復制和淺復制

  • 淺復制(淺拷貝,指針拷貝,shallow copy)
    • 源對象和副本對象是同一個對象
    • 源對象(副本對象)引用計數器 1,相當于做一次retain操作
    • 本質是:沒有產生新的對象
      NSString *srcStr = @quot;lnjquot;; 
      NSString *copyStr = [srcStr copy]; 
      NSLog(@quot;src = http://www.tuicool.com/articles/%p, copy = %pquot;, srcStr, copyStr);
  • 深復制(深拷貝,內容拷貝,deep copy)

    • 源對象和副本對象是不同的兩個對象
    • 源對象引用計數器不變,副本對象計數器為1(因為是新產生的)
    • 本質是:產生了新的對象
      NSString *srcStr = @quot;lnjquot;; 
      NSMutableString *copyStr = [srcStr mutableCopy]; 
      NSLog(@quot;src = http://www.tuicool.com/articles/%p, copy = %pquot;, srcStr, copyStr); 
      NSLog(@quot;src = %@, copy = %@quot;, srcStr, copyStr); 
      [copyStr appendString:@quot; coolquot;]; 
      NSLog(@quot;src = %@, copy = %@quot;, srcStr, copyStr);
      NSMutableString *srcStr = [NSMutableString stringWithFormat:@quot;lnjquot;]; 
      NSString *copyStr = [srcStr copy]; 
      [srcStr appendString:@quot; coolquot;]; 
      NSLog(@quot;src = http://www.tuicool.com/articles/%p, copy = %pquot;, srcStr, copyStr); 
      NSLog(@quot;src = %@, copy = %@quot;, srcStr, copyStr);
      NSMutableString *srcStr = [NSMutableString stringWithFormat:@quot;lnjquot;]; NSMutableString *copyStr = [srcStr mutableCopy]; 
      [srcStr appendString:@quot; coolquot;]; 
      [copyStr appendString:@quot; 520itquot;]; 
      NSLog(@quot;src = http://www.tuicool.com/articles/%p, copy = %pquot;, srcStr, copyStr); 
      NSLog(@quot;src = %@, copy = %@quot;, srcStr, copyStr);
  • 只有源對象和副本對象都不可變時,才是淺復制,其它都是深復制

    Paste_Image.png

十、copy與內存管理

10.1copy與內存管理

  • 淺拷貝
    • 原對象引用計數器 1
    • 必須對原對象進行釋放
      har *cstr = quot;this is a c stringquot;;
      NSString *str1 = [[NSString alloc] initWithUTF8String:cstr];
      NSLog(@quot;str = %luquot;, [str1 retainCount]);
      NSString *str2 = [str1 copy];
      NSLog(@quot;str = %luquot;, [str1 retainCount]);
      [str2 release];必須做一次release
  • 深拷貝
    • 必須釋放新對象
      char *cstr = quot;this is a c stringquot;;
      NSString *str1 = [[NSString alloc] initWithUTF8String:cstr];
      NSLog(@quot;str = %luquot;, [str1 retainCount]);
      NSMutableString *str2 = [str1 mutableCopy];
      NSLog(@quot;str = %luquot;, [str1 retainCount]);
      [str2 release]; // 必須做一次release

十一、property中的copy關鍵字

11.1@property中的copy的作用

  • 防止外界修改內部的值
    @interface Person : NSObject 
    @property (nonatomic, retain) NSString *name; 
    @end
    NSMutableString *str = [NSMutableString stringWithFormat:@quot;lnjquot;]; 
    Person *p = [[Person alloc] init]; 
    p.name = str; 
    // person中的屬性會被修改 
    [str appendString:@quot; coolquot;]; 
    NSLog(@quot;name = %@quot;, p.name);
  • 防止訪問對象對象已經釋放
    • 不用copy情況
      Person *p = [[Person alloc] init];
      p.name = @quot;lnjquot;;
      Dog *d = [[Dog alloc] init];
      d.age = 10;
      NSLog(@quot;retainCount = %luquot;, [d retainCount]);// 1
      p.pBlock = ^{ 
        // 報錯, 調用之前就銷毀了 
      NSLog(@quot;age = %dquot;, d.age);
      };
      [d release]; // 0
      p.pBlock();
      [p release];
    • 用copy情況
      Person *p = [[Person alloc] init]; 
      p.name = @quot;lnjquot;; 
      Dog *d = [[Dog alloc] init]; 
      d.age = 10; 
      NSLog(@quot;retainCount = %luquot;, [d retainCount]); // 1 
      p.pBlock = ^{ 
        // 會對使用到的外界對象進行一次retain 
        NSLog(@quot;age = %dquot;, d.age); 
        NSLog(@quot;retainCount = %luquot;, [d retainCount]); // 1
      }; 
      [d release]; // 1 
      p.pBlock(); 
      [p release];

11.2@property內存管理策略選擇

  • 非ARC

    • 1gt; copy : 只用于NSString\block
    • 2gt; retain : 除NSString\block以外的OC對象
    • 3gt; assign :基本數據類型、枚舉、結構體(非OC對象),當2個對象相互引用,一端用retain,一端用assign
  • ARC

    • 1gt; copy : 只用于NSString\block
    • 2gt; strong : 除NSString\block以外的OC對象
    • 3gt; weak : 當2個對象相互引用,一端用strong,一端用weak
    • 4gt; assgin : 基本數據類型、枚舉、結構體(非OC對象)

十二、自定義的類實現copy操作

12.1自定義類實現copy操作

  • 讓類遵守NSCopying協議
  • 實現 copyWithZone:方法,在該方法中返回一個對象的副本即可。
  • 在copyWithZone方法中,創建一個新的對象,并設置該對象的數據與現有對象一致, 并返回該對象.

    zone: 表示空間,分配對象是需要內存空間的,如果指定了zone,就可以指定 新建對象對應的內存空間。但是:zone是一個非常古老的技術,為了避免在堆中出現內存碎片而使用的。在今天的開發中,zone幾乎可以忽略

  • 無父類實現

    -(id)copyWithZone(NSZone *)zone{ 
       CustomMode *custom = [[[self class] copyWithZone:zone] init]; 
       Custom -gt;_a = [_a copyWithZone:zone]; 
       Custom -gt; _c = _c;//不是對象的 直接賦值 
       Return custom;
    }
  • 有父類實現
    • 不調用父類方法, 無法拷貝父類中繼承的屬性
    • 不重新父類copyWithZone, 無法拷貝本來中的特有屬性
      -(id)copyWithZone(NSZone *)zone{
       CustomModel *custom = [super copyWithZone:zone];
       ….
       Return custom;
      }

十三、單例設計模式

13.1單例模式概念

  • 什么是單例模式:(辛格爾頓)
    • 單例模式的意圖是是的類的對象成為系統中唯一的實例,#56319;#56320;供一個訪問點,供客戶類共享資源。
  • 什么情況下使用單例?
    • 1,類只能有一個實例,而且必須從一個為人熟知的訪問點對其進行訪問,比如工廠方法。
    • 2,這個唯一的實例只能通過子類化進行擴展,而且擴展的對象不會破壞客戶端代碼。
  • 單例設計模式的要點:
    • (1)某個類只能有一個實例。
    • (2)他必須自行創建這個對象
    • (3)必須自行向整個系統#56319;#56320;供這個實例;
    • (4)為了保證實例的唯一性,我們必須將
    • (5)這個方法必須是一個靜態類

13.2簡單的單例模式實現

#define interfaceSingleton(name)  (instancetype)share##name

#if __has_feature(objc_arc)
// ARC
  (instancetype)share##name \
{ \
name *instance = [[self alloc] init]; \
return instance; \
} \
static name *_instance = nil; \
  (instancetype)allocWithZone:(struct _NSZone *)zone \
{ \
static dispatch_once_t onceToken; \
dispatch_once(amp;onceToken, ^{ \
_instance = [[super allocWithZone:zone] init]; \
}); \
return _instance; \
} \
- (id)copyWithZone:(NSZone *)zone{ \
return _instance; \
} \
- (id)mutableCopyWithZone:(NSZone *)zone \
{ \
return _instance; \
}
#else

// MRC
#define implementationSingleton(name) \
  (instancetype)share##name \
{ \
name *instance = [[self alloc] init]; \
return instance; \
} \
static name *_instance = nil; \
  (instancetype)allocWithZone:(struct _NSZone *)zone \
{ \
static dispatch_once_t onceToken; \
dispatch_once(amp;onceToken, ^{ \
_instance = [[super allocWithZone:zone] init]; \
}); \
return _instance; \
} \
- (id)copyWithZone:(NSZone *)zone{ \
return _instance; \
} \
- (id)mutableCopyWithZone:(NSZone *)zone \
{ \
return _instance; \
} \
- (oneway void)release \
{ \
} \
- (instancetype)retain \
{ \
return _instance; \
} \
- (NSUInteger)retainCount \
{ \
return MAXFLOAT; \
}
#endif

代碼鏈接

百度云:

鏈接: https://pan.baidu.com/s/1eSx9GT8 密碼: p4fp


Tags: NSDictionary

文章來源:http://www.jianshu.com/p/77431ccf15ac


ads
ads

相關文章
ads

相關文章

ad