下面是我最近兩年學(xué)習(xí)OC中的一些基礎(chǔ)知識(shí),對(duì)于學(xué)習(xí)OC基礎(chǔ)知識(shí)的人可能有些幫助怠晴,拿出來(lái)分享一下遥金,還是那句話不喜勿噴哦親。蒜田。稿械。。冲粤。
(1)
一美莫、Objective-C概述
1. Object-C簡(jiǎn)稱OC页眯,擴(kuò)充自C語(yǔ)言的面向?qū)ο缶幊陶Z(yǔ)言
2. 蘋果OS X和iOS操作系統(tǒng)的主要編程語(yǔ)言
3. OC的時(shí)間進(jìn)度
1) 1980年布萊德·確斯發(fā)明OC語(yǔ)言
2) 1988年NextStep公司使用OC開發(fā)
3) 1996年OC成為蘋果主要編程語(yǔ)言
4. OC語(yǔ)言的特點(diǎn)
1. C語(yǔ)言的超集,允許在OC中使用C語(yǔ)言源代碼厢呵,編譯器兼容C語(yǔ)言程序
2. C語(yǔ)言是面向過(guò)程窝撵,OC是面向?qū)ο缶幊?/p>
3. 包含一個(gè)運(yùn)行時(shí)系統(tǒng)(Runtime)
4. 類庫(kù)豐富
二、兩種編程思想
1. 面向過(guò)程編程
1)分析解決問(wèn)題的步驟襟铭,實(shí)現(xiàn)函數(shù)碌奉,依次調(diào)用
2)以過(guò)程為中心
2. 面向?qū)ο缶幊?/p>
1)分解問(wèn)題組成的對(duì)象,協(xié)調(diào)對(duì)象間的聯(lián)系和通信寒砖,解決問(wèn)題
2)以對(duì)象為中心
PS: 對(duì)象定義了解決問(wèn)題的步驟中的行為赐劣,不刻意完成一個(gè)步驟
3. 舉例,設(shè)計(jì)五子棋軟件
1) 面向過(guò)程編程設(shè)計(jì)
分析步驟
設(shè)計(jì)各類函數(shù)
一次調(diào)用完成功能
2) 面向?qū)ο缶幊淘O(shè)計(jì)
分析結(jié)構(gòu)對(duì)象
根據(jù)功能定義類
使用對(duì)象功能完成程序
旗手對(duì)象:接受用戶輸入哩都,通知棋盤對(duì)象在那個(gè)修改布局變化魁兼,利用規(guī)則對(duì)象對(duì)器具進(jìn)行判定
規(guī)則對(duì)象:提供游戲規(guī)則
棋盤對(duì)象:繪制布局
3): 面向?qū)ο笤O(shè)計(jì)具有良好的可擴(kuò)展性、可重用性
三漠嵌、類和對(duì)象的基本概念
1. 類
具有相同特征和行為事物的抽象
導(dǎo)演類:
特征:姓名咐汞、性別、國(guó)籍
行為:拍電影献雅、客串碉考、X規(guī)則
練習(xí):描述汽車類、手機(jī)類挺身,自己再嘗試列舉類并描述
2. 對(duì)象
對(duì)象是類的實(shí)例,是一個(gè)具體的實(shí)例
馮小剛對(duì)象:
有姓名锌仅、有性別章钾、有國(guó)籍
會(huì)拍電影、會(huì)客串热芹、X規(guī)則
練習(xí):iPhone4S是否是對(duì)象贱傀、波音747是否為對(duì)象、消失的MH370是否是對(duì)象伊脓,自己列舉幾個(gè)對(duì)象
3. 小結(jié)
1)類和對(duì)象是面向?qū)ο蟮暮诵?/p>
2)工作中就是不斷的對(duì)應(yīng)類府寒,創(chuàng)建對(duì)象,使用對(duì)象
3)如何描述類
4)區(qū)分類和對(duì)象
四报腔、OC中類的定義
定義類分兩步:接口部分和實(shí)現(xiàn)部分
1. 接口部分:對(duì)外聲明類的特征和行為
1) 用來(lái)聲明類的特征和行為
2) 標(biāo)志是@interface...@end
3) 類名沥割、父類名鞋邑、變量、方法,
4) 關(guān)鍵字@public
2. 實(shí)現(xiàn)部分:對(duì)內(nèi)實(shí)現(xiàn)行為
1)用來(lái)實(shí)現(xiàn)方法在验,即實(shí)現(xiàn)類的行為
2)標(biāo)志是@implementation...@end
3. 練習(xí):
1) 定義奧迪汽車類
2) 定義手機(jī)類
五、類和文件
文件和類本質(zhì)沒有關(guān)系还绘,為了方便管理,實(shí)現(xiàn)封裝特性
1. 類:
@interface...@end
@implementation...@end
2. 文件
.h 稱為接口文件或頭文件 .m稱為實(shí)現(xiàn)文件捌刮,用Xcode創(chuàng)建一個(gè)類時(shí)默認(rèn)設(shè)置如下:
1)使用類名命名文件
2) .h 文件管理類的接口部分
.m 文件管理類的實(shí)現(xiàn)部分
3. 練習(xí)
1) 在.h文件中定義與文件不同名的類
2) 在.h文件中完成定義類
3) 在文件中定義多個(gè)類
六、使用類創(chuàng)建對(duì)象
1. 創(chuàng)建對(duì)象分兩步
1)分配內(nèi)存空間
根據(jù)類中聲明的實(shí)例變量為對(duì)象分配內(nèi)存
Person *p = [Person alloc];
+(id)alloc; +表示這個(gè)方法屬于類舒岸,只能類執(zhí)行绅作,id表示任意類型的對(duì)象,即創(chuàng)建好的對(duì)象
2)初始化
對(duì)創(chuàng)建的對(duì)象進(jìn)行實(shí)例變量的初始化設(shè)置
p = [p init];
-(id)init -表示這個(gè)方法屬于對(duì)象蛾派,只能對(duì)象執(zhí)行俄认,id表示初始化完成的對(duì)象
3) 通常這兩步需要連寫
Person *p = [[Person alloc] init];
(2)
一、實(shí)例變量可見度
1. public(公有的)
實(shí)例變量可以被任意操作碍脏,實(shí)際情況中很少使用Public梭依,有以下兩個(gè)原因:
1)使用@public關(guān)鍵字,暴露了類內(nèi)部的細(xì)節(jié)
2)不符合面向?qū)ο笳Z(yǔ)言的三大特性之一 - 封裝
2. protected(受保護(hù)的典尾,默認(rèn)的)
實(shí)例變量只能在該類和其子類中操作
3. private(私有的)
實(shí)例對(duì)象只能在該類內(nèi)訪問(wèn)
4. 思考
如果在其他類中使用@protected修飾的實(shí)例變量
二役拴、方法
1. 類方法
只能使用類來(lái)調(diào)用,在返回值類型的前面加+來(lái)標(biāo)識(shí)
注:類方法中不能使用實(shí)例變量
2. 實(shí)例方法(對(duì)象方法)
只能使用對(duì)象調(diào)用
3. 方法聲明
格式
- (返回類型)參數(shù)形容詞1:(參數(shù)類型)參數(shù)名1 參數(shù)形容詞2:(參數(shù)類型)參數(shù)名2
方法名呢钾埂?
參數(shù)形容詞拼接起來(lái)就是該方法的方法名
4. 方法調(diào)用
[對(duì)象名或者類名 方法名];
比如:
[student sayHi];
正確表述:
給student對(duì)象發(fā)送sayHi消息
1)student接收到消息河闰,及方法sayHi
2) student找到sayHi方法,并執(zhí)行
5. 定義AodiCar類和MobilePhone類褥紫,需求:
1)實(shí)例變量使用默認(rèn)可見度
2)添加方法實(shí)現(xiàn)對(duì)實(shí)例變量的操作
3)任意添加方法并使用
三姜性、自定義初始化方法
1. -(id)init 這個(gè)初始化方法只能給實(shí)例變量設(shè)置默認(rèn)值,不靈活髓考,我們可以通過(guò)自定義初始化方法給實(shí)例變量設(shè)值
練習(xí):
1. 給AodiCar類添加自定義初始化方法
2. 給MobilePhone類添加自定義初始化方法
四部念、OC中導(dǎo)入頭文件的兩種方式
1. #import
1. 導(dǎo)入頭文件,即將導(dǎo)入的頭文件中的內(nèi)容氨菇,賦值到當(dāng)前類
2. <>用于導(dǎo)入類庫(kù)中的頭文件
3. ""用于導(dǎo)入自定義的類
4. 功能類似C語(yǔ)言中的#include,但可以避免頭文件被重復(fù)包含
2. @class
1. 告訴編譯器有這個(gè)類儡炼,無(wú)法導(dǎo)入類的接口內(nèi)容
2. 有效避免嵌套引用
五、復(fù)合
1. 多個(gè)組件組合在一起查蓉,形成一個(gè)整體乌询,然后使用整體進(jìn)行工作,這種組合成為復(fù)合豌研。
2. OC中妹田,類的實(shí)例變量由其他類型組成。
3. 簡(jiǎn)單的說(shuō)就是讓兩個(gè)類關(guān)聯(lián)起來(lái)就是復(fù)合
(3)
一鹃共、繼承
1. 繼承的上層:父類(或超類)
繼承的下層:子類
2. 繼承是單向的,兩個(gè)類之間不能互相繼承
3. 繼承具有傳遞性
子類繼承父類的特征和行為
4. 子類擴(kuò)展父類鬼佣,更具體
5. 繼承特點(diǎn):
1) OC中只允許單繼承
2) 沒有父類的類稱為根類,OC中的根類是NSObject
3) 子類繼承的內(nèi)容
除了私有變量之外的所有實(shí)例變量和方法
4) 子類可以重寫父類的方法
6. 練習(xí)
1)定義Person類
2)定義Student類及汉,繼承自Person類
3)使用繼承得到的實(shí)例變量
4)使用繼承得到的方法
5)定義CollegeStudent類沮趣,繼承自Student類
7. 繼承中方法的查找,查看課件中的圖片
8. super
1)父類對(duì)象
2)可以執(zhí)行父類中實(shí)現(xiàn)的方法
二坷随、初始化方法
1. 初始化過(guò)程
1)執(zhí)行父類中實(shí)現(xiàn)的初始化方法房铭,向上遞歸到NSObject類中的初始化方法
2)判斷父類中的初始化是否成功驻龟,即self是否存在
3)完成對(duì)象的初始化設(shè)置,返回對(duì)象
三缸匪、便利構(gòu)造器
1. 作用
是一種快速創(chuàng)建對(duì)象的方式.它本質(zhì)上是把初始化方法做了一次封裝,方便外接使用.
2. 寫法
類方法和對(duì)象方法的配合使用
(4)
一翁狐、 學(xué)習(xí)查看類的基本信息
1. 繼承自誰(shuí)
2. 遵循什么協(xié)議
3. 屬于什么框架
4. 從iOS哪個(gè)版本開始支持
二、 字符串類
1. NSString:不可變字符串
對(duì)象創(chuàng)建賦值以后凌蔬,內(nèi)容和長(zhǎng)度不能動(dòng)態(tài)更改
2. NSMutableString:可變字符串
該類創(chuàng)建的字符串是一個(gè)動(dòng)態(tài)的可變的字符串露懒,可以支持增刪改查等動(dòng)態(tài)的操作
3. 聯(lián)系
1) NSMutableString是NSString的子類,繼承的到所有方法
2) 不可變字符串的修改操作砂心,本質(zhì)就是得到一個(gè)新的字符串
3) 不可變字符串的修改方法以string開頭懈词,有返回值
4) 可變字符串的修改方法沒有返回值,修改原字符串
三辩诞、 字符串常用方法
1. 創(chuàng)建一個(gè)字符創(chuàng)常量
2. 快速創(chuàng)建一個(gè)字符串
3. 創(chuàng)建一個(gè)格式化的字符串
4. 字符串的比較
5. 字符串的轉(zhuǎn)換
6. 字符串的截取與拼接
NSMutableString方法
7. 增
8. 刪
9. 改
10.查
四坎弯、NSNumber,數(shù)值對(duì)象
用于將基本數(shù)據(jù)類型封裝為對(duì)象
三、數(shù)組類
1. 特點(diǎn)
1)容器類译暂,管理一組對(duì)象類型的數(shù)據(jù)
2)數(shù)組中元素是有序的抠忘,索引值從0開始
3) 數(shù)組中存儲(chǔ)的元素必須是對(duì)象,類型任意
2. 分為可變數(shù)組與不可變數(shù)組
四外永、數(shù)組常用方法
1. 數(shù)組對(duì)象的創(chuàng)建
2. 獲取數(shù)組中的元素個(gè)數(shù)以及訪問(wèn)數(shù)組元素
3. 追加數(shù)組中的內(nèi)容
4. 數(shù)組轉(zhuǎn)字符串
5. 判斷數(shù)組中是否存在一個(gè)指定的對(duì)象
6. 根據(jù)指定的對(duì)象返回索引下標(biāo)崎脉、返回?cái)?shù)組中最后一個(gè)元素
不可變數(shù)組
7. 新增
8. 插入
9. 刪除最后一個(gè)元素
10. 刪除指定的元素
11. 刪除指定位置的元素
12. 批量刪除
13. 替換元素
(5)
查看API找方法
1. 判斷指定字符串是否在字符串的頭部
2. 判斷指定字符串是否在字符串的尾部
3. 將數(shù)字型字符串轉(zhuǎn)化為基本數(shù)據(jù)類型
一、數(shù)組的遍歷
1. for循環(huán)
2. for..in循環(huán)
二伯顶、字典
特點(diǎn):
利用鍵值對(duì)存取值
格式: @{@"key":@"value"}
相比于數(shù)組:
因?yàn)槭峭ㄟ^(guò)key查找的囚灼,所以能比數(shù)組更快的查到所要找的數(shù)據(jù)
三、NSDictionary:不可變字典
字典內(nèi)容確定后祭衩,不可再更改
1. 常用方法
字典對(duì)象的創(chuàng)建
獲取字典的值
獲取字典數(shù)量
獲取字典所有的鍵和值
獲取文件中的plist數(shù)據(jù)
枚舉器訪問(wèn)
四啦撮、NSMutableDictionary:可變字典,項(xiàng)目開發(fā)中建議使用可變字典
1. 常用方法
創(chuàng)建指定元素個(gè)數(shù)的字典
增加元素
刪除元素
全部刪除
五、集合
特點(diǎn):
OC中為我們提供了批量處理數(shù)據(jù)的一種數(shù)據(jù)類型-集合
與數(shù)組的區(qū)別:
1. 都是存儲(chǔ)不同的對(duì)象的地址汪厨;不過(guò)NSArray是有序的集合,NSSet是無(wú)序的集合
2. 查找集合中的元素比數(shù)組速度更快愉择,但是它沒有順序
3. 集合中不允許有重復(fù)的值
六劫乱、NSSet
常用方法
創(chuàng)建對(duì)象
枚舉器訪問(wèn)集合元素 intersect
判斷兩個(gè)集合是否有交集
判斷當(dāng)前集合是否是子集
七、NSMutableSet
常用方法
創(chuàng)建指定元素個(gè)數(shù)的一個(gè)集合對(duì)象
添加一個(gè)對(duì)象到集合
把數(shù)組對(duì)象添加到集合中
從集合中刪除一個(gè)對(duì)象
獲得兩個(gè)集合的并集
得到兩個(gè)集合的交集
從一個(gè)集合中減去另一個(gè)集合
給集合賦值
八锥涕、數(shù)組排序
//默認(rèn)升序
sortedArrayUsingSelector
//能指定升序還是降序
sortedArrayUsingComparator
(6)
一衷戈、拷貝對(duì)象的基本概念? 1、拷貝一個(gè)對(duì)象作為副本层坠,他會(huì)開辟一塊新的內(nèi)存來(lái)存儲(chǔ)副本對(duì)象殖妇,就像復(fù)制文件一樣,即源對(duì)象和副本對(duì)象是兩塊不同的內(nèi)存區(qū)域? 2破花、對(duì)象具備拷貝功能谦趣,必須實(shí)現(xiàn)協(xié)議
3疲吸、常用的可復(fù)制對(duì)象有NSNumber、NSString前鹅、NSArray摘悴、NSDictionary、NSMutableDictionary舰绘、NSMutableArray蹂喻、NSMutableString
4、拷貝對(duì)象的種類:
1) copy: 產(chǎn)生對(duì)象的副本是不可變的
如果原來(lái)的對(duì)象是一個(gè)不可變的捂寿,那么他們的地址指向同一個(gè)地址口四,也就說(shuō)他們是同一個(gè)對(duì)象
如果原來(lái)的對(duì)象是一個(gè)可變對(duì)象,那么他會(huì)新生成一個(gè)不可變對(duì)象秦陋,地址不同
2)MutableCopy: 產(chǎn)生的對(duì)象副本是可變的
得到一個(gè)新的可變對(duì)象
5蔓彩、課堂實(shí)例
創(chuàng)建一個(gè)數(shù)組(包含元素:one,two踱侣,three等)粪小,然后分別對(duì)它進(jìn)行保留、和拷貝操作抡句,刪除其中的一個(gè)元素探膊,看看發(fā)生了什么?
二待榔、淺拷貝和深拷貝基本概念和用法
1逞壁、淺拷貝只支付對(duì)象的本身,對(duì)象的屬性锐锣、包含的對(duì)象不做拷貝
2腌闯、深拷貝則拷貝對(duì)象本身,對(duì)象的屬性也會(huì)拷貝一份
3雕憔、Foundation框架中支持拷貝的類姿骏,默認(rèn)是淺拷貝
4、課堂練習(xí)
一個(gè)數(shù)組包含了許多個(gè)對(duì)象斤彼,復(fù)制一個(gè)數(shù)組的副本分瘦,那么兩個(gè)數(shù)組中的元素是沒復(fù)制的,指向的還是同一個(gè)對(duì)象琉苇。
三嘲玫、對(duì)象的自定義拷貝
1、對(duì)象擁有拷貝特性并扇,必須實(shí)現(xiàn)NSCopying去团、NSMutableCopying協(xié)議,實(shí)現(xiàn)該協(xié)議的copyWithZone和MutableCopyWithZone方法
2、Objective-C對(duì)象的深土陪、淺拷貝的區(qū)別就在于你對(duì)copyWithZone的不同實(shí)現(xiàn)
5昼汗、課堂練習(xí)
自定義類實(shí)現(xiàn)深、淺拷貝
6. 課堂實(shí)例
我們創(chuàng)建一個(gè)汽車類旺坠,汽車擁有一個(gè)Engine對(duì)象乔遮,一個(gè)車重和一個(gè)名字,讓我們來(lái)一起實(shí)現(xiàn)下他的深復(fù)制和淺復(fù)制
四取刃、總結(jié)
1蹋肮、復(fù)制對(duì)象的概念,淺復(fù)制璧疗、深復(fù)制的區(qū)別坯辩。
2、自定義對(duì)象如何支持復(fù)制崩侠,實(shí)現(xiàn)NSCopying協(xié)議漆魔。
3、自定義對(duì)象如何實(shí)現(xiàn)深復(fù)制和淺復(fù)制却音。
4改抡、Foundation框架中支持復(fù)制的對(duì)象需要注意的地方。
補(bǔ)充:
可以將NSZone,可以想象成一個(gè)內(nèi)存池系瓢,alloc或是dealloc這些操作阿纤,都是在這個(gè)內(nèi)存池中操作的。
cocoa總是會(huì)配置一個(gè)默認(rèn)的NSZone夷陋,任何默認(rèn)的內(nèi)存操作都是在這個(gè)“zone”上操作的欠拾。
(7)
一、類目(category)的基本概念和用法? 1骗绕、封裝是面向?qū)ο蟮囊粋€(gè)特征藐窄,OC也不意外,但有時(shí)候我們會(huì)碰到這樣一種情況酬土,比如我封裝了一個(gè)類荆忍,不想再動(dòng)它了,可是隨著程序功能的增加撤缴,需要在哪個(gè)類中增加一個(gè)小小的方法东揣,這是我們就不必再那個(gè)類中做修改或者在定義一個(gè)子類,只需要在用到那個(gè)方法時(shí)隨手添加一個(gè)該類的類目即可? ? 1) 在類目定義的方法腹泌,會(huì)成為原始類的一部分,與其他方法的調(diào)用沒有區(qū)別? ? 2) 通過(guò)給父類定義類目方法尔觉,其子類也會(huì)繼承這些方法凉袱,如果子類添加類目方法,父類則不會(huì)擁有子類的類目方法? 2、類目的應(yīng)用和局限? ? ? 1)應(yīng)用? ? ? ? 對(duì)現(xiàn)有類進(jìn)行擴(kuò)展:? ? ? ? ? 比如专甩,可以擴(kuò)展Cocoa Touch框架中的類钟鸵,你在類目中增加的方法會(huì)被子類所繼承,而且在運(yùn)行時(shí)跟其他的方法沒有區(qū)別? ? ? ? 作為子類的替代手段:? ? ? ? ? 不需要定義和使用一個(gè)子類涤躲,可以通過(guò)類目直接向已有的類增加方法? ? ? ? 對(duì)類中的方法歸類:? ? ? ? ? 利用category把龐大的類劃分為小塊分別進(jìn)行開發(fā)棺耍,從而更好的對(duì)類中的方法進(jìn)行更新和維護(hù)? ? ? 2)局限性? ? ? ? ? 無(wú)法向類目中,添加新的實(shí)例變量种樱,類目中沒有位置來(lái)容納實(shí)例變量蒙袍,如果想增加類的實(shí)例變量,只能通過(guò)定義子類的方式? ? ? ? ? 在類目中一般不要覆蓋現(xiàn)有類的方法二嫩挤、延展基本概念和用法? ? 類的延展就如同是"匿名"的類目害幅,延展中聲明的方法在類本身的@implementation和它對(duì)應(yīng)的@end之間實(shí)現(xiàn),類有時(shí)需要方法方法只有自己所見岂昭,我們可以通過(guò)延展的方式定義類的私有方法? ? //延展? ? @interface Person ()? ? ? - (void)privateMethod;? ? @end三以现、示例? ? 創(chuàng)建一個(gè)MachinePerson類,讓這個(gè)機(jī)器人能夠說(shuō)話约啊,在不改變?cè)惖幕A(chǔ)上讓這個(gè)機(jī)器人會(huì)跳舞? ? 給NSArray添加一個(gè)類目邑遏,讓NSArray能夠?qū)nt型各位上的數(shù)放到一個(gè)數(shù)組中一、協(xié)議(protocol)的基本概念? ? 1恰矩、協(xié)議的聲明看起來(lái)比較類似一個(gè)類的接口文件记盒,不同的是協(xié)議沒有父類也不能定義實(shí)例變量。? ? 2枢里、協(xié)議是一種特殊的程序設(shè)計(jì)結(jié)構(gòu)孽鸡,用于聲明專門被別的類實(shí)現(xiàn)的方法,協(xié)議在以下場(chǎng)合非常有用:? ? ? 1)需要由別的類實(shí)現(xiàn)的方法? ? ? 2)聲明未知類的接口? ? ? 3)兩個(gè)雷之間的通信? ? 3栏豺、協(xié)議的基本特點(diǎn)? ? ? 1)協(xié)議可以被任何類實(shí)現(xiàn)方法彬碱,協(xié)議本身不是類,他是定義了一個(gè)其他類可實(shí)現(xiàn)的接口奥洼,類目也可以采用協(xié)議? ? ? ? 2)協(xié)議的關(guān)鍵字? ? ? ? ? @required:表示必須強(qiáng)制實(shí)現(xiàn)的方法? ? ? ? ? @optional:表示可以有選擇性的實(shí)現(xiàn)方法? ? ? 3)實(shí)現(xiàn)的聲明與實(shí)現(xiàn)? ? ? ? ? /* 協(xié)議的聲明 */? ? ? ? ? @protocol HelloProtocol@optional? ? ? ? ? - (void)optionalMethod1;? ? ? ? ? - (void)optionalMethod2;? ? ? ? ? @required? ? ? ? ? - (void)requiredMethod1;? ? ? ? ? @end? ? ? ? ? /* 協(xié)議的實(shí)現(xiàn) */? ? ? ? ? @implementation Person? ? ? ? ? - (void)requiredMethod1 {? ? ? ? ? } // 實(shí)現(xiàn)了該協(xié)議中的方法巷疼,且方法必須實(shí)現(xiàn)? ? ? ? ? - (void)optionalMethod1 {? ? ? ? ? } // 實(shí)現(xiàn)了該協(xié)議中的方法,可以選擇不實(shí)現(xiàn)? ? ? ? ? @end? ? ? ? ? ? ? ? ? ? ? ? ? ? ? /* 采用了該協(xié)議 */? ? ? ? ? @interface Person : NSObject@end
二灵奖、委托設(shè)計(jì)模式
1嚼沿、指一個(gè)對(duì)象提供機(jī)會(huì)對(duì)另一個(gè)對(duì)象中的行為發(fā)生變化時(shí)做出的反應(yīng)
如:當(dāng)將一顆石子(對(duì)象1)丟入水中(行為發(fā)生變化,之前可能在你的手中)時(shí)瓷患,水面(對(duì)象2)泛起波紋(做出的反應(yīng))
2骡尽、基本思想:
兩個(gè)對(duì)象協(xié)同解決問(wèn)題,通常用于對(duì)象之間的通信
3擅编、基本特點(diǎn):
1)簡(jiǎn)化了對(duì)象的行為攀细,最小化了對(duì)象之間的耦合度
2)使用代理箫踩,一般來(lái)說(shuō)無(wú)需子類化
3)簡(jiǎn)化了應(yīng)用程序開發(fā),既容易實(shí)現(xiàn)谭贪,又靈活
三境钟、 示例:中介找房
1、假設(shè)有一個(gè)Jack的人(Person)俭识,他想租一套公寓(Apartment)慨削,由于他工作繁忙(或者其他原因),沒有時(shí)間(或者自身沒有能力)去租房套媚。因此缚态,他委托中介公司(Agent)幫他尋找房源,找到合適的房源告知Jack凑阶。
2猿规、補(bǔ)充
1)定時(shí)器
一旦創(chuàng)建了一個(gè)定時(shí)器對(duì)象(NSTimer實(shí)例),他可以按照一定時(shí)間的間隔,將指定消息發(fā)送到目標(biāo)對(duì)象宙橱,并更新某個(gè)對(duì)象的行為姨俩,你可以選擇在未來(lái)的某個(gè)時(shí)候?qū)⑺?開啟",或者將它停止乃至銷毀师郑。
2)NSRunloop
一個(gè)runloop就是一個(gè)事件處理的循環(huán)环葵,用來(lái)不斷的調(diào)度工作以及處理輸入事件,使用runloop的目的是讓你的線程在有工作的時(shí)候忙于工作宝冕,而沒有工作的時(shí)候處于休眠狀態(tài)
在我們的應(yīng)用程序中张遭,不需要?jiǎng)?chuàng)建NSRunloop對(duì)象,因?yàn)榈乩妫谖覀兊闹骶€程中(包含其他子線程)系統(tǒng)會(huì)自動(dòng)穿件NSRunloop對(duì)象菊卷,如果需要訪問(wèn)當(dāng)前線程中的runloop,你可以通過(guò)類方法『currentRunloop』獲取到
(8)
一宝剖、引用計(jì)數(shù)器和對(duì)象所有權(quán)的基本概念
1洁闰、引用計(jì)數(shù)器
每個(gè)對(duì)象都會(huì)有一個(gè)引用計(jì)數(shù)器,當(dāng)引用計(jì)數(shù)器為0是万细,系統(tǒng)就會(huì)將這個(gè)對(duì)象給釋放
2扑眉、對(duì)象所有權(quán)
當(dāng)一個(gè)所有者(owner,其本身可以是任何一個(gè)OC對(duì)象)做了以下某個(gè)動(dòng)作時(shí)赖钞,它就擁有了對(duì)一個(gè)對(duì)象的所有權(quán)
1)alloc, allocWithZone:, copy, copyWithZone:, mutableCopy, mutableCopyWithZone:
2) 如果沒有創(chuàng)建對(duì)象腰素,而是將對(duì)象保留使用,同樣擁有該對(duì)象的所有權(quán)
retain
3) 如果你擁有了某個(gè)對(duì)象的所有權(quán)雪营,在不需要某一個(gè)對(duì)象時(shí)弓千,需要釋放他們
release autorelease
3. 案例
1) 假設(shè)在main函數(shù)主程序中,不小心想powerPC實(shí)例對(duì)象發(fā)送了release消息献起,即powerPC實(shí)例銷毀了计呈,但apple實(shí)例可能仍然在某個(gè)地方在使用powerPC實(shí)例砰诵,那么你的程序就會(huì)crash掉。
2) 我們知道2005年后捌显,蘋果的CPU轉(zhuǎn)向了intel的懷抱,因此总寒,我們需要將CPU改為intel的CPU
4. 詳解delloc方法
什么時(shí)候調(diào)用
當(dāng)對(duì)象的引用計(jì)數(shù)器為0時(shí)扶歪,系統(tǒng)會(huì)自動(dòng)調(diào)用delloc方法,回收內(nèi)存
為什么要調(diào)用父類的dealloc方法
子類的某些實(shí)例是繼承自父類的摄闸,因此我們需要調(diào)用父類的delloc,釋放父類擁有的這些對(duì)象
調(diào)用順序
1)釋放子類中的對(duì)象
2)釋放父類中所擁有的實(shí)例
5. 案例
創(chuàng)建一個(gè)Vehicle類善镰,以及Vehicle類的子類Car類,Vehicle類擁有一個(gè)實(shí)例變量_name年枕,以及一個(gè)初始化名字的實(shí)例方法炫欺。
Car類自身?yè)碛幸粋€(gè)V6渦輪增加引擎。
6. 總結(jié)
該如何持有對(duì)象
1)初始化方法
2)直接向?qū)ο蟀l(fā)送retain消息熏兄,持有dealloc方法釋放該對(duì)象
3)
二品洛、點(diǎn)語(yǔ)法的內(nèi)存管理
1、賦值:
1)assign:直接賦值摩桶,默認(rèn)
2)retain:賦值桥状,并保留對(duì)象
3)copy:拷貝對(duì)象
2、讀寫性
1)readwrite:生成getter硝清、setter方法辅斟,默認(rèn)是readwrite
2) readonly:生成getter方法
3、原子性
1)atomic:多線程環(huán)境下芦拿, 存在線程保護(hù)士飒,默認(rèn)
2)nonatomic:多線程環(huán)境下,不存在線程保
三蔗崎、ASSIGN酵幕、RETAIN與COPY的區(qū)別
1、assign
直接賦值蚁趁,只是一個(gè)別名而已裙盾。
2、retain
保留的這個(gè)對(duì)象他嫡,兩個(gè)對(duì)象指向了同一個(gè)位置番官。
3、copy
開辟了一個(gè)新的內(nèi)存空間钢属,分別指向了不同的內(nèi)存位置徘熔,引用計(jì)數(shù)分別為1,與之前的對(duì)象完全脫離關(guān)系淆党。這里我們尤其需要注意酷师,某些時(shí)候copy的
作用相當(dāng)于retain
四讶凉、自動(dòng)釋放池
1、基本概念
cocoa有一個(gè)自動(dòng)釋放池的概念山孔,顧名思義懂讯,他是可以存放一些實(shí)體的集合,在這個(gè)自動(dòng)釋放池中的對(duì)象台颠,是能夠被自動(dòng)釋放的
NSObject類提供了一個(gè)autorelease消息褐望,當(dāng)我們向一個(gè)對(duì)象發(fā)送autorelease消息時(shí),這個(gè)對(duì)象就被放入了自動(dòng)釋放池
2串前、 自動(dòng)釋放池的銷毀時(shí)間
當(dāng)我們想一個(gè)對(duì)象發(fā)送了autorelease消息是瘫里,當(dāng)自動(dòng)釋放池銷毀時(shí),會(huì)對(duì)池中的每個(gè)對(duì)象發(fā)送一條release消息荡碾,以此釋放他們
3谨读、創(chuàng)建自動(dòng)釋放池
ios5.0 后寫法
@autoreleasepool {}
ios5.0 之前寫法
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
[pool release];
4、示例
創(chuàng)建一個(gè)Person類坛吁,創(chuàng)建一個(gè)Person類的實(shí)例jack劳殖,將jack加入自動(dòng)釋放池,即向他發(fā)送一條autorelease消息阶冈,查看它的生命周期是怎樣的闷尿。
完成第一點(diǎn)內(nèi)容后,我們?cè)谙騤ack實(shí)例發(fā)送一條retain消息女坑。查看它的引用計(jì)數(shù)和生命周期是如何的填具。
五、內(nèi)存管理總結(jié)
1匆骗、當(dāng)你使用new, alloc或copy方法創(chuàng)建一個(gè)對(duì)象時(shí)劳景,該對(duì)象的引用計(jì)數(shù)器為1。當(dāng)不再使用該對(duì)象時(shí)碉就,你要負(fù)責(zé)向該對(duì)象發(fā)送一條release或者autorelease消息盟广,這樣,該對(duì)象將在其使用壽命結(jié)束時(shí)被銷毀
2瓮钥、你通過(guò)任何其他方法獲得一個(gè)對(duì)象時(shí)筋量,則假設(shè)該對(duì)象的引用計(jì)數(shù)為1,而且已經(jīng)被設(shè)置為自動(dòng)釋放碉熄,你不需要執(zhí)行任何方法來(lái)釋放該對(duì)象桨武。如果你打算在一段時(shí)間內(nèi)擁有該對(duì)象,則需要保留它并確保在操作完成時(shí)釋放它锈津。
3呀酸、如果你保留了某個(gè)對(duì)象,你需要釋放或自動(dòng)釋放該對(duì)象琼梆,必須保持retain方法和release方法的使用次數(shù)相等性誉。
4窿吩、除了alloc、new或copy之外的方法創(chuàng)建的對(duì)象都被聲明了autorelease错览。誰(shuí)retain纫雁,誰(shuí)release。只要你調(diào)用了retain倾哺,無(wú)論這個(gè)對(duì)象是如何生成的先较,你都要調(diào)用release。有時(shí)候你的代碼中明明沒有retain
5悼粮、大道至簡(jiǎn)
如果創(chuàng)建一個(gè)對(duì)象使用了alloc、copy[mutable]曾棕、retain扣猫,那么你就有義務(wù)向這個(gè)
對(duì)象發(fā)送一條release或者autorelease消息。
六翘地、內(nèi)存管理的兩種方式
1. ARC 自動(dòng)管理->程序員開辟內(nèi)存申尤,編譯器幫助釋放內(nèi)存
iOS5.0的編譯特性,它只允許用戶開辟內(nèi)存空間衙耕,不去釋放空間昧穿,編譯器幫程序員默認(rèn)加了釋放的代碼
2. MRC 手動(dòng)管理->程序員開辟內(nèi)存,程序員釋放內(nèi)存
內(nèi)存的開辟和釋放都由程序代碼進(jìn)行控制橙喘,相對(duì)垃圾回收來(lái)說(shuō)时鸵,對(duì)內(nèi)存的控制更加靈活,可以在自己需要的釋放的時(shí)候及時(shí)釋放厅瞎,對(duì)程序員的要求較高饰潜,程序員要熟悉內(nèi)存管理機(jī)制。
內(nèi)存管理機(jī)制:引用計(jì)數(shù)器
七和簸、ARC和垃圾回收機(jī)制
1彭雾、垃圾回收機(jī)制
程序只需要開辟內(nèi)存空間,不需要用代碼顯示的釋放锁保,系統(tǒng)來(lái)判斷哪些空間不再被使用薯酝,并回收這些內(nèi)存空間,以便再次分配爽柒,整個(gè)回收的過(guò)程不需要寫任何代碼吴菠,由系統(tǒng)自動(dòng)完成垃圾回收
2、與java/net語(yǔ)言相同霉赡,oc2.0以后橄务,也提供了垃圾回收機(jī)制,但在iOS移動(dòng)終端設(shè)備中穴亏,并不支持垃圾回收機(jī)制(取決于終端設(shè)備的性能),因此iPhone并不能對(duì)內(nèi)存進(jìn)行自動(dòng)垃圾回收處理(中間模式autorelease)
3蜂挪、垃圾回收機(jī)制并不是ARC重挑,ARC也是需要管理內(nèi)存的,只不過(guò)是隱式的管理內(nèi)存棠涮,編譯器會(huì)在適當(dāng)?shù)牡胤阶詣?dòng)插入retain.release和autorelease消息
(9)
一谬哀、NSFileHandle
1、對(duì)文件常做的處理
1)對(duì)文件內(nèi)容進(jìn)行讀取和寫入操作
2)做斷點(diǎn)續(xù)傳
2严肪、處理文件的步驟
1)創(chuàng)建一個(gè)NSFileHandle對(duì)象
2)對(duì)打開的文件進(jìn)行I/O操作
3)關(guān)閉文件
3史煎、不足
只可以讀寫文件,不能創(chuàng)建文件驳糯,創(chuàng)建文件使用NSFileManager
二篇梭、常用方法
打開一個(gè)文件準(zhǔn)備讀取
+ (id)fileHandleForReadingAtPath:(NSString *)path;
打開一個(gè)文件準(zhǔn)備寫入
+ (id)fileHandleForWritingAtPath:(NSString *)path;
打開一個(gè)文件準(zhǔn)備更新(讀取、更新)
+ (id)fileHandleForUpdatingAtPath:(NSString *)path;
從設(shè)備或通道返回可用的數(shù)據(jù)
- (NSData *)availableData;
從當(dāng)前的節(jié)點(diǎn)讀取到文件末尾
- (NSData *)readDataToEndOfFile;
從當(dāng)前節(jié)點(diǎn)開始讀取指定的長(zhǎng)度數(shù)據(jù)
- (NSData *)readDataOfLength:(NSUInteger)length;
寫入數(shù)據(jù)
- (void)writeData:(NSData *)data;
獲取當(dāng)前文件的偏移量
- (unsigned long long)offsetInFile;
跳到指定文件的偏移量
- (void)seekToFileOffset:(unsigned long long)offset;
跳到文件末尾
- (unsigned long long)seekToEndOfFile;
關(guān)閉文件
- (void)closeFile;
三酝枢、練習(xí)
1恬偷、創(chuàng)建一個(gè)Date.text文件,獲取當(dāng)前的日期帘睦,將日期格式為“2013/02/14 05:20:00”的形式袍患。然后一秒鐘記錄一次,將新的時(shí)間存入到文件中竣付。
2诡延、復(fù)制一個(gè)大型文件,為了節(jié)約內(nèi)存古胆,每次只讀取500個(gè)字節(jié)肆良。
(注意:最后一次讀取可能超出500個(gè)字節(jié),可以采取總長(zhǎng)度減去已經(jīng)讀取的長(zhǎng)度來(lái)判斷,如果小于500個(gè)字節(jié)就不用讀取500個(gè)字節(jié)直接讀取到文件末尾就可以)
一赤兴、 文件管理常用的類和方法
1妖滔、NSFileManager:
提供了對(duì)文件的基本操作類,對(duì)文件的刪除桶良、修改座舍、移動(dòng)、復(fù)制等內(nèi)容
2陨帆、常用方法
創(chuàng)建一個(gè)新的文件并寫入數(shù)據(jù)
- (BOOL)createFileAtPath:(NSString *)path contents:(NSData *)data attributes:(NSDictionary *)attr;
從一個(gè)文件中讀取數(shù)據(jù)
- (NSData *)contentsAtPath:(NSString *)path;
srcPath路徑上的文件移動(dòng)到 dstPath 路徑上
- (BOOL)moveItemAtPath:(NSString *)srcPath toPath:(NSString *)dstPath error:(NSError **)error;
比較兩個(gè)文件的內(nèi)容是否一樣
- (BOOL)contentsEqualAtPath:(NSString *)path1 andPath:(NSString *)path2;
文件是否存在
- (BOOL)fileExistsAtPath:(NSString *)path;
移除文件
- (BOOL)removeItemAtPath:(NSString *)path error:(NSError **)error;
二曲秉、屬性列表化
iOS數(shù)據(jù)持久性的一種方式,使用方便簡(jiǎn)單快捷
只能將Bool疲牵、NSNumber承二、NSString、NSData纲爸、NSDate亥鸠、NSArray、NSDictionary 寫入屬性列表plist文件
一、應(yīng)用程序沙盒的基本概念
1负蚊、iOS中的沙盒(sandbox)機(jī)制
1)iOS應(yīng)用程序只能對(duì)自己創(chuàng)建的文件系統(tǒng)讀取文件神妹,這個(gè)"獨(dú)立","封閉","安全"的空間,稱之為沙盒家妆,所有的非代碼文件都要保存在此鸵荠。
2)它一般存放著你程序包文件(可執(zhí)行文件)、圖片伤极、聲音蛹找、視頻、plist哨坪、sqlite數(shù)據(jù)庫(kù)以及其他文件
2)每個(gè)應(yīng)用程序都有自己的獨(dú)立的存儲(chǔ)空間(沙盒)庸疾,一般情況下應(yīng)用程序是不可以相互訪問(wèn)沙盒,也有例外当编,比如系統(tǒng)通訊錄能在用戶授權(quán)的情況下被第三方應(yīng)用訪問(wèn)
2彼硫、沙盒目錄文件的組成以及相關(guān)含義
當(dāng)我們創(chuàng)建我們的應(yīng)用程序時(shí),在每個(gè)沙盒中默認(rèn)含有四個(gè)文件凌箕,如下:
Documnets:
一般我們需要持久的數(shù)據(jù)都放在這個(gè)目錄中,你可以在當(dāng)中添加子文件夾词渤,需要注意的是牵舱,iTunes備份和恢復(fù)的時(shí)候,會(huì)包括此目錄
Library:
設(shè)置程序的默認(rèn)設(shè)置和其他狀態(tài)信息
Library/Caches:存放緩存文件缺虐,應(yīng)用程序再次啟動(dòng)過(guò)程中需要的信息
Library/Preferences:包含應(yīng)用程序的偏好設(shè)置文件芜壁。
tmp:
創(chuàng)建臨時(shí)文件的目錄,當(dāng)我們的iOS設(shè)備重啟是高氮,文件會(huì)自動(dòng)被清除
程序.app慧妄,與另三個(gè)路徑的父路徑不同
這是應(yīng)用程序的程序包目錄,包含應(yīng)用程序的本身剪芍。由于應(yīng)用程序必須經(jīng)過(guò)簽名塞淹,所以您在運(yùn)行時(shí)不能對(duì)這個(gè)目錄中的內(nèi)容進(jìn)行修改,否則可能會(huì)使應(yīng)用程序無(wú)法啟動(dòng)
二罪裹、獲取沙盒目錄
1饱普、獲取到沙盒的根目錄
NSString *homePath = NSHomeDirectory();
2延柠、獲取Documents目錄
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString *docPath = [paths lastObject];
3惹苗、獲取Library中的Cache
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory,NSUserDomainMask, YES);
NSString *docPath = [paths lastObject];
4、獲取tmp路徑
NSString *temp = NSTemporaryDirectory();
5惶凝、獲取程序包文件路徑
[[NSBundle mainBundle] resourcePath
三峡继、NSString類路徑處理方法
有些時(shí)候我們需要對(duì)獲取到的文件目錄做一些特殊處理冯袍,常用的方法有以下幾個(gè):
比如針對(duì):
NSString *path = @"/Users/apple/testfile.text";
//獲得組成此路徑的各個(gè)組成部分,結(jié)果:(“/”,” Users”, “apple”, ”testfile.text”)
- (NSArray *)pathComponents;
// 提取路徑的最后一個(gè)組成部分,結(jié)果:testfile.text
- (NSString *)lastPathComponent;
// 刪除路徑的最后一個(gè)組成部分康愤,結(jié)果:/Users/apple
- (NSString *)stringByDeletingLastPathComponent;
// 將path添加到現(xiàn)有路徑的末尾儡循,結(jié)果:/Users/apple/testfile.text/app.text
- (NSString *)stringByAppendingPathComponent:(NSString *)str;
// 取路徑最后部分的擴(kuò)展名,結(jié)果:text
- (NSString *)pathExtension;
// 刪除路徑最后部分的擴(kuò)展名翘瓮,結(jié)果:/Users/apple/testfile
- (NSString *)stringByDeletingPathExtension;
// 路徑最后部分追加擴(kuò)展名贮折,結(jié)果:/Users/apple/testfile.text.jpg
- (NSString *)stringByAppendingPathExtension:(NSString *)str;
四、NSData的基本概念
NSData是用來(lái)包裝數(shù)據(jù)用的
NSData存儲(chǔ)的是二進(jìn)制數(shù)據(jù)资盅,這樣就屏蔽了數(shù)據(jù)之間的差異调榄,文本、音頻呵扛、圖像等數(shù)據(jù)都可以用NSData來(lái)存儲(chǔ)
NSMutableData繼承NSData類每庆,可以對(duì)該對(duì)象進(jìn)行數(shù)據(jù)修改
//string ---> data
NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
//data ---> string
NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
(10)
一、KVC(key value code)的基本概念和用法? 1今穿、基本概念? ? ? ? 1)鍵-值編碼是一個(gè)用于間接訪問(wèn)對(duì)象屬性的機(jī)制缤灵,使用該機(jī)制不需要調(diào)用存取方法和變量實(shí)例就可以訪問(wèn)對(duì)象屬性? ? ? 2)通過(guò)KVC可以給readonly的屬性賦值,? ? ? 3)如果對(duì)象屬性為基本數(shù)據(jù)類型時(shí)蓝晒,我們存的時(shí)候需要將數(shù)據(jù)封裝為NSNumber類型腮出,系統(tǒng)內(nèi)部存取時(shí),系統(tǒng)會(huì)自動(dòng)封裝/解封? ? ? 4)如果沒有用@property聲明芝薇,他講在內(nèi)部查找名為_key或key的實(shí)例變量? ? ? 5)路徑? ? ? 除了通過(guò)鍵值設(shè)置值外胚嘲,鍵/值編碼還支持指定路徑,通過(guò).號(hào)隔開? ? ? 6)一對(duì)多的關(guān)系? ? ? 如果向NSArray請(qǐng)求一個(gè)鍵值洛二,它實(shí)際上會(huì)查詢數(shù)組中的每個(gè)對(duì)象來(lái)查找這個(gè)鍵值馋劈,然后將查詢結(jié)果打包到另一個(gè)數(shù)組中并返回給你。? ? ? 7)可以應(yīng)用字符做簡(jiǎn)單運(yùn)算晾嘶,sum/min/max/avg/count? ? ? 8)存取值格式? ? ? ? 存值? ? ? ? ? setValue:forKey:? ? ? ? ? setValue:forKeyPath:? ? ? ? 取值? ? ? ? ? valueForKey:? ? ? ? ? valueForKeyPath:? 2妓雾、適用情況:將服務(wù)器的內(nèi)容轉(zhuǎn)化為數(shù)據(jù)模型,能夠簡(jiǎn)化代碼? 3垒迂、練習(xí)? ? ? 定義一個(gè)Person對(duì)象械姻,他叫喬布斯,他有許多蘋果設(shè)備:? ? ? 1個(gè)macbook,價(jià)格8000? ? ? 1個(gè)iPhone, 價(jià)格5000? ? ? 1個(gè)iPad, 價(jià)格3800? ? ? 使用kvc為Person設(shè)置名字机断, 使用kvc計(jì)算喬布斯所有設(shè)備的總價(jià)策添。? ? 二、KVO(Key-Value-Observer)的基本概念和用法? ? 1毫缆、基本概念? ? ? 一種使對(duì)象獲取其他獨(dú)享的特定屬性變化的通知機(jī)制? ? 2唯竹、適用情況? ? ? 主要用于試圖,交互方面苦丁,比如界面的某些數(shù)據(jù)變化了浸颓,界面的顯示也需要跟著變化,就需要建立數(shù)據(jù)和界面的關(guān)聯(lián)? ? 3、實(shí)現(xiàn)步驟? ? ? 1)采用下面這個(gè)方法給屬性添加觀察者,在哪里注冊(cè)觀察者就要在哪里移除觀察者? ? ? ? ? - (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(nullable void *)context;? ? ? 2)觀察者實(shí)現(xiàn)下面方法产上,如果監(jiān)聽的屬性發(fā)生變化棵磷,便會(huì)調(diào)用該方法。? ? ? ? ? - (void)observeValueForKeyPath:(nullable NSString *)keyPath ofObject:(nullable id)object change:(nullable NSDictionary*)change context:(nullable void *)context;
3)個(gè)人習(xí)慣在delloc中釋放
- (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath context:(nullable void *)context;
4晋涣、練習(xí):
監(jiān)聽狗的動(dòng)作仪媒,做相應(yīng)的回應(yīng)
三、通知的基本概念和用法
1谢鹊、基本概念
1)一種一對(duì)多的信息廣播機(jī)制算吩,一個(gè)應(yīng)用程序同時(shí)只能有一個(gè)NSNotificationCenter對(duì)象
2)任何人都可以發(fā)送任何消息到消息中心,識(shí)別感興趣通知的標(biāo)示就是object+通知名稱
2佃扼、適用情況
類與類之間傳遞信息
3偎巢、實(shí)現(xiàn)步驟
1)添加通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(paySalary) name:@"發(fā)工資啦" object:nil];
2)實(shí)現(xiàn)添加通知時(shí)方法選擇器選擇的方法
3)在需要發(fā)送通知的類中采用下面方法發(fā)送通知,發(fā)送成功便會(huì)執(zhí)行步驟二實(shí)現(xiàn)的方法
[[NSNotificationCenter defaultCenter] postNotificationName:@"發(fā)工資啦" object:nil];
4)移除通知
[[NSNotificationCenter defaultCenter] postNotificationName:nil object:nil userInfo:nil];
(11)
一兼耀、歸檔的基本概念? 之前將數(shù)據(jù)保存本地压昼,只能是字符串、數(shù)組瘤运、字典窍霞、NSNumber、BOOL等容器類對(duì)象對(duì)象拯坟,不能將所有對(duì)象都給保存官撼,而采用歸檔能將所有的對(duì)象轉(zhuǎn)化為二進(jìn)制數(shù)據(jù)保存在文件中,并通過(guò)解歸檔讓將文件里面保存的數(shù)據(jù)讀取出來(lái)二似谁、使用環(huán)境? ? 之前我們給通訊錄添加一個(gè)聯(lián)系人只能是將添加的人放到一個(gè)字典中,然后將這個(gè)字典放到數(shù)組中掠哥,最終將數(shù)組寫入文件中? ? 當(dāng)我們需要顯示這些聯(lián)系人時(shí)巩踏,要從文件中將這個(gè)數(shù)組讀取出來(lái),還要將數(shù)據(jù)里面的一個(gè)個(gè)字典轉(zhuǎn)化成model,放到一個(gè)新數(shù)組里? ? 而現(xiàn)在我們可以使用歸檔在添加的時(shí)候就將這一個(gè)個(gè)聯(lián)系人的信息轉(zhuǎn)化成model续搀,將這些model直接放到一個(gè)數(shù)組里塞琼,需要展示的時(shí)候,在從文件中讀取出來(lái)數(shù)據(jù)禁舷,此時(shí)這個(gè)數(shù)組里面存放直接就是一個(gè)個(gè)model? ? 有些應(yīng)用支持一個(gè)離線緩存彪杉,也就是說(shuō)當(dāng)手機(jī)沒聯(lián)網(wǎng)時(shí),可以將手機(jī)有網(wǎng)時(shí)的數(shù)據(jù)存放在本地牵咙,當(dāng)手機(jī)沒網(wǎng)時(shí)派近,從本地中取出來(lái)這些數(shù)據(jù)展示? ? 三、某個(gè)對(duì)象支持歸檔解歸檔需要滿足三個(gè)條件? 1洁桌、所屬的類遵守NSCoding協(xié)議? 2渴丸、實(shí)現(xiàn)協(xié)議里面的歸檔方法? ? ? - (void)encodeWithCoder:(NSCoder *)aCoder? 3、實(shí)現(xiàn)協(xié)議里面的解歸檔方法? ? ? - (nullable instancetype)initWithCoder:(NSCoder *)aDecoder四、對(duì)系統(tǒng)的類進(jìn)行歸檔解歸檔? ? 1谱轨、指定將對(duì)象放在哪個(gè)文件中戒幔,歸檔后的文件,后綴要求是archiver? ? ? [NSHomeDirectory() stringByAppendingPathComponent:@"data.archiver"];? ? 2土童、將對(duì)象歸檔到指定的路徑中? ? ? [NSKeyedArchiver archiveRootObject:name toFile:path];? ? 3诗茎、將歸檔后的數(shù)據(jù)提取出來(lái)? ? ? [NSKeyedUnarchiver unarchiveObjectWithFile:path];五、對(duì)自定義的類進(jìn)行歸檔與解歸檔? ? 1献汗、讓這個(gè)類遵循2敢订、實(shí)現(xiàn)歸檔方法,aCoder就是歸檔時(shí)傳過(guò)來(lái)的歸檔對(duì)象,對(duì)象被歸檔時(shí)會(huì)調(diào)用這個(gè)方法? ? ? - (void)encodeWithCoder:(NSCoder *)aCoder{? ? ? ? ? ? [aCoder encodeObject:self.name forKey:@"name"];? ? ? ? [aCoder encodeInteger:self.age forKey:@"age"];? ? ? ? [aCoder encodeObject:self.sex forKey:@"sex"];? ? ? }? ? 3雀瓢、實(shí)現(xiàn)解歸檔方法枢析,對(duì)象解歸檔是會(huì)調(diào)用這個(gè)方法? ? ? - (instancetype)initWithCoder:(NSCoder *)aDecoder{? ? ? ? ? //解歸檔時(shí)會(huì)產(chǎn)生一個(gè)Person對(duì)象,這里是給這個(gè)Person對(duì)象賦值? ? ? self = [super init];? ? ? ? ? ? if (self) {? ? ? ? ? ? ? ? self.name = [aDecoder decodeObjectForKey:@"name"];? ? ? ? self.age = [aDecoder decodeIntegerForKey:@"age"];? ? ? ? self.sex = [aDecoder decodeObjectForKey:@"sex"];? ? ? }? ? ? ? return self;? ? }六刃麸、同時(shí)將多個(gè)對(duì)象歸檔與解歸檔? ? 1醒叁、歸檔? ? ? 1)準(zhǔn)備一個(gè)可變的data對(duì)象,通過(guò)歸檔對(duì)象將多個(gè)數(shù)據(jù)存在一個(gè)data對(duì)象里泊业,最終將這個(gè)data寫入文件? ? ? ? NSMutableData *data = [NSMutableData data];? ? ? 2)archiver初始化的時(shí)候包裝一個(gè)可變的data對(duì)象? ? ? ? NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc]initForWritingWithMutableData:data];? ? ? 3)通過(guò)歸檔對(duì)象將這些數(shù)據(jù)轉(zhuǎn)化成二進(jìn)制把沼,并保存在一個(gè)data對(duì)象里? ? ? ? [archiver encodeObject:name forKey:@"name"];? ? ? ? [archiver encodeInteger:age forKey:@"age"];? ? ? ? [archiver encodeObject:sex forKey:@"sex"];? ? ? 4)轉(zhuǎn)化完畢,意思是結(jié)束使用歸檔對(duì)象將上面的數(shù)據(jù)保存在了data里面? ? ? ? [archiver finishEncoding];? ? ? 5)將轉(zhuǎn)化好的data寫入文件? ? ? ? [data writeToFile:path atomically:YES];? ? 2吁伺、解歸檔? ? ? 1)將路徑里的二進(jìn)制數(shù)據(jù)給取出來(lái)? ? ? ? ? ? ? ? NSMutableData *data = [NSMutableData dataWithContentsOfFile:path];? ? ? 2)將二進(jìn)制數(shù)據(jù)包裝在一個(gè)解歸檔對(duì)象中? ? ? ? NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc]initForReadingWithData:data];? ? ? 3)通過(guò)解歸檔對(duì)象將二進(jìn)制數(shù)據(jù)分別給反序列化? ? ? ? ? ? NSString *name = [unarchiver decodeObjectForKey:@"name"];? ? ? ? ? ? NSInteger age = [unarchiver decodeIntegerForKey:@"age"];? ? ? ? ? ? NSString *sex = [unarchiver decodeObjectForKey:@"sex"];七饮睬、練習(xí)? 1、模擬網(wǎng)絡(luò)數(shù)據(jù)進(jìn)行本地緩存? ? 1)修改新工程自帶的ViewController.h 如下? ? ? #import@interface ViewController : UITableViewController? ? ? @end? ? 2)在AppDelegate.m里面自定義window,? ? ? self.window = [[UIWindow alloc]initWithFrame:[UIScreen mainScreen].bounds];? ? ? [self.window makeKeyAndVisible];? ? ? //報(bào)錯(cuò)后篮奄,記得導(dǎo)入ViewController? #import "ViewController.h"? ? ? self.window.rootViewController = [[UINavigationController alloc]initWithRootViewController:[[ViewController alloc]init]];? ? 3)新建一個(gè)InfoModel類捆愁,? ? ? InfoModel.h? ? ? ? #import//對(duì)象要?dú)w檔必須要遵守NSCoding協(xié)議? ? ? ? @interface InfoModel : NSObject@property(nonatomic,copy) NSString *name;
@property(nonatomic,copy) NSString *phone;
@end
InfoModel.m
#import "InfoModel.h"
@implementation InfoModel
- (void)encodeWithCoder:(NSCoder *)aCoder{
[aCoder encodeObject:self.name forKey:@"name"];
[aCoder encodeObject:self.phone forKey:@"phone"];
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder{
self = [super init];
if (self) {
self.name = [aDecoder decodeObjectForKey:@"name"];
self.phone = [aDecoder decodeObjectForKey:@"phone"];
}
return self;
}
@end
4) ViewController.m
#import "ViewController.h"
#import "InfoModel.h"
//報(bào)錯(cuò),將課件中的MJExtension文件夾拖到工程中
#import "MJExtension.h"
//模擬本地緩存路徑
#define kLocalPath [NSHomeDirectory() stringByAppendingPathComponent:@"data.archiver"]
//模擬服務(wù)器路徑
#define kServerPath [[NSBundle mainBundle] pathForResource:@"Connect" ofType:@"plist"]
@interface ViewController ()
{
NSMutableArray *dataArray;
}
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self loadData];
}
- (void)loadData{
//準(zhǔn)備數(shù)據(jù)
dataArray = [self fetchData];
if(dataArray == nil){
NSLog(@"請(qǐng)檢查網(wǎng)絡(luò)設(shè)置");
return;
}
[self.tableView reloadData];
}
- (NSMutableArray *)fetchData{
//1窟却、先從服務(wù)器獲取數(shù)據(jù)
NSMutableArray *tempArray = [NSMutableArray arrayWithContentsOfFile:kServerPath];
if (tempArray == nil) {
//2昼丑、如果從服務(wù)器獲取數(shù)據(jù)失敗,則從本地緩存中讀取數(shù)據(jù)
tempArray = [NSKeyedUnarchiver unarchiveObjectWithFile:kLocalPath];
}else{
//3、如果從服務(wù)器獲取數(shù)據(jù)成功夸赫,則將數(shù)據(jù)通過(guò)MJExtension框架菩帝,轉(zhuǎn)化為model
tempArray = [InfoModel mj_objectArrayWithKeyValuesArray:tempArray];
//4、將最新從服務(wù)器獲取到數(shù)據(jù)保存到本地
[NSKeyedArchiver archiveRootObject:tempArray toFile:kLocalPath];
}
return tempArray;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return dataArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *cellID = @"cellID";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellID];
}
InfoModel *model = dataArray[indexPath.row];
cell.textLabel.text = model.name;
cell.detailTextLabel.text = model.phone;
return cell;
}
@end
(12)
一茬腿、基本概念
全稱是Grand Central Dispath呼奢,純C語(yǔ)言,提供非常多強(qiáng)大的函數(shù)切平,是目前蘋果官網(wǎng)推薦的多線程開發(fā)方式握础,NSOperation便是基于GCD的封裝
二、GCD的優(yōu)勢(shì)所在
1悴品、為多核的并行運(yùn)算提出了解決方案
2弓候、GCD會(huì)自動(dòng)利用更多的CPU內(nèi)核郎哭,比如雙核、四核
3菇存、GCD會(huì)自動(dòng)管理線程的生命周期(創(chuàng)建線程夸研、調(diào)度任務(wù)、銷毀線程)
4依鸥、程序員只需要告訴GCD想要執(zhí)行什么任務(wù)亥至,不需要編寫任何線程管理代碼
三、GCD中有2個(gè)核心概念
1贱迟、隊(duì)列:用來(lái)存放任務(wù)
1)串行隊(duì)列
只有一個(gè)線程姐扮,加入到隊(duì)列中的操作按添加順序依次執(zhí)行,一個(gè)任務(wù)執(zhí)行完畢后衣吠,才能再執(zhí)行下一個(gè)任務(wù)
2)并發(fā)隊(duì)列
有多個(gè)線程茶敏,操作進(jìn)來(lái)以后會(huì)將這些線程安排在可用的處理器上,同時(shí)保證先進(jìn)來(lái)的任務(wù)優(yōu)先處理
PS:GCD中還有一個(gè)特殊隊(duì)列就是主隊(duì)列缚俏,用來(lái)執(zhí)行主線程的操作任務(wù)
2惊搏、任務(wù):放在隊(duì)列中執(zhí)行
1)同步執(zhí)行
只能在當(dāng)前線程中執(zhí)行任務(wù),不具備開啟新線程的能力
2)異步執(zhí)行
可以在新的線程中執(zhí)行任務(wù)忧换,具備開啟新線程的能力恬惯。
四、GCD做多線程開發(fā)可以抽象成兩步
1亚茬、找到隊(duì)列
1)找到更新UI的主線程所在的隊(duì)列
dispatch_queue_t mainQueue= dispatch_get_main_queue();
2) 創(chuàng)建隊(duì)列
dispatch_queue_t serialQueue = dispatch_queue_create("mySerialQueue", DISPATCH_QUEUE_SERIAL);
第一個(gè)參數(shù):隊(duì)列名字
第二個(gè)參數(shù):隊(duì)列類類型
并行隊(duì)列:DISPATCH_QUEUE_CONCURRENT
串行隊(duì)列:DISPATCH_QUEUE_SERIAL
3)系統(tǒng)內(nèi)部給我們提供有一個(gè)現(xiàn)成的并發(fā)全局隊(duì)列
dispatch_queue_t queue = dispatch_get_global_queue(0 , 0);
第一個(gè)參數(shù):線程的優(yōu)先級(jí), DISPATCH_QUEUE_PRIORITY_BACKGROUND是最低的酪耳。
第二個(gè)參數(shù):系統(tǒng)保留的參數(shù),永遠(yuǎn)傳0
2刹缝、在隊(duì)列中確定想做的事
1) 使用同步的方式
dispatch_sync(queue, ^{
});
2)使用異步的方式
dispatch_async(queue, ^{
});
五碗暗、GCD創(chuàng)建的線程任務(wù)有四種執(zhí)行方式
1、串行隊(duì)列同步執(zhí)行任務(wù)
dispatch_queue_t serialQueue = dispatch_queue_create("serialQueue", DISPATCH_QUEUE_SERIAL);
dispatch_sync(serialQueue, ^{
NSLog(@"-%@",[NSThread currentThread]);
});
dispatch_sync(serialQueue, ^{
NSLog(@"1 - %@", [NSThread currentThread]);
});
dispatch_sync(serialQueue, ^{
NSLog(@"2 - %@", [NSThread currentThread]);
});
dispatch_sync(serialQueue, ^{
NSLog(@"3 - %@", [NSThread currentThread]);
});
同步不具有開辟新線程的能力梢夯,不會(huì)開辟新的線程去執(zhí)行任務(wù)言疗,會(huì)在當(dāng)前線程中順序執(zhí)行任務(wù)。
2厨疙、串行隊(duì)列異步執(zhí)行任務(wù)
dispatch_queue_t serialQueue1 = dispatch_queue_create("serialQueue1", DISPATCH_QUEUE_SERIAL);
dispatch_async(serialQueue1, ^{
NSLog(@"1 = %@",[NSThread currentThread]);
});
dispatch_async(serialQueue1, ^{
NSLog(@"2 = %@",[NSThread currentThread]);
});
dispatch_async(serialQueue1, ^{
NSLog(@"3 = %@",[NSThread currentThread]);
});
異步具有創(chuàng)建新線程的能力,會(huì)開辟新的線程去執(zhí)行任務(wù)疑务,但由于是串行沾凄,里面只能創(chuàng)建一個(gè)線程,所以還是會(huì)按順序執(zhí)行
3知允、并行隊(duì)列同步執(zhí)行任務(wù)
dispatch_queue_t concurrentQueue = dispatch_queue_create("concurrentQueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_sync(concurrentQueue, ^{
NSLog(@"1 = %@",[NSThread currentThread]);
});
dispatch_sync(concurrentQueue, ^{
NSLog(@"2 = %@",[NSThread currentThread]);
});
dispatch_sync(concurrentQueue, ^{
NSLog(@"3 = %@",[NSThread currentThread]);
});
同步不具有創(chuàng)建新線程的能力撒蟀,不會(huì)開辟新的線程去執(zhí)行任務(wù),會(huì)在當(dāng)前線程去執(zhí)行任務(wù)
4温鸽、并發(fā)隊(duì)列異步執(zhí)行任務(wù)(常用)
dispatch_queue_t concurrentQueue1 = dispatch_queue_create("concurrentQueue", DISPATCH_QUEUE_CONCURRENT);
dispatch_async(concurrentQueue1, ^{
NSLog(@"1 = %@",[NSThread currentThread]);
});
dispatch_async(concurrentQueue1, ^{
NSLog(@"2 = %@",[NSThread currentThread]);
});
dispatch_async(concurrentQueue1, ^{
NSLog(@"3 = %@",[NSThread currentThread]);
});
并行隊(duì)列可以里可以有多個(gè)線程保屯,同步執(zhí)行的方式又可以開辟多個(gè)線程手负,所以這里實(shí)現(xiàn)了多個(gè)線程并行執(zhí)行,沒有按照順序
六、GCD組的應(yīng)用
GCD中可以將一組相關(guān)聯(lián)的操作姑尺,定義到一個(gè)群組中
定義到群組中之后竟终,當(dāng)所有線程完成時(shí),可以獲得通知
0切蟋、創(chuàng)建全局隊(duì)列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
1统捶、定義群組
dispatch_group_t group = dispatch_group_create();
2、定義群組的異步任務(wù)
dispatch_group_async(group, queue, ^{
});
dispatch_group_async(group, queue, ^{
});
3柄粹、群組任務(wù)完成通知
dispatch_group_notify(group, queue, ^{
});
1)dispatch_group_notify可以監(jiān)聽一組任務(wù)是否完成喘鸟。這個(gè)方法很有用,比如你執(zhí)行三個(gè)下載任務(wù)驻右,當(dāng)三個(gè)任務(wù)都下載完成后什黑,才通知界面說(shuō)已經(jīng)完成
2)如果不需要監(jiān)聽一組任務(wù),可以直接使用dispatch_async方法
六堪夭、線程鎖
1愕把、在多線程應(yīng)用中,所有被搶奪資源的屬性需要設(shè)置為原子屬性,atomic屬性茵瘾,必須與@synchronized(同步鎖)一起使用
2礼华、系統(tǒng)會(huì)在多線程搶奪時(shí),保證該屬性有且僅有一個(gè)線程能夠訪問(wèn)
3拗秘、操作步驟
1)將資源屬性設(shè)置原子屬性
2)將處理該屬性的代碼放到線程鎖中
@synchronized (self) {
}
-------------------------------------------------------------------
歡迎點(diǎn)贊收藏圣絮,喜歡的話就關(guān)注我,一起共勉雕旨,學(xué)習(xí)進(jìn)步