【OC梳理】Copy顾瞪、KVC舔庶、KVO

Copy

OC中copy的作用是:利用一個源對象產(chǎn)生一個副本對象,它們之間不會相互影響陈醒。

關(guān)于深拷貝與淺拷貝

深拷貝是指對對象的具體內(nèi)容進(jìn)行復(fù)制惕橙,并占用新的內(nèi)存空間,淺拷貝就是對內(nèi)存地址的復(fù)制钉跷。
自定義的類如果要深拷貝弥鹦,需要遵循 NSCopying, NSMutableCopying 協(xié)議,在協(xié)議方法中實(shí)現(xiàn)copy相關(guān)方法爷辙。
數(shù)組的深拷貝彬坏,也需要自己將所有對象拷貝一份再添加。
下面的代碼:

    NSMutableArray *array = [NSMutableArray array];
    [array addObject:[NSObject new]];
    [array addObject:[NSObject new]];
    [array addObject:[NSObject new]];
    [array addObject:[NSObject new]];
    NSArray *copyArray = [array copy];
    NSArray *copycopyArray = [copyArray copy];
    NSMutableArray *mutACopy = [array mutableCopy];
    NSMutableArray *arrCopy = [copyArray mutableCopy];
    NSLog(@"原來的數(shù)組            :%p ----> %p",&array,*&array);
    NSLog(@"copy的數(shù)組           :%p ----> %p",&copyArray,*&copyArray);
    NSLog(@"copycopy的數(shù)組       :%p ----> %p",&copycopyArray,*&copycopyArray);
    NSLog(@"mutableCopy原來的數(shù)組 :%p ----> %p",&mutACopy,*&mutACopy);
    NSLog(@"mutableCopy copy的數(shù)組:%p ----> %p",&arrCopy,*&arrCopy);

輸出的結(jié)果如下:

... Demo[11327:4606426] 原來的數(shù)組            :0x7ffee226d9a0 ----> 0x60400044a9e0
... Demo[11327:4606426] copy的數(shù)組           :0x7ffee226d998 ----> 0x60400044aa10
... Demo[11327:4606426] copycopy的數(shù)組       :0x7ffee226d990 ----> 0x60400044aa10
... Demo[11327:4606426] mutableCopy原來的數(shù)組 :0x7ffee226d988 ----> 0x60400044fcc0
... Demo[11327:4606426] mutableCopy copy的數(shù)組:0x7ffee226d980 ----> 0x60400044fcf0

打斷點(diǎn)可以看到所有的Array中的元素的地址都是相同的膝晾,并沒有進(jìn)行復(fù)制栓始,并從輸出結(jié)果看出:

copy的對象為MutableArray時,會有一個新的指針指向新的內(nèi)存地址(新的Array對象)血当。
copy的對象為Array時幻赚,會有一個新的指針指向原來的內(nèi)存地址(原來的Array對象)。
mutableCopy的對象為MutableArray時臊旭,會有一個新的指針指向新的內(nèi)存地址(新的MutableArray對象)落恼。
mutableCopy的對象為Array時,會有一個新的指針指向新的內(nèi)存地址(新的MutableArray對象)离熏。

參考文章:
Objective-C中的淺拷貝和深拷貝
OC數(shù)組中的深拷貝

KVC

KVC(Key Valued Coding)佳谦,鍵值編碼,即常說的反射機(jī)制滋戳,是在運(yùn)行狀態(tài)中钻蔑,對于任意一個類啥刻,都能夠知道這個類的所有屬性和方法;對于任意一個對象矢棚,都能夠調(diào)用它的任意一個方法和屬性郑什,進(jìn)行屬性的動態(tài)讀寫府喳。
對于某些private屬性蒲肋,如果使用KVC進(jìn)行修改,這就破壞了類的封裝性(當(dāng)然了有些情況不得不使用KVC進(jìn)行修改)钝满。

  • KVC的主要用途是ORM映射,就是dictionary與model的互轉(zhuǎn)兜粘。

常用方法

