GeekBand - Objective-C學(xué)習(xí)筆記(二)

字符串處理NSString

認(rèn)識字符串NSString

  • NSString是一個Unicode編碼治力、16位字符的字符序列
  • NSString被定義為類价捧,引用類型,拷貝時具有引用語義。
  • 初始化方法:字面初始化、初始化器逃贝、工廠方法
  • NSSring擁有恒定性谣辞,所有的操作無法更改字符串本身,如果有更改沐扳,都是返回新值的形式泥从。
  • NSString擁有共享機制,引用計數(shù)管理對其有特殊的管理規(guī)則

oc的NSString和c語言的區(qū)別

  • NSString是一個oc對象,OC字符串是一個字符串對象,字符串常量需要用@""包含沪摄。
  • C語言字符串是一個數(shù)據(jù)類型躯嫉,用""包含
  • OC中的字符串以Unicode編碼,C語言的字符串以字符的ASCII碼形式杨拐。
  • 打印OC字符串用%@,打印C語言字符串用%s

三種初始化方法:

NSString *str1 = @"Hello World!";
//字面常量祈餐,加@才是OC的字符串

NSString *str2 = [[NSString alloc]initWithCString:"Hello World!" encoding:NSUTF8StringEncoding];
//用內(nèi)存分配搭配初始化器

NSString *str3 = [NSString stringWithCString:"Hello World!" encoding:NSUTF8StringEncoding];
//工廠方法,是一個類方法哄陶,通過類方法內(nèi)部返回一個對象

NSString *str4= @"Hello World!";

上面運行結(jié)果str1str4的存放地址是一樣的(共享機制)帆阳。只要用字面常量創(chuàng)立的字符串才會共享

  • 判斷相等isEqualToString值是否相等
  • str1 == str2比較指針(引用)是否相等

NSMutableString

  • NSMutableString具有可變性,NSString具有恒定性
  • NSMutableString不具有共享機制,NSString具有共享機制
  • NSMutableString不是在原有內(nèi)存上直接增長,而是重新分配一個更大或更小的緩存容量存放字符
  • NSMutableString是NSString的子類
NSMutableString *mustr1 = [NSMutableString stringWithString: @"Hello,World!"];
//工場方法停止初始化

NSLog(@"mustr1:%p",mustr1);

NSMutableString *mustr2 = [NSMutableString stringWithString: @"Hello,World!"];
NSLog(@"mustr2:%p",mustr2);

NSString *str5=mustr1;

NSLog(@"str5:%@",str5);
[mustr1 appendString:@" Very Good!"];
NSLog(@"str5:%@",str5);
//NSMutableString的改動奕筐,使他的父類NSString發(fā)作了改動

存在的固有問題:通過mustr1的改動,使的父類NSString發(fā)生了改變(而上面提到NSString具有不變性)

NSMutableString的內(nèi)存機制

緩存容量與增長

  • 字符串初始化后,會分配一個緩存容量capacity,其長度一般大于實際的字符串?dāng)?shù)量,當(dāng)然也可以自己給它一個緩存容量
  • 當(dāng)字符串增長時,如果實際需求大于capacity,其capacity會以兩倍的方式指數(shù)增長,代價是:
    • 分配新的堆內(nèi)存2*capacity
    • 將原來堆內(nèi)存的內(nèi)容拷貝到新內(nèi)存,
    • 釋放原來堆內(nèi)存
  • 最佳實踐:估計好capacity,預(yù)先分配好一定容量,避免以后capacity的增長

常見操作

  • NSString常見操作
    • 訪問字符串:獲取字符串变骡、字符串長度离赫、字面量、大小寫轉(zhuǎn)換
    • 查詢字符串:定位子串塌碌、獲取子串渊胸、是否包含子串、查詢字符集
    • 其他操作:比較字符串台妆、替換字符串翎猛、分解字符串
  • NSMutableString:
    • 添加字符串 [mustr3 appendString:@"Hello Objective"];
    • 刪除字符串
    • 修改字符串

集合類型

數(shù)組

  • 數(shù)組是一個有序的元素序列,支持隨機存取接剩。索引從0開始切厘,索引訪問越界會拋出運行時異常。注意與C語言數(shù)組不同懊缺。
