OC的理解與特性
OC作為一門面向?qū)ο蟮恼Z言,自然具有面向?qū)ο蟮恼Z言特性:封裝溉奕、繼承忍啤、多態(tài)。它既具有靜態(tài)語言的特性(如C++)同波,又有動態(tài)語言的效率(動態(tài)綁定、動態(tài)加載等)卫枝《锟妫總體來講吆玖,OC確實是一門不錯的編程語言,多態(tài):不同對象以自己的方式響應(yīng)相同的消息的能力叫做多態(tài)怜奖。意思就是假設(shè)生物類(life)都用有一個相同的方法-eat;
Objective-C具有相當(dāng)多的動態(tài)特性翅阵,表現(xiàn)為三方面:動態(tài)類型(Dynamic typing)迁央、動態(tài)綁定(Dynamic binding)和動態(tài)加載(Dynamic loading)岖圈。動態(tài)——必須到運行時(run time)才會做的一些事情钙皮。
動態(tài)類型:即運行時再決定對象的類型,這種動態(tài)特性在日常的應(yīng)用中非常常見导匣,簡單來說就是id類型茸时。事實上,由于靜態(tài)類型的固定性和可預(yù)知性厕氨,從而使用的更加廣泛汹粤。靜態(tài)類型是強類型,而動態(tài)類型屬于弱類型嘱兼,運行時決定接受者。
動態(tài)綁定:基于動態(tài)類型汇四,在某個實例對象被確定后踢涌,其類型便被確定了,該對象對應(yīng)的屬性和響應(yīng)消息也被完全確定背苦。
動態(tài)加載:根據(jù)需求加載所需要的資源潘明,最基本就是不同機型的適配,例如厚宰,在Retina設(shè)備上加載@2x的圖片遂填,而在老一些的普通蘋設(shè)備上加載原圖澈蝙,讓程序在運行時添加代碼模塊以及其他資源碉克,用戶可根據(jù)需要加載一些可執(zhí)行代碼和資源并齐,而不是在啟動時就加載所有組件,可執(zhí)行代碼可以含有和程序運行時整合的新類撕贞。
autorelease:即延遲釋放测垛。
自動釋放池的作用:在程序執(zhí)行完畢即池子即將銷毀的時候會對池子中所有調(diào)用autorelease的對象進(jìn)行一次release操作。
面試題一:自動釋放池什么時候創(chuàng)建食侮,什么時候銷毀?
每一次運行循環(huán)執(zhí)行后链快,也就是每當(dāng)事件被觸發(fā)時都會創(chuàng)建自動釋放池眉尸。在程序執(zhí)行的過程中,所有autorelease的對象在出了作用域之后會被添加到最近創(chuàng)建的自動釋放池中霉祸。運行循環(huán)結(jié)束前會釋放自動釋放池袱蜡,還有池子滿了也會銷毀。
其工作原理是:自動釋放池被銷毀或耗盡時會向池中的所有對象發(fā)送release消息奔穿,釋放所有autorelease對象迅细。
自動釋放池常見面試題代碼
for (int i = 0; i < 100000; ++i) {
NSString *str = @"Hello World";
str = [str stringByAppendingFormat:@"- %d",i];? //字符串拼接
? str = [str uppercaseString];? //將字符串替換成大寫
}
如果循環(huán)的次數(shù)過大淘邻,會出現(xiàn)什么問題?該怎么解決统阿?
? 會出現(xiàn)內(nèi)存溢出,循環(huán)內(nèi)部創(chuàng)建大量的臨時對象扶平,沒有被釋放
? 每次循環(huán)都將上一次創(chuàng)建的對象release
for(inti =0; i <100000; ++i) {
? ? ? @autoreleasepool{
NSString*str =@"Hello World";
str = [strstringByAppendingFormat:@"- %d",i];
str = [struppercaseString];
? ? }
? ? }
不會自動管理內(nèi)存的情況?
編譯器不會自動管理CoreFoundation框架的數(shù)據(jù)類型對象的生命周期哥谷,因此使用CoreFoundation框架直接橋接數(shù)據(jù)類型麻献,就必須手動管理這些對象的內(nèi)存
AFNetwork
AF底層基于 NSURlsession? (session:會議)
AF的五個功能模塊
1.網(wǎng)絡(luò)通信 (AFURLsessionManager)(Manager:管理)
2.網(wǎng)絡(luò)通訊安全
3.網(wǎng)絡(luò)狀態(tài)監(jiān)聽
4.網(wǎng)絡(luò)通訊序列化反序列化
5.對UIkit的封裝
AF的實現(xiàn)流程
通過AFHTTPRequestOperationManager---->(確定請求方式 get ,post ,請求參數(shù))----->給到AFURLRequestSerialization(Serialization:序列化;進(jìn)行參數(shù)拼接)----->AFHTTPRequestOperation(Operation:經(jīng)營,計算监婶;下放到請求隊列 NSOperationQueue中)---->最后由最底層的AFURLconnectionOperation (去完成請求齿桃,做https認(rèn)證)--->數(shù)據(jù)返回到AFhttpRequestOperation----->通過AFURLResponseSerialization (Response [r?'sp?ns] 響應(yīng))--->進(jìn)行數(shù)據(jù)解析成json xml格式? 返回到AFHTTPRequestOperationManager中
1、帶block形式带污, 內(nèi)部是任務(wù)隊列進(jìn)行下載 香到,就是對operation的一個封裝下載。
2雷绢、還對uikit 內(nèi)部的類進(jìn)行類別形式添加方法(異步下載圖片)理卑。
3、還可以檢測網(wǎng)絡(luò)狀態(tài)藐唠。
多線程:
GCD 與 NSOperation 的區(qū)別:NSThread
GCD 和 NSOperation 都是用于實現(xiàn)多線程:
GCD 基于C語言的底層API,GCD主要與block結(jié)合使用踪宠,代碼簡潔高效妈嘹。
NSOperation 屬于Objective-C類,是基于GCD更高一層的封裝柬脸。復(fù)雜任務(wù)一般用NSOperation實現(xiàn)。
performSelectorOnMainThread:
使用NSOperation的情況:各個操作之間有依賴關(guān)系灾测、操作需要取消暫停垦巴、并發(fā)管理、控制操作之間優(yōu)先級蛾号,限制同時能執(zhí)行的線程數(shù)量.讓線程在某時刻停止/繼續(xù)等涯雅。
使用GCD的情況:一般的需求很簡單的多線程操作,用GCD都可以了活逆,簡單高效。
CGD :1.充分利用設(shè)備的多核最高效 2.自動管理線程的生命周期3.CGD 是先進(jìn)先出的 4.基于c實現(xiàn)
NSoperation:? 1.基于GCD 封裝的 使用更加面向?qū)ο?2.可以改變隊列的執(zhí)行順序3.比GCD多了一些簡單實用的功能
GCD 的方法1.獲取全局并行隊列? dipatch _ get_grolop_queue
? ? ? ? ? ? ? ? ? ? 2.獲取主隊列? dispatch_get_main_queue? ? ? ? ? ?
? ? ? ? ? ? ? ? ? ? 3.創(chuàng)建串行行隊列? dispatch _queue_serial
? ? ? ? ? ? ? ? ? 4.創(chuàng)建并行行隊列? dispatch _queue_concurrent [k?n'k?r(?)nt]
? ? ? ? ? ? ? ? ? 5.延遲提交? dispatch_after【啊 f t】
? ? ? ? ? ? ? ? ? ? dispatch_time_t
? ? ? ? ? ? ? ? ? 6.行完成后 dispatch_group_notify
barrier【百瑞額】:表示柵欄怒允,當(dāng)在并發(fā)隊列里面使用柵欄時候纫事,柵欄之前的并發(fā)任務(wù)開始并發(fā)執(zhí)行,執(zhí)行完畢后丽惶,執(zhí)行柵欄內(nèi)的任務(wù)爬立,等柵欄任務(wù)執(zhí)行完畢后,再并發(fā)執(zhí)行柵欄后的任務(wù)抡秆。
Objective-C 中創(chuàng)建線程的方法是什么吟策?如果在主線程中執(zhí)行代碼,方法是什么着撩?如果想延時執(zhí)行代碼、方法又是什么睹酌?
答:線程創(chuàng)建有三種方法:使用NSThread創(chuàng)建剩檀、使用GCD的dispatch、使用子類化的NSOperation,然后將其加入NSOperationQueue;
NSOperation在主線程執(zhí)行代碼沪猴,方法是performSelectorOnMainThread,perform[執(zhí)行]
如果想延時執(zhí)行代碼可以用performSelector:onThread:withObject:waitUntilDone:
GCD:Main Dispatch Queue/Global Dispatch Queue? 主隊列特殊的串行壶辜、全局的并行隊列
dispatch? _after? 延遲執(zhí)行
FMDB
插入數(shù)據(jù)? @"insert into user (name, password) values(?, ?) ";表名 (字段1, 字段2...) values (值1, 值2...)担租;
刪除數(shù)據(jù) @"delete from user? where";
更新數(shù)據(jù) @"UPDATE USER SET id = ? WHERE? name = ?";
FMDatabaseQueue多線程安全:? 原理創(chuàng)建一個隊列(串行線程隊列),然后將放入的隊列的block順序執(zhí)行岭参,這樣避免了多線程同時訪問數(shù)據(jù)庫
設(shè)計模式
代理 ?單利 觀察者 MVC 工廠
單例模式: 一個類只有一個實例對象尝艘。
創(chuàng)建方法:GCD的一次函數(shù)(dispatch_once_t)通知中心就是單利
應(yīng)用場景 封裝FMDB 整個程序使用
工廠方法模式:定義創(chuàng)建對象的接口,讓子類決定實例化哪一個類秒际。工廠方法使得一個類的實例化延遲到其子類狡汉。
應(yīng)用場景 :多種樣式的cell 根據(jù)model 產(chǎn)出不同的cell布局
KVO: 的實現(xiàn)依賴于? Runtime實現(xiàn) . 當(dāng)某個類的屬性對象第一次被觀察時,系統(tǒng)就會在運行期動態(tài)地創(chuàng)建該類的一個派生類嵌莉,在這個派生類中重寫基類中任何被觀察屬性的setter 方法。派生類在被重寫的setter方法內(nèi)實現(xiàn)真正的通知機制
KVO 的鍵值觀察通知依賴于 NSObject 的兩個方法:willChangeValueForKey:和 didChangevlueForKey:
KVC:即鍵值編碼
1锐峭,對私有變量進(jìn)行賦值
2可婶,字典轉(zhuǎn)模型
當(dāng)觀察某對象 A 時,KVO 機制動態(tài)創(chuàng)建一個對象A當(dāng)前類的子類椎扬,并為這個新的子類重寫了被觀察屬性 keyPath 的 setter 方法。setter 方法隨后負(fù)責(zé)通知觀察對象屬性的改變狀況蚕涤。
Notification 通知
默認(rèn)是以同步的方式發(fā)送通知的;
異步發(fā)送通知:將通知加到通知隊列中茴丰,就可以將一個通知異步的發(fā)送到當(dāng)前的線程,這些方法調(diào)用后會立即返回贿肩,不用再等待通知的所有監(jiān)聽者都接收并處理完龄寞。
做多線程開發(fā)時,需要在線程調(diào)度方法中手動添加自動釋放池,尤其是當(dāng)執(zhí)行循環(huán)的時候溜哮,如果循環(huán)內(nèi)部有使用類的快速創(chuàng)建方法創(chuàng)建的對象色解, 一定要將循環(huán)體放到自動釋放池中。
Block:獲取其它函數(shù)局部變量的匿名函數(shù)
匿名函數(shù):沒有函數(shù)名的函數(shù)在抛,一對{}包裹的內(nèi)容是匿名函數(shù)的作用域,OC中的Block則可以用指針來直接調(diào)用一個函數(shù)刚梭;
雖然使用Block不用聲明類票唆,但是Block提供了類似Objective-C的類一樣可以通過成員變量來保存作用域外變量值的方法,那些在Block的一對{}里使用到但卻是在{}作用域以外聲明的變量衅金,就是Block截獲的自動變量簿煌。
block的注意點
1). 在block內(nèi)部使用外部指針且會造成循環(huán)引用情況下,需要用__week修飾外部指針:
__weak typeof(self) weakSelf = self;
2). 在block內(nèi)部如果調(diào)用了延時函數(shù)還使用弱指針會取不到該指針姨伟,因為已經(jīng)被銷毀了,需要在block內(nèi)部再將弱指針重新強引用一下夺荒。
__strong typeof(self) strongSelf = weakSelf;
3). 如果需要在block內(nèi)部改變外部棧區(qū)變量的話良蒸,需要在用__block修飾外部變量嫩痰。
__block在__main_block_func_0里面可以看到傳遞的是指針。所以成功改變了變量的值串纺。
什么時候在 block 中不需要使用 weakSelf
問題:我們知道仔燕,在使用 block 的時候魔招,為了避免產(chǎn)生循環(huán)引用,通常需要使用 weakSelf 與 strongSelf外恕,寫下面這樣的代碼:
__weaktypeof(self) weakSelf =self
;[selfdoSomeBlockJob:^{?
__strongtypeof(weakSelf) strongSelf = weakSelf;if(strongSelf)
{? ? ? ? ...? ? }}];
那么請問:什么時候在 block里面用self乡翅,不需要使用weakself?
當(dāng)block本身不被self 持有,而被別的對象持有蠕蚜,同時不產(chǎn)生循環(huán)引用的時候,就不需要使用weakself了腺毫。最常見的代碼就是UIView的動畫代碼挣柬,我們在使用UIView animateWithDuration:animations方法 做動畫的時候,并不需要使用weakself急黎,因為引用持有關(guān)系是:
UIView 的某個負(fù)責(zé)動畫的對象持有block,block 持有了self因為 self 并不持有 block勃教,所以就沒有循環(huán)引用產(chǎn)生匠抗,因為就不需要使用 weak self 了。
[UIView animateWithDuration:0.2 animations:^{
? ? self.alpha = 1;
}];
當(dāng)動畫結(jié)束時心软,UIView會結(jié)束持有這個 block,如果沒有別的對象持有block的話删铃,block 對象就會釋放掉,從而 block會釋放掉對于 self 的持有猎唁。整個內(nèi)存引用關(guān)系被解除。
Block不允許修改外部變量的值腐魂,這里所說的外部變量的值逐纬,指的是棧中指針的內(nèi)存地址。__block 所起到的作用就是只要觀察到該變量被 block 所持有兔毒,就將“外部變量”在棧中的內(nèi)存地址放到了堆中甸箱。進(jìn)而在block內(nèi)部也可以修改外部變量的值。
介紹一下分類芍殖,能用分類做什么?內(nèi)部是如何實現(xiàn)的龟梦?它為什么會覆蓋掉原來的方法肯适?
category:我們可以給類或者系統(tǒng)類添加實例方法方法。我們添加的實例方法框舔,會被動態(tài)的添加到類結(jié)構(gòu)里面的methodList列表里面。categort
類別 (category)和擴展(Extension) 繼承
使用分類(category)樱溉。
1.分類(category)的作用
1.1作用:可以在不修改原來類的基礎(chǔ)上纬凤,為一個類擴展方法。
1.2最主要的用法:給系統(tǒng)自帶的類擴展方法挖帘。
1.類擴展(extension)是category的一個特例,有時候也被稱為匿名分類拇舀。他的作用是為一個類添加一些私有的成員變量和方法。
繼承:子類不僅擁有父類所有的屬性和方法骄崩,而且可以創(chuàng)建屬于自己的屬性和方法。
iOS手動局框架-Masonry
運用JavaScriptCore框架進(jìn)行交互
在iOS 7之后抠璃,apple添加了一個新的庫JavaScriptCore脱惰,用來做JS交互,因此JS與原生OC交互也變得簡單了許多枪芒。這是我做的一個例子
- (void)webViewDidFinishLoad:(UIWebView *)webView {
? ? self.webTitle = [self.webView stringByEvaluatingJavaScriptFromString:@"document.title"];
? [self needNavigationleftButtonTitle:nil RightButtonTiele:nil TitleLable:self.webTitle targat:self];
? ? self.jsContext = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
? ? self.jsContext[@"submitFrom"] = self;
? ? self.jsContext.exceptionHandler = ^(JSContext *context, JSValue *exceptionValue) {
? ? ? ? context.exception = exceptionValue;
? ? ? ? NSLog(@"異常信息:%@", exceptionValue);
? ? };
}
析核心動畫CoreAnimation
基礎(chǔ)動畫(CABaseAnimation)
關(guān)鍵幀動畫(CAKeyframeAnimation)
組動畫(CAAnimationGroup)
過渡動畫(CATransition)
Instruments提供了很多功能舅踪,我會重點介紹一下我最常用的幾類:
1.Time Profiler:CPU分析工具分析代碼的執(zhí)行時間良蛮。
2.Core Animation:離屏渲染,圖層混合等GPU耗時货徙。
3.Leaks:內(nèi)存檢測,內(nèi)存泄漏檢測工具痴颊。
4.Energy Log:耗電檢測工具屡贺。
5.Network:流量檢測工具。
棧區(qū)和堆區(qū)
棧區(qū)(stack)由編譯器自動分配釋放 ,存放方法(函數(shù))的參數(shù)值, 局部變量的值等泻仙,棧是向低地址擴展的數(shù)據(jù)結(jié)構(gòu),是一塊連續(xù)的內(nèi)存的區(qū)域玉转。即棧頂?shù)牡刂泛蜅5淖畲笕萘渴窍到y(tǒng)預(yù)先規(guī)定好的殴蹄。
堆區(qū)(heap)一般由程序員分配釋放, 若程序員不釋放,程序結(jié)束時由OS回收猾担,向高地址擴展的數(shù)據(jù)結(jié)構(gòu)垒探,是不連續(xù)的內(nèi)存區(qū)域,從而堆獲得的空間比較靈活圾叼。
碎片問題:對于堆來講捺癞,頻繁的new/delete勢必會造成內(nèi)存空間的不連續(xù),從而造成大量的碎片惕鼓,使程序效率降低。對于棧來講箱歧,則不會存在這個問題一膨,因為棧是先進(jìn)后出的隊列,他們是如此的一一對應(yīng)价淌,以至于永遠(yuǎn)都不可能有一個內(nèi)存塊從棧中間彈出.
全局區(qū)(靜態(tài)區(qū))(static),全局變量和靜態(tài)變量的存儲是放在一塊 的,初始化的全局變量和靜態(tài)變量在一塊區(qū)域, 未初始化的全局變量和未初始化的靜態(tài)變量在相鄰的另一塊區(qū)域瞒津。程序結(jié)束后有系統(tǒng)釋放。
文字常量區(qū)—常量字符串就是放在這里的巷蚪。程序結(jié)束后由系統(tǒng)釋放。
程序代碼區(qū)—存放函數(shù)體的二進(jìn)制代碼
CornerStone使用分享[康那思透恩]
CornerStone是mac下非常流行的一個SVN管理工具啦膜,mac版本svn管理中最推薦使用的一個前联。
用@property聲明的 NSString / NSArray / NSDictionary 經(jīng)常使用 copy 關(guān)鍵字,為什么似嗤?如果改用strong關(guān)鍵字,可能造成什么問題乘粒?
答:用 @property 聲明 NSString、NSArray轧铁、NSDictionary 經(jīng)常使用 copy 關(guān)鍵字,是因為他們有對應(yīng)的可變類型:NSMutableString齿风、NSMutableArray绑洛、NSMutableDictionary,他們之間可能進(jìn)行賦值操作(就是把可變的賦值給不可變的)脸候,為確保對象中的字符串值不會無意間變動,應(yīng)該在設(shè)置新屬性值時拷貝一份运沦。
1. 因為父類指針可以指向子類對象,使用 copy 的目的是為了讓本對象的屬性不受外界影響,使用 copy 無論給我傳入是一個可變對象還是不可對象,我本身持有的就是一個不可變的副本配深。
2. 如果我們使用是 strong ,那么這個屬性就有可能指向一個可變對象,如果這個可變對象在外部被修改了,那么會影響該屬性。
//總結(jié):使用copy的目的是薪寓,防止把可變類型的對象賦值給不可變類型的對象時澜共,可變類型對象的值發(fā)送變化會無意間篡改不可變類型對象原來的值锥腻。
@synthesize 和 @dynamic 分別有什么作用?
@property有兩個對應(yīng)的詞京革,一個是@synthesize(合成實例變量)幸斥,一個是@dynamic。
如果@synthesize和@dynamic都沒有寫甲葬,那么默認(rèn)的就是 @synthesize var = _var;
// 在類的實現(xiàn)代碼里通過 @synthesize 語法可以來指定實例變量的名字。(@synthesize var = _newVar;)
1. @synthesize 的語義是如果你沒有手動實現(xiàn)setter方法和getter方法坡垫,那么編譯器會自動為你加上這兩個方法。
2. @dynamic 告訴編譯器冰悠,屬性的setter與getter方法由用戶自己實現(xiàn),不自動生成(如溉卓,@dynamic var)。
如何對iOS設(shè)備進(jìn)行性能測試万栅?
答: Profile-> Instruments[in吹門特] ->Time Profiler
寫一個完整的代理西疤,包括聲明、實現(xiàn)
// 創(chuàng)建
@protocol MyDelagate
@required
-(void)eat:(NSString *)foodName;
@optional
-(void)run;
@end
//? 聲明 .h
@interface person: NSObject
@end
//? 實現(xiàn) .m
@implementation person
- (void)eat:(NSString *)foodName {
? NSLog(@"吃:%@!", foodName);
}
- (void)run {
? NSLog(@"run!");
}
@end
iOS的沙盒目錄結(jié)構(gòu)是怎樣的扰她?
沙盒結(jié)構(gòu):
1). Application:存放程序源文件,上架前經(jīng)過數(shù)字簽名徒役,上架后不可修改窖壕。
2). Documents:常用目錄,iCloud備份目錄鸳吸,存放數(shù)據(jù)。(這里不能存緩存文件晌砾,否則上架不被通過)
3). Library:
Caches:存放體積大又不需要備份的數(shù)據(jù)烦磁。(常用的緩存路徑)
Preference:設(shè)置目錄,iCloud會備份設(shè)置信息都伪。
4). tmp:存放臨時文件,不會被備份猬仁,而且這個文件下的數(shù)據(jù)有可能隨時被清除的可能。
介紹一下XMPP聋溜?
XMPP是一種以XML為基礎(chǔ)的開放式實時通信協(xié)議。
簡單的說撮躁,XMPP就是一種協(xié)議买雾,一種規(guī)定。就是說漓穿,在網(wǎng)絡(luò)上傳東西,XMM就是規(guī)定你上傳大小的格式叙赚。
冒泡排序
/**
* 【冒泡排序】:相鄰元素兩兩比較僚饭,比較完一趟,最值出現(xiàn)在末尾
* 第1趟:依次比較相鄰的兩個數(shù)鳍鸵,不斷交換(小數(shù)放前,大數(shù)放后)逐個推進(jìn)击罪,最值最后出現(xiàn)在第n個元素位置
* 第2趟:依次比較相鄰的兩個數(shù)贪薪,不斷交換(小數(shù)放前,大數(shù)放后)逐個推進(jìn)古掏,最值最后出現(xiàn)在第n-1個元素位置
* ……? ……
* 第n-1趟:依次比較相鄰的兩個數(shù),不斷交換(小數(shù)放前,大數(shù)放后)逐個推進(jìn)光涂,最值最后出現(xiàn)在第2個元素位置
*/
void bublleSort(int *arr, int length) {
? ? for(int i = 0; i < length - 1; i++) { //趟數(shù)
? ? ? ? for(int j = 0; j < length - i - 1; j++) { //比較次數(shù)
? ? ? ? ? ? if(arr[j] > arr[j+1]) {
? ? ? ? ? ? ? ? int temp = arr[j];
? ? ? ? ? ? ? ? arr[j] = arr[j+1];
? ? ? ? ? ? ? ? arr[j+1] = temp;
? ? ? ? ? ? }
? ? ? ? }
? ? }
}
熱更新
Weex
跨平臺,一套代碼钝计,iOS、Android都可以運行私恬。用前端語法實現(xiàn)原生效果。比React Native更好用疫衩。
weex基于vue.js荣德,ReactNative使用React。
ReactNative安裝配置麻煩涮瞻。 weex安裝cli之后就可以使用。
react模板JSX有一定的學(xué)習(xí)成本近顷,vue和常用的web開發(fā)類似,模板是普通的html窒升,數(shù)據(jù)綁定用mustache風(fēng)格家淤,樣式直接使用css。
四絮重、React Native
不像Weex能一套代碼多端運行,需要自己分別做修改青伤。
React Native 可以動態(tài)添加業(yè)務(wù)模塊,但無法做到修改原生OC代碼号杠。
JSPatch丰歌、lua 配合React Native可以讓一個原生APP時刻處于可擴展可修改的狀態(tài)。
UIImage初始化一張圖片有幾種方法立帖?簡述各自的優(yōu)缺點。
imageNamed:系統(tǒng)會先檢查系統(tǒng)緩存中是否有該名字的Image堂飞,如果有的話,則直接返回绰筛,如果沒有,則先加載圖像到緩存铝噩,然后再返回。
initWithContentsOfFile【文件的內(nèi)容】:系統(tǒng)不會檢查系統(tǒng)緩存讳窟,而直接從文件系統(tǒng)中加載并返回。
函數(shù)式編程
函數(shù)式編程總結(jié)
如果想再去調(diào)用別的方法丽啡,那么就需要返回一個對象硬猫;
如果想用()去執(zhí)行,那么需要返回一個block坑雅;
如果想讓返回的block再調(diào)用對象的方法,那么這個block就需要返回一個對象(即返回值為一個對象的block)裹粤。