//獲取值的方法
valueForKey:            //傳入NSString屬性的名字。
valueForKeyPath:        //傳入NSString屬性的路徑弯蚜,xx.xx形式孔轴。
valueForUndefinedKey    //它的默認(rèn)實(shí)現(xiàn)是拋出異常,可以重寫這個函數(shù)做錯誤處理碎捺。

修改值的方法
setValue:forKey:
setValue:forKeyPath:
setValue:forUndefinedKey:

使用KVC實(shí)現(xiàn)ORM

假定有一個商品model路鹰,其定義屬性如下:

@property (nonatomic,copy) NSString * goodsId;      //商品ID
@property (nonatomic,copy) NSString * coverImage;   //封面
@property (nonatomic,copy) NSString * shopPrice;    //商城價(零售價)
@property (nonatomic,copy) NSString * sales;        //銷量
//...

服務(wù)器返回的字符串為:

{
  "goods_id":"7",
  "cover_image":"http://www.nenyimall.com/products/H6200IFLO.jpg",
  "shop_price":"¥15.00",
  "sales":"139",
  ...
}

其中有3個字段的key與我們定義的屬性名有區(qū)別,這時候收厨,只需重寫下面兩個方法:

-(void)setValue:(id)value forUndefinedKey:(NSString *)key{
    if ([key isEqualToString:@"goods_id"]) {
        [self setValue:value forKey:@"goodsId"];
    }else
    if ([key isEqualToString:@"cover_image"]) {
        [self setValue:value forKey:@"coverImage"];
    }else
    if ([key isEqualToString:@"shop_price"]) {
        [self setValue:value forKey:@"shopPrice"];
    }
}

-(id)valueForUndefinedKey:(NSString *)key{
    id result = nil;
    if ([key isEqualToString:@"goods_id"]) {
        result = [self valueForKey:@"goodsId"];
    }else
    if ([key isEqualToString:@"cover_image"]) {
        result = [self valueForKey:@"coverImage"];
    }else
    if ([key isEqualToString:@"shop_price"]) {
        result = [self valueForKey:@"shopPrice"];
    }
    return result;
}

然后就可以使用setValuesForKeysWithDictionary:將dictionary轉(zhuǎn)換為model晋柱;
使用dictionaryWithValuesForKeys:將屬性轉(zhuǎn)換為dictionary。
參考文章:
iOS開發(fā)-OC篇-KVC詳解

KVO

KVO(Key Valued Observer)诵叁,鍵值觀察雁竞,是使用獲取其他對象的特定屬性變化的通知機(jī)制。所有NSObject的子類都支持這個機(jī)制拧额。

常用語法

/**
 創(chuàng)建一個觀察者
 @param observer 觀察者
 @param keyPath 被觀察的屬性
 @param options 傳遞給接收者的值的類型 NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld
 @param context 上下文碑诉,可用于區(qū)分注冊者
 */
[被觀察對象 addObserver:<#(nonnull NSObject *)#> forKeyPath:<#(nonnull NSString *)#> options:<#(NSKeyValueObservingOptions)#> context:<#(nullable void *)#>];

/**
 觀察者的回調(diào)方法
 @param keyPath 被觀察的屬性
 @param object 被觀察的屬性值
 @param change 變化的記錄
 @param context 上下文
 */
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
  //do something
}

/**
 移除觀察者
 @param observer 觀察者
 @param keyPath 被觀察的屬性
 */