NSArray *array1=[NSArray arrayWithObjects:@"Shanghai",@"Beijing",@"New York",@"Paris", nil];
NSArray *array2=[[NSArray alloc] initWithObjects:@"Shanghai",@"Beijing",@"New York",@"Paris", nil];
NSArray *array3=@[@"Shanghai",@"Beijing",@"New York",@"Paris"];
  • 可以通過count方法訪問數(shù)組中元素的個數(shù)疫稿,返回一個NSInteger.

  • NSArray被定義為class,引用類型鹃两,拷貝時具有引用語義遗座。

  • NSArray的元素必須是對象,即NSObject的子類俊扳。

    • 如果為基本數(shù)值類型途蒋,須要用NSNumber 封裝為對象類型后,才能放入數(shù)組中馋记。
    NSInteger number=100;
    NSNumber *numberObject1= [NSNumber numberWithInteger:number ];
    
    • 如果為C語言結(jié)構(gòu)類型号坡,須要用NSValue 封裝為對象類型后懊烤,才能放入數(shù)組中。
    NSValue *pointObject = [NSValue value:&point withObjCType:@encode(Point)];
    
    • 數(shù)組元素可以是不同對象類型筋帖,可能會有類型不安全奸晴。
  • NSArray具有常量性:長度和元素指針都不能更改。但指針指向的對象內(nèi)部可以更改日麸。

NSArray內(nèi)存模型

NSArray內(nèi)存模型

數(shù)組遍歷

  • 最快 for in 直接訪問內(nèi)存寄啼,優(yōu)化索引檢查,比for循環(huán)快5-10倍
  • 較慢 NSEnumeration遍歷迭代的方法
NSEnumerator *enumerator = [array5 objectEnumerator];
BLNPoint* item;
while (item = [enumerator nextObject]){
    item.x++;
    item.y++;
}
  • for循環(huán)最慢

數(shù)組查找的方法

  • indexOfObject 查找是否存在“值相等”的對象(類型需要實現(xiàn)isEqual)代箭。

    NSUInteger index1=[array5 indexOfObject:target];

  • indexOfObjectIdenticalTo 查找是否存在“指針想等”的對象墩划。

    NSUInteger index2=[array5 indexOfObjectIdenticalTo:p3];

  • objectAtIndex:方法訪問數(shù)組中的單個元素,返回給定索引處的單個元素嗡综。

  • lastObject:方法返回數(shù)組的最后一個元素乙帮。

數(shù)組排序

不改變原數(shù)組(常量性),返回新數(shù)組极景。

NSArray* sortArray1=[array1 sortedArrayUsingSelector:@selector(compare:)];

使用NSMutableArray

  • NSMutableArray支持更改數(shù)組長度和元素指針察净,為NSArray的子類。
  • capacity與NSMuatbalString一樣
  • 估計好capacity預(yù)先分配一定容量盼樟,避免以后增長
  • 盡量避免使用insertObject:atIndex:removeObjectAtIndex:等操作氢卡,因為會改變數(shù)組元素序列,涉及大量內(nèi)存拷貝操作晨缴,代價高译秦。

set

  • NSSet 是一個無序的集合,其存儲的對象不能重復(fù)击碗。
  • 常量性:長度和元素指針都不能更改筑悴。但指針指向的對象內(nèi)部可以更改。
  • 創(chuàng)建NSMutableSet時用initWithCapacity提前設(shè)置capacity稍途。

Dictionary字典類型

  • NSDictionary是一個存儲key-value的無序集合阁吝,key唯一,value可重復(fù)械拍。

  • NSDictionary被定義為class求摇,引用類型,拷貝時具有引用意義殊者。

  • 常量集合 NSDictionary,可變集合: NSMutableDictionary:

  • 常量性:長度和元素指針都不能更改与境。但指針指向的對象內(nèi)部可以更改。

  • 創(chuàng)建NSMutableDictionary 時用initWithCapacity 提前設(shè)置capacity

  • 支持Fast Enumeration和NSEnumerator遍歷猖吴,前者較快摔刁。

  • 排序方法

    • sortedArrayUsingSortDescriptors:
    • sortedArrayUsingFunction:context:
    • sortedArrayUsingSelector:

其他類型

  • NSMumber類是用來封裝基本數(shù)據(jù)類型。
    • 裝箱(boxing)是一個基本類型的數(shù)據(jù)封裝成對象的過程
    • 開箱(unboxing)從對象中提取基本類型的數(shù)據(jù)
+(NSNumber *) numberWithChar:(char) value;
+(NSNumber *) numberWithInt:(int) value;
+(NSNumber *) numberWithFloat:(float) value;
+(NSNumber *) numberWithBool:(BOOL) value;
//可以通過下面的實例方法重新獲得基本類型數(shù)據(jù):
-(char) charValue;
-(int) intValue;
-(float) floatValue;
-(BOOL) boolValue;
-(NSString *) stringValue;

  • NSValue可以封裝任意值海蔽,可以使用NSValue將結(jié)構(gòu)體放入NSArray和NSDictionary中共屈。
    +(NSValue *) valueWithBytes: (const void *) value objCType:(const char *) type;

自動引用計數(shù)ARC

ARC

  • 自動引用計數(shù)(Automatic Reference Counting)是Objective-C默認(rèn)的內(nèi)存管理機制绑谣,其針對堆上的對象,由編譯器自動生成操作引用計數(shù)的指令(retain或release)拗引,來管理對象的創(chuàng)建與釋放借宵。
  • 哪些對象受ARC管理:
    1. OC對象指針
    2. Block指針
    3. 使用attribute((NSObject))定義的typedef
  • 哪些對象不受ARC管理:
    1. 值類型(簡單值類型,C語言struct)
    2. 使用其他方式分配的堆對象(如使用malloc分配)
    3. 非內(nèi)存資源

引用計數(shù)管理

  • 新創(chuàng)建(使用alloc矾削,new壤玫,copy等)一個引用類型對象,引用計數(shù)為1
    BLNPoint *p1 = [[BLNPoint alloc]init];
    BLNRectangle *rect = [[BLNRectangle alloc]init];
  • 對象引用計數(shù)增1——retain操作:
    1. 將對象引用賦值給其他變量或常量哼凯。
      BLNPoint *p2 = p1;
    2. 將對象引用賦值給其他屬性或?qū)嵗兞俊?br> rect.center = p1;
    3. 將對象傳遞給函數(shù)參數(shù)欲间,或者返回值。
      draw(p1);
    4. 將對象加入集合中断部。
      array=[[NSMutableArray alloc]initWithCapacity:10];
      [array addObject:p1];
  • 對象引用計數(shù)減1——release操作:
    1. 將局部變量或全局變量賦值為nil或其他值猎贴。
      p1 = nil;
      p2 = nil;
    2. 將屬性賦值為nil或其他值。
      rect.center = nil;
    3. 實例屬性所在的對象被釋放蝴光。
    4. 參數(shù)或局部變量離開函數(shù)她渴。
    5. 將對象從集合中刪除。
      [array removeObjectAtIndex:0];
  • 引用計數(shù)變?yōu)?時蔑祟,內(nèi)存自動被釋放

自動釋放池(Autorelease Pool)

  • release會導(dǎo)致對象立即釋放趁耗。如果頻繁對對象進行release,可能會造成瑣碎的內(nèi)存管理負(fù)擔(dān)做瞪。autorelease可以將release的調(diào)用延遲到自動釋放池被釋放時对粪。

  • 推薦使用自動釋放池(AutoreleasePool)Block右冻,當(dāng)其結(jié)束時装蓬,所有接受autorelease消息的對象將會被立即釋放(即發(fā)送release消息)。

  • AppKit和UIKit框架在處理每一次事件循環(huán)迭代時纱扭,都會將其放入一個Autorelease Pool中牍帚。大多數(shù)情況,無需程序員干預(yù)乳蛾。

  • 什么時候需要手工管理Autorelease Pool

    • 編寫的程序不基于UI框架暗赶,如命令行程序。
    • 在循環(huán)中創(chuàng)建大量臨時對象肃叶,需要更早地釋放蹂随,避免臨時對象聚集導(dǎo)致內(nèi)存峰值過大。
    • 在主線程之外創(chuàng)建新的線程因惭,在新線程開始執(zhí)行處岳锁,需要創(chuàng)建自己的Autorelease Pool.
    • 可以嵌套使用Autorelease Pool.

類型合同:協(xié)議

認(rèn)識協(xié)議 Protocol

  • 協(xié)議:類型的合同約定,只描述外部接口蹦魔,不提供具體實現(xiàn)激率。
  • 協(xié)議可以包含以下成員:
    1. 屬性
    2. 實例方法
    3. 類方法
    4. 初始化器-不常用
    5. 析構(gòu)器-不常用
@protocol Drawable
@property  NSInteger x;
@property  NSInteger y;
-(void)draw;
+(void)createShape;
@optional
-(void)moveToX:(NSInteger)x withY:(NSInteger)y;
@end
  • 協(xié)議中無法包含實例變量成員
  • 協(xié)議中定義的屬性本質(zhì)上是訪問器方法咳燕,編譯器不會合成實例變量。