[被觀察對象 removeObserver:<#(nonnull NSObject *)#> forKeyPath:<#(nonnull NSString *)#>];

局限性

父類和子類同時存在KVO時(監(jiān)聽同一個對象的同一個屬性),很容易出現(xiàn)對同一個keyPath進(jìn)行兩次removeObserver操作侥锦,從而導(dǎo)致程序crash进栽。要避免這個問題,就需要區(qū)分出KVO是self注冊的恭垦,還是superClass注冊的快毛,我們可以在 -addObserver:forKeyPath:options:context:和-removeObserver:forKeyPath:context這兩個方法中傳入不同的context進(jìn)行區(qū)分。

參考文章:
OC中KVO的基本概念和使用方法
iOS開發(fā)-KVO的奧秘
iOS下KVO使用過程中的陷阱

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末署照,一起剝皮案震驚了整個濱河市祸泪,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌建芙,老刑警劉巖没隘,帶你破解...
    沈念sama閱讀 211,194評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異禁荸,居然都是意外死亡右蒲,警方通過查閱死者的電腦和手機(jī)阀湿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來瑰妄,“玉大人陷嘴,你說我怎么就攤上這事〖渥” “怎么了灾挨?”我有些...
    開封第一講書人閱讀 156,780評論 0 346
  • 文/不壞的土叔 我叫張陵,是天一觀的道長竹宋。 經(jīng)常有香客問我劳澄,道長,這世上最難降的妖魔是什么蜈七? 我笑而不...
    開封第一講書人閱讀 56,388評論 1 283
  • 正文 為了忘掉前任秒拔,我火速辦了婚禮,結(jié)果婚禮上飒硅,老公的妹妹穿的比我還像新娘砂缩。我一直安慰自己,他們只是感情好三娩,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,430評論 5 384
  • 文/花漫 我一把揭開白布庵芭。 她就那樣靜靜地躺著,像睡著了一般尽棕。 火紅的嫁衣襯著肌膚如雪喳挑。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,764評論 1 290
  • 那天滔悉,我揣著相機(jī)與錄音伊诵,去河邊找鬼。 笑死回官,一個胖子當(dāng)著我的面吹牛曹宴,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播歉提,決...
    沈念sama閱讀 38,907評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼笛坦,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了苔巨?” 一聲冷哼從身側(cè)響起版扩,我...
    開封第一講書人閱讀 37,679評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎侄泽,沒想到半個月后礁芦,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,122評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,459評論 2 325
  • 正文 我和宋清朗相戀三年柿扣,在試婚紗的時候發(fā)現(xiàn)自己被綠了肖方。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,605評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡未状,死狀恐怖俯画,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情司草,我是刑警寧澤艰垂,帶...
    沈念sama閱讀 34,270評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站翻伺,受9級特大地震影響材泄,放射性物質(zhì)發(fā)生泄漏沮焕。R本人自食惡果不足惜吨岭,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,867評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望峦树。 院中可真熱鬧辣辫,春花似錦、人聲如沸魁巩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽谷遂。三九已至葬馋,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間肾扰,已是汗流浹背畴嘶。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留集晚,地道東北人窗悯。 一個月前我還...
    沈念sama閱讀 46,297評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像偷拔,于是被迫代替她去往敵國和親蒋院。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,472評論 2 348

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

  • 轉(zhuǎn)自 iOS 面試常見問題最全梳理 序言 目前形勢莲绰,參加到iOS隊(duì)伍的人是越來越多欺旧,甚至已經(jīng)到供過于求了。今年蛤签,找...
    ZMJun閱讀 793評論 0 11
  • OC的理解與特性 OC作為一門面向?qū)ο蟮恼Z言辞友,自然具有面向?qū)ο蟮恼Z言特性:封裝、繼承顷啼、多態(tài)踏枣。它既具有靜態(tài)語言的特性...
    失憶的程序員閱讀 482評論 0 1
  • 序言 目前形勢茵瀑,參加到iOS隊(duì)伍的人是越來越多间驮,甚至已經(jīng)到供過于求了。今年马昨,找過工作人可能會更深刻地體會到今年的就...
    Jack_lin閱讀 78,348評論 110 1,945
  • *面試心聲:其實(shí)這些題本人都沒怎么背,但是在上海 兩周半 面了大約10家 收到差不多3個offer,總結(jié)起來就是把...
    Dove_iOS閱讀 27,130評論 30 470
  • OC的理解與特性 OC作為一門面向?qū)ο蟮恼Z言竞帽,自然具有面向?qū)ο蟮恼Z言特性:封裝、繼承鸿捧、多態(tài)屹篓。它既具有靜態(tài)語言的特性...
    克魯?shù)吕?/span>閱讀 447評論 0 0