協(xié)議關(guān)鍵字

  • @required:表明其后所有的方法是實現(xiàn)該協(xié)議的必須方法乒躺。協(xié)議的默認(rèn)行為招盲,如果沒有指定@required ,協(xié)議中聲明的所有方法都默認(rèn)是必須實現(xiàn)的嘉冒。
  • @optional:表明實現(xiàn)類時可以選擇性實現(xiàn)該方法曹货。實現(xiàn)了該協(xié)議的類可以選擇不實現(xiàn)任何在@optional后所有聲明的方法。

使用協(xié)議

  • 一個類遵守協(xié)議健爬,需要實現(xiàn)協(xié)議約定的的所有@required成員
@interface BLNPoint : NSObject<Drawable>
@implementation BLNPoint
-(void)draw
{
    NSLog(@"%@",self);
}
+(void)createShape{
    NSLog(@"Create a Shape");
}
-(void)moveToX:(NSInteger)x withY:(NSInteger)y
{
    self.x = x;
    self.y = y;
}
@end
  • 協(xié)議中的屬性須在實現(xiàn)類的.h文件中聲明(編譯器合成實例變量需要)控乾。
@property  NSInteger x;
@property  NSInteger y;
  • 注意編譯警告?:
    • 遵守協(xié)議后卻沒有實現(xiàn)必選協(xié)議方法時,會出現(xiàn)警告提示娜遵。
    • 協(xié)議類型變量被賦值非協(xié)議類型對象時蜕衡,會出現(xiàn)警告提示。
  • 協(xié)議本質(zhì)上是一種類型设拟,可以作為聲明類型慨仿,但不能創(chuàng)建實例。
  • 檢查協(xié)議類型
    -->使用conformsToProtocol:檢查對象是否實現(xiàn)了協(xié)議纳胧。
void process2(id obj){
    if ([obj conformsToProtocol:@protocol(AProtocol) ]) {
        [obj methodA];
    }
}

更多協(xié)議形式

  • 協(xié)議繼承
    • 一個協(xié)議可以繼承一個或多個協(xié)議
    • 實現(xiàn)子協(xié)議的類型镰吆,也必須實現(xiàn)父協(xié)議中約定的成員
  • 協(xié)議組合
    • 可以使用protocol<A,B,...>來組合多個協(xié)議
    • 實現(xiàn)組合協(xié)議的類型,必須實現(xiàn)組合協(xié)議中的每一個協(xié)議
  • 可選協(xié)議
    • 協(xié)議的 某些成員可以定義為optional跑慕,不必實現(xiàn)
  • 常用協(xié)議
    • NSObject:包含對象的常用操作万皿,想等、字符串表示核行、哈希
    • NSCopying:支持復(fù)制的類型必須遵守該協(xié)議
    • NSFastEnumeration:實現(xiàn)快速枚舉 for-in的類型采用
    • NSCoding協(xié)議:支持將對象圖進行編碼/解碼以支持對象序列化

類別與擴展

類別Category

  • 類別支持在沒有源代碼的情況下牢硅,基于某些特定的場合,為一個類增加功能芝雪。
  • 可以添加
    • 類方法
    • 實例方法
    • 重寫基類方法
  • 不能添加
    • 屬性
    • 實例變量
    • 已存在的同名方法
@interface BLNPoint(Drawing)
-(void)draw;
-(void)setWeight:(NSInteger)weight;
-(NSInteger)weight;
@end
  • 命名規(guī)范
    • 文件名:類名+擴展方法减余,如 NSString+Drawing.h/.m

使用場景

  • 適合在沒有源代碼的情況下,向已經(jīng)封裝的類中添加方法惩系。
    @interface NSString(Drawing)
  • 為一個類在某些特殊場景下增加功能
@interface BLNPoint(Drawing)
-(void)draw;
-(void)setWeight:(NSInteger)weight;
-(NSInteger)weight;
@end
  • 對于復(fù)雜的大型文件分割實現(xiàn)位岔。
  • 添加類別
    1. 自己創(chuàng)建的類
    2. 系統(tǒng)的類
    3. 第三方庫

擴展extension

  • 擴展支持在編譯時,有類的源代碼的前提下堡牡,向類添加功能抒抬。可以將擴展看做匿名的類別晤柄。
  • 接口定義在.m文件中@implementation前聲明擦剑,實現(xiàn)代碼仍然在@implementation內(nèi)實現(xiàn)。
@interface Circle ()
{
    NSString * _name;
}
@property (readwrite )NSInteger  radius;//修改讀寫屬性
@property  NSInteger center;//添加屬性
-(float)getDiameter;//實例方法
+(void)process:(Circle*) circle;//類方法
@end
  • 擴展支持添加以下成員:
    1. 添加屬性。
    2. 添加實例成員抓于。
    3. 添加類方法做粤。
    4. 添加實例方法。
    5. 改寫屬性的讀寫屬性捉撮。

使用擴展

  • 擴展實現(xiàn)的成員都只能在.m實現(xiàn)文件內(nèi)部訪問怕品,在類外不可以直接訪問。
  • 擴展的主要用途在于信息隱藏巾遭,隱藏一些外部無需訪問肉康、而內(nèi)部實現(xiàn)又需要使用的屬性、方法:
    • 類的主接口主要用于“對類外公開”的接口灼舍。
    • 類的擴展接口用于“對類內(nèi)可見”的接口吼和。

OC泛型

  • 泛型是程序設(shè)計語言的一種特性,他主要是為了限制類型的骑素,比如OC中的數(shù)組炫乓,你可以限制他里面裝的是NSString類型。

  • 泛型的基本格式

    • 泛型聲明格式:在聲明類的時候,在類型后面<泛型名稱>
    • 泛型定義格式:放在限制的類型后面<類型>
  • 泛型的好處

    • 提高程序員開發(fā)規(guī)范献丑,讓程序員一眼就可以看出該使用什么類型
    • 限制類型末捣,不允許裝入其它的類型
    • 可以使用點語法
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市创橄,隨后出現(xiàn)的幾起案子箩做,更是在濱河造成了極大的恐慌,老刑警劉巖妥畏,帶你破解...
    沈念sama閱讀 217,406評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件邦邦,死亡現(xiàn)場離奇詭異,居然都是意外死亡醉蚁,警方通過查閱死者的電腦和手機燃辖,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評論 3 393
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來馍管,“玉大人郭赐,你說我怎么就攤上這事薪韩∪贩校” “怎么了?”我有些...
    開封第一講書人閱讀 163,711評論 0 353
  • 文/不壞的土叔 我叫張陵俘陷,是天一觀的道長罗捎。 經(jīng)常有香客問我,道長拉盾,這世上最難降的妖魔是什么桨菜? 我笑而不...
    開封第一講書人閱讀 58,380評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上倒得,老公的妹妹穿的比我還像新娘泻红。我一直安慰自己,他們只是感情好霞掺,可當(dāng)我...
    茶點故事閱讀 67,432評論 6 392
  • 文/花漫 我一把揭開白布谊路。 她就那樣靜靜地躺著,像睡著了一般菩彬。 火紅的嫁衣襯著肌膚如雪缠劝。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,301評論 1 301
  • 那天骗灶,我揣著相機與錄音惨恭,去河邊找鬼。 笑死耙旦,一個胖子當(dāng)著我的面吹牛脱羡,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播免都,決...
    沈念sama閱讀 40,145評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼轻黑,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了琴昆?” 一聲冷哼從身側(cè)響起氓鄙,我...
    開封第一講書人閱讀 39,008評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎业舍,沒想到半個月后抖拦,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,443評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡舷暮,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,649評論 3 334
  • 正文 我和宋清朗相戀三年态罪,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片下面。...
    茶點故事閱讀 39,795評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡复颈,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出沥割,到底是詐尸還是另有隱情耗啦,我是刑警寧澤,帶...
    沈念sama閱讀 35,501評論 5 345
  • 正文 年R本政府宣布机杜,位于F島的核電站帜讲,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏椒拗。R本人自食惡果不足惜似将,卻給世界環(huán)境...
    茶點故事閱讀 41,119評論 3 328
  • 文/蒙蒙 一获黔、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧在验,春花似錦玷氏、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至侦厚,卻和暖如春耻陕,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背刨沦。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評論 1 269
  • 我被黑心中介騙來泰國打工诗宣, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人想诅。 一個月前我還...
    沈念sama閱讀 47,899評論 2 370
  • 正文 我出身青樓召庞,卻偏偏與公主長得像,于是被迫代替她去往敵國和親来破。 傳聞我的和親對象是個殘疾皇子篮灼,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,724評論 2 354

推薦閱讀更多精彩內(nèi)容