iOS知識(shí)點(diǎn)集合

iOS程序運(yùn)行流程

  1. 系統(tǒng)調(diào)用app的main函數(shù)

  2. main函數(shù)調(diào)用UIApplicationMain.

  3. UIApplicationMain創(chuàng)建shared application instance, UIApplication默認(rèn)的instance.

  4. UIApplicationMain讀取Info.plist找到主nib文件, 加載nib,把shared application instance 設(shè)為nib的owner.

  5. 通過nib文件,創(chuàng)建app的獨(dú)立UIWindows object.

  6. 通過nib,實(shí)例化了程序的AppDelegate object.

  7. app內(nèi)部啟動(dòng)結(jié)束,application:didFinishLaunchingWith- Options: 被設(shè)定成 wAppDelegate instance.

  8. AppDelegate向UIWindow instance發(fā)makeKeyAndVisible消息, app界面展示給用戶. app準(zhǔn)備好接收用戶的操作指令.

簡(jiǎn)述應(yīng)用程序按Home鍵進(jìn)入后臺(tái)時(shí)的生命周期,以及從后臺(tái)回到前臺(tái)時(shí)的生命周期?

應(yīng)用程序的狀態(tài):

Not running 未運(yùn)行,程序沒啟動(dòng)
Inactive 未激活,程序在前臺(tái)運(yùn)行,不過沒接受到事件,沒有事件處理的狀態(tài)下通常處于這個(gè)狀態(tài)。
Active 激活 程序在前臺(tái)并且接收到了事件
Backgound 后臺(tái) 程序在后臺(tái)而且能執(zhí)行代碼,大多數(shù)程序進(jìn)入這個(gè)狀態(tài)后會(huì)在在這個(gè)狀態(tài)上停留一會(huì)。
Suspended 掛起 程序在后臺(tái)不能執(zhí)行代碼。

  • (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    //告訴代理進(jìn)程啟動(dòng)但還沒進(jìn)入狀態(tài)保存
  • (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    // 告訴代理啟動(dòng)基本完成程序準(zhǔn)備開始運(yùn)行
  • (void)applicationWillResignActive:(UIApplication *)application
    // 當(dāng)應(yīng)用程序?qū)⒁敕腔顒?dòng)狀態(tài)執(zhí)行,在此期間,應(yīng)用程序不接收消息或事件,比如來電話了
  • (void)applicationDidBecomeActive:(UIApplication *)application
    // 當(dāng)應(yīng)用程序入活動(dòng)狀態(tài)執(zhí)行,這個(gè)剛好跟上面那個(gè)方法相反
  • (void)applicationDidEnterBackground:(UIApplication *)application
    // 當(dāng)程序被推送到后臺(tái)的時(shí)候調(diào)用。所以要設(shè)置后臺(tái)繼續(xù)運(yùn)行,則在這個(gè)函數(shù)里面設(shè)置即可
  • (void)applicationWillEnterForeground:(UIApplication *)application
    //當(dāng)程序從后臺(tái)將要重新回到前臺(tái)時(shí)候調(diào)用,這個(gè)剛好跟上面的那個(gè)方法相反。
  • (void)applicationWillTerminate:(UIApplication *)application
    //當(dāng)程序?qū)⒁顺鍪潜徽{(diào)用,通常是用來保存數(shù)據(jù)和一些退出前的清理工作。這個(gè)需要要設(shè)置UIApplicationExitsOnSuspend的鍵值。
  • (void)applicationDidFinishLaunching:(UIApplication*)application
    //當(dāng)程序載入后執(zhí)行

描述應(yīng)用程序的啟動(dòng)順序?

1、程序入口main函數(shù)創(chuàng)建UIApplication實(shí)例和UIApplication代理實(shí)例
2、在UIApplication代理實(shí)例中重寫啟動(dòng)方法,設(shè)置第一ViewController
3、在第一ViewController中添加控件,實(shí)現(xiàn)對(duì)應(yīng)的程序界面。

參考鏈接:http://www.itdecent.cn/p/bdf3f20848b9

iOS本地?cái)?shù)據(jù)存儲(chǔ)都有哪幾種方式?iOS如何實(shí)現(xiàn)復(fù)雜對(duì)象的存儲(chǔ)?

NSKeyedArchiver(歸檔)采用歸檔的形式來保存數(shù)據(jù),該數(shù)據(jù)對(duì)象需要遵守NSCoding協(xié)議,并且該對(duì)象對(duì)應(yīng)的類必須提供encodeWithCoder:和initWithCoder:方法;
NSUserDefaults:用來保存應(yīng)用程序設(shè)置和屬性、用戶保存的數(shù)據(jù)。用戶再次打開程序或開機(jī)后這些數(shù)據(jù)仍然存在。NSUserDefaults可以存儲(chǔ)的數(shù)據(jù)類型包括:NSData、NSString、NSNumber、NSDate、NSArray、NSDictionary;
Write寫入方式:永久保存在磁盤中;
SQLite(FMDB、CoreData) ;
NSCoding + NSKeyedArchiver實(shí)現(xiàn)復(fù)雜對(duì)象的存儲(chǔ);

堆和棧的區(qū)別?

棧區(qū)(stack)--由編譯器自動(dòng)分配釋放,存放函數(shù)的參數(shù)值、局部變量的值。
堆區(qū)(heap)--一般由程序員分配釋放。
全局區(qū)(靜態(tài)區(qū))(static)--全局變量和靜態(tài)變量。程序結(jié)束后由系統(tǒng)釋放。
文字常量區(qū)--常量字符串存放在這里。程序結(jié)束后由系統(tǒng)釋放。
程序代碼區(qū)—存放函數(shù)體的二進(jìn)制文件。
棧:只要棧的剩余空間大于所申請(qǐng)空間,系統(tǒng)將為程序提供內(nèi)存,否則將報(bào)異常提示棧溢 出。
堆:首先應(yīng)該知道操作系統(tǒng)有一個(gè)記錄空閑內(nèi)存地址的鏈表,當(dāng)系統(tǒng)收到程序的申請(qǐng)時(shí),會(huì)遍歷該鏈表,尋找第一個(gè)空間大于所申請(qǐng)空間的堆結(jié)點(diǎn),然后將該結(jié)點(diǎn)從空閑結(jié)點(diǎn)鏈表中刪除,并將該結(jié)點(diǎn)的空間分配給程序,另外,對(duì)于大多數(shù)系統(tǒng),會(huì)在這塊內(nèi)存空間中的首地址處記錄本次分配的大小,這樣,代碼中的delete語句才能正確的釋放本內(nèi)存空間。另外,由于找到的堆結(jié)點(diǎn)的大小不一定正好等于申請(qǐng)的大小,系統(tǒng)會(huì)自動(dòng)的將多余的那部分重新放入空閑鏈表中。

iOS類是否可以多繼承?如果沒有,那可以用其他方法實(shí)現(xiàn)嗎?簡(jiǎn)述實(shí)現(xiàn)過程

不可以,可以通過消息轉(zhuǎn)發(fā)、delegate和protocol和類別來實(shí)現(xiàn)類似多繼承

KVO (Key-value observing)

KVO是觀察者模式的另一實(shí)現(xiàn)。
使用了isa混寫(isa-swizzling)來實(shí)現(xiàn)KVO

使用setter方法改變值KVO會(huì)生效,使用setValue:forKey即KVC改變值KVO也會(huì)生效,因?yàn)镵VC會(huì)去調(diào)用setter方法

  • (void)setValue:(id)value
    {
    [self willChangeValueForKey:@"key"];

    [super setValue:value];

    [self didChangeValueForKey:@"key"];
    }

那么通過直接賦值成員變量會(huì)觸發(fā)KVO嗎?

不會(huì),因?yàn)椴粫?huì)調(diào)用setter方法,需要加上
willChangeValueForKey和didChangeValueForKey方法來手動(dòng)觸發(fā)才行

KVC(Key-value coding)**

-(id)valueForKey:(NSString *)key;

-(void)setValue:(id)value forKey:(NSString *)key;
復(fù)制代碼

KVC就是指iOS的開發(fā)中,可以允許開發(fā)者通過Key名直接訪問對(duì)象的屬性,或者給對(duì)象的屬性賦值。而不需要調(diào)用明確的存取方法。這樣就可以在運(yùn)行時(shí)動(dòng)態(tài)地訪問和修改對(duì)象的屬性。而不是在編譯時(shí)確定,這也是iOS開發(fā)中的黑魔法之一。很多高級(jí)的iOS開發(fā)技巧都是基于KVC實(shí)現(xiàn)的

當(dāng)調(diào)用setValue:屬性值 forKey:@”name“的代碼時(shí),,底層的執(zhí)行機(jī)制如下:

image.png
  • 程序優(yōu)先調(diào)用set<Key>:屬性值方法,代碼通過setter方法完成設(shè)置。注意,這里的<key>是指成員變量名,首字母大小寫要符合KVC的命名規(guī)則,下同
  • 如果沒有找到setName:方法,KVC機(jī)制會(huì)檢查+ (BOOL)accessInstanceVariablesDirectly方法有沒有返回YES,默認(rèn)該方法會(huì)返回YES,如果你重寫了該方法讓其返回NO的話,那么在這一步KVC會(huì)執(zhí)行setValue:forUndefinedKey:方法,不過一般開發(fā)者不會(huì)這么做。所以KVC機(jī)制會(huì)搜索該類里面有沒有名為<key>的成員變量,無論該變量是在類接口處定義,還是在類實(shí)現(xiàn)處定義,也無論用了什么樣的訪問修飾符,只在存在以<key>命名的變量,KVC都可以對(duì)該成員變量賦值。
  • 如果該類即沒有set<key>:方法,也沒有_<key>成員變量,KVC機(jī)制會(huì)搜索_is<Key>的成員變量。
  • 和上面一樣,如果該類即沒有set<Key>:方法,也沒有_<key>和_is<Key>成員變量,KVC機(jī)制再會(huì)繼續(xù)搜索<key>和is<Key>的成員變量。再給它們賦值。
  • 如果上面列出的方法或者成員變量都不存在,系統(tǒng)將會(huì)執(zhí)行該對(duì)象的setValue:forUndefinedKey:方法,默認(rèn)是拋出異常。

即如果沒有找到Set<Key>方法的話,會(huì)按照_key,_iskey,key,iskey的順序搜索成員并進(jìn)行賦值操作。

如果開發(fā)者想讓這個(gè)類禁用KVC,那么重寫+ (BOOL)accessInstanceVariablesDirectly方法讓其返回NO即可,這樣的話如果KVC沒有找到set<Key>:屬性名時(shí),會(huì)直接用setValue:forUndefinedKey:方法。

當(dāng)調(diào)用valueForKey:@”name“的代碼時(shí),KVC對(duì)key的搜索方式不同于setValue:屬性值 forKey:@”name“,其搜索方式如下:

image.png

  • 首先按get<Key>,<key>,is<Key>的順序方法查找getter方法,找到的話會(huì)直接調(diào)用。如果是BOOL或者Int等值類型, 會(huì)將其包裝成一個(gè)NSNumber對(duì)象。
  • 如果上面的getter沒有找到,KVC則會(huì)查找countOf<Key>,objectIn<Key>AtIndex或<Key>AtIndexes格式的方法。如果countOf<Key>方法和另外兩個(gè)方法中的一個(gè)被找到,那么就會(huì)返回一個(gè)可以響應(yīng)NSArray所有方法的代理集合(它是NSKeyValueArray,是NSArray的子類),調(diào)用這個(gè)代理集合的方法,或者說給這個(gè)代理集合發(fā)送屬于NSArray的方法,就會(huì)以countOf<Key>,objectIn<Key>AtIndex或<Key>AtIndexes這幾個(gè)方法組合的形式調(diào)用。還有一個(gè)可選的get<Key>:range:方法。所以你想重新定義KVC的一些功能,你可以添加這些方法,需要注意的是你的方法名要符合KVC的標(biāo)準(zhǔn)命名方法,包括方法簽名。
  • 如果上面的方法沒有找到,那么會(huì)同時(shí)查找countOf<Key>,enumeratorOf<Key>,memberOf<Key>格式的方法。如果這三個(gè)方法都找到,那么就返回一個(gè)可以響應(yīng)NSSet所的方法的代理集合,和上面一樣,給這個(gè)代理集合發(fā)NSSet的消息,就會(huì)以countOf<Key>,enumeratorOf<Key>,memberOf<Key>組合的形式調(diào)用。
  • 如果還沒有找到,再檢查類方法+ (BOOL)accessInstanceVariablesDirectly,如果返回YES(默認(rèn)行為),那么和先前的設(shè)值一樣,會(huì)按_<key>,_is<Key>,<key>,is<Key>的順序搜索成員變量名,這里不推薦這么做,因?yàn)檫@樣直接訪問實(shí)例變量破壞了封裝性,使代碼更脆弱。如果重寫了類方法+ (BOOL)accessInstanceVariablesDirectly返回NO的話,那么會(huì)直接調(diào)用valueForUndefinedKey:方法,默認(rèn)是拋出異常。

iOS用什么方式實(shí)現(xiàn)對(duì)一個(gè)對(duì)象的KVO?(KVO的本質(zhì)是什么?)

利用RuntimeAPI動(dòng)態(tài)生成一個(gè)子類,并且讓instance對(duì)象的isa指向這個(gè)全新的子類
當(dāng)修改instance對(duì)象的屬性時(shí),會(huì)調(diào)用Foundation的_NSSetXXXValueAndNotify函數(shù)
willChangeValueForKey:
父類原來的setter
didChangeValueForKey:
內(nèi)部會(huì)觸發(fā)監(jiān)聽器(Oberser)的監(jiān)聽方法(observeValueForKeyPath:ofObject:change:context:)

屬性關(guān)鍵字**

1.讀寫權(quán)限:readonly,readwrite(默認(rèn))
2.原子性: atomic(默認(rèn)),nonatomic。atomic讀寫線程安全,但效率低,而且不是絕對(duì)的安全,比如如果修飾的是數(shù)組,那么對(duì)數(shù)組的讀寫是安全的,但如果是操作數(shù)組進(jìn)行添加移除其中對(duì)象的還,就不保證安全了。
3.引用計(jì)數(shù):

  • retain/strong
  • assign:修飾基本數(shù)據(jù)類型,修飾對(duì)象類型時(shí),不改變其引用計(jì)數(shù),會(huì)產(chǎn)生懸垂指針,修飾的對(duì)象在被釋放后,assign指針仍然指向原對(duì)象內(nèi)存地址,如果使用assign指針繼續(xù)訪問原對(duì)象的話,就可能會(huì)導(dǎo)致內(nèi)存泄漏或程序異常
  • weak:不改變被修飾對(duì)象的引用計(jì)數(shù),所指對(duì)象在被釋放后,weak指針會(huì)自動(dòng)置為nil
  • copy:分為深拷貝和淺拷貝
    淺拷貝:對(duì)內(nèi)存地址的復(fù)制,讓目標(biāo)對(duì)象指針和原對(duì)象指向同一片內(nèi)存空間會(huì)增加引用計(jì)數(shù)
    深拷貝:對(duì)對(duì)象內(nèi)容的復(fù)制,開辟新的內(nèi)存空間

image.png

可變對(duì)象的copy和mutableCopy都是深拷貝
不可變對(duì)象的copy是淺拷貝,mutableCopy是深拷貝
copy方法返回的都是不可變對(duì)象

分類、擴(kuò)展、代理、通知、KVO、KVC、屬性

參考鏈接:https://juejin.im/post/6844904039008698381

@property (nonatomic, copy) NSMutableArray * array;這樣寫有什么影響?

因?yàn)閏opy方法返回的都是不可變對(duì)象,所以array對(duì)象實(shí)際上是不可變的,如果對(duì)其進(jìn)行可變操作如添加移除對(duì)象,則會(huì)造成程序crash

frame 和 bounds 的區(qū)別是什么?

frame相對(duì)于父視圖,是父視圖坐標(biāo)系下的位置和大小。bounds相對(duì)于自身,是自身坐標(biāo)系下的位置和大小。
frame以父控件的左上角為坐標(biāo)原點(diǎn),bounds以自身的左上角為坐標(biāo)原點(diǎn)

什么時(shí)候會(huì)發(fā)生「隱式動(dòng)畫」?

當(dāng)改變CALayer的一個(gè)可做動(dòng)畫的屬性,它并不能立刻在屏幕上體現(xiàn)出來.相反,它是從先前的值平滑過渡到新的值。這一切都是默認(rèn)的行為,你不需要做額外的操作,這就是隱式動(dòng)畫

UIView 和 CALayer 之間的關(guān)系?

UIView顯示在屏幕上歸功于CALayer,通過調(diào)用drawRect方法來渲染自身的內(nèi)容,調(diào)節(jié)CALayer屬性可以調(diào)整UIView的外觀,UIView繼承自UIResponder,CALayer不可以響應(yīng)用戶事件
UIView是iOS系統(tǒng)中界面元素的基礎(chǔ),所有的界面元素都繼承自它。它內(nèi)部是由Core Animation來實(shí)現(xiàn)的,它真正的繪圖部分,是由一個(gè)叫CALayer(Core Animation Layer)的類來管理。UIView本身,更像是一個(gè)CALayer的管理器,訪問它的根繪圖和坐標(biāo)有關(guān)的屬性,如frame,bounds等,實(shí)際上內(nèi)部都是訪問它所在CALayer的相關(guān)屬性
UIView有個(gè)layer屬性,可以返回它的主CALayer實(shí)例,UIView有一個(gè)layerClass方法,返回主layer所使用的類,UIView的子類,可以通過重載這個(gè)方法,來讓UIView使用不同的CALayer來顯示

+[UIView animateWithDuration:animations:completion:] 內(nèi)部大概是如何實(shí)現(xiàn)的?

animateWithDuration:這就等于創(chuàng)建一個(gè)定時(shí)器
animations:這是創(chuàng)建定時(shí)器需要實(shí)現(xiàn)的SEL
completion:是定時(shí)器結(jié)束以后的一個(gè)回調(diào)block

iOS 的沙盒目錄結(jié)構(gòu)是怎樣的?

Application:存放程序源文件,上架前經(jīng)過數(shù)字簽名,上架后不可修改
Documents:常用目錄,iCloud備份目錄,存放數(shù)據(jù),這里不能存緩存文件,否則上架不被通過
Library
Caches:存放體積大又不需要備份的數(shù)據(jù),SDWebImage緩存路徑就是這個(gè)
Preference:設(shè)置目錄,iCloud會(huì)備份設(shè)置信息
tmp:存放臨時(shí)文件,不會(huì)被備份,而且這個(gè)文件下的數(shù)據(jù)有可能隨時(shí)被清除的可能

Push Notification推送 是如何工作的?

推送通知分為兩種,一個(gè)是本地推送,一個(gè)是遠(yuǎn)程推送
本地推送:不需要聯(lián)網(wǎng)也可以推送,是開發(fā)人員在APP內(nèi)設(shè)定特定的時(shí)間來提醒用戶干什么

image.png

從圖中可以很清楚的看出來推送的原理主要分為以下幾步:
1.由App向iOS設(shè)備發(fā)送一個(gè)注冊(cè)通知,用戶需要同意系統(tǒng)發(fā)送推送。
2.iOS向APNs遠(yuǎn)程推送服務(wù)器發(fā)送App的Bundle Id和設(shè)備的UDID。
3.APNs根據(jù)設(shè)備的UDID和App的Bundle Id生成deviceToken再發(fā)回給App。
4.App再將deviceToken發(fā)送給遠(yuǎn)程推送服務(wù)器(自己的服務(wù)器), 由服務(wù)器保存在數(shù)據(jù)庫中。
5.當(dāng)自己的服務(wù)器想發(fā)送推送時(shí), 在遠(yuǎn)程推送服務(wù)器中輸入要發(fā)送的消息并選擇發(fā)給哪些用戶的deviceToken,由遠(yuǎn)程推送服務(wù)器發(fā)送給APNs。
6.APNs根據(jù)deviceToken發(fā)送給對(duì)應(yīng)的用戶。
· APNs 服務(wù)器就是蘋果專門做遠(yuǎn)程推送的服務(wù)器。
·deviceToken是由APNs生成的一個(gè)專門找到你某個(gè)手機(jī)上的App的一個(gè)標(biāo)識(shí)碼。
· deviceToken 可能會(huì)變,如果你更改了你項(xiàng)目的bundle Identifier或者APNs服務(wù)器更新了可能會(huì)變。

是一個(gè)與線程相關(guān)的機(jī)制。
一個(gè)RunLoop就是一個(gè)時(shí)間處理的循環(huán),用來不停的調(diào)度工作以及處理輸入時(shí)間。使用runloop的目的是讓你的線程在有工作的時(shí)候忙于工作,而沒工作的時(shí)候處于休眠狀態(tài)。runloop的設(shè)計(jì)是為了減少cpu無謂的空轉(zhuǎn);

進(jìn)程與線程的特點(diǎn)與區(qū)別?

1)進(jìn)程和線程都是由操作系統(tǒng)所體會(huì)的程序運(yùn)行的基本單元,系統(tǒng)利用該基本單元實(shí)現(xiàn)系統(tǒng)對(duì)應(yīng)用的并發(fā)性。
2)進(jìn)程和線程的主要差別在于它們是不同的操作系統(tǒng)資源管理方式。 進(jìn)程有獨(dú)立的地址空間,一個(gè)進(jìn)程崩潰后,在保護(hù)模式下不會(huì)對(duì)其它進(jìn)程產(chǎn)生影響,而線程只是一個(gè)進(jìn)程中的不同執(zhí)行路徑。線程有自己的堆棧和局部變量,但線程之間沒有單獨(dú)的地址空間,一個(gè)線程死掉就等于整個(gè)進(jìn)程死掉,所以多進(jìn)程的程序要比多線程的程序健壯,但在進(jìn)程切換時(shí),耗費(fèi)資源較大,效率要差一些。但對(duì)于一些要求同時(shí)進(jìn)行并且又要共享某些變量的并發(fā)操作,只能用線程,不能用進(jìn)程。 共享變量可以實(shí)現(xiàn)線程調(diào)用另一個(gè)線程。

25匹馬,現(xiàn)有5條跑道,沒有計(jì)時(shí)器,要找出最快3匹馬,至少要跑幾場(chǎng)?

至少跑7場(chǎng),

對(duì)25匹馬隨機(jī)分成5個(gè)組(A,B,C,D,E,F),每組跑一場(chǎng),記錄每一匹馬在當(dāng)前組中名次(第1名,第2名,第3名)(跑了五場(chǎng))
從各個(gè)組中選取名次為第一名的馬組成一組,跑一場(chǎng),記錄名次(第六場(chǎng)),本組第1名則確定了25匹馬中最快的一匹馬
選取第六場(chǎng)中名次為第1名的所在原來組名次為第2、3名馬,選取第六場(chǎng)中名次為第2名的所在原來組名次第1、2名馬(它自己+第2名),選取第六場(chǎng)中名次為第3名所在原來組名次第1名的馬(它自己),組成一組,跑一場(chǎng),記錄名次(第七場(chǎng)),本場(chǎng)的第1、2名就是25匹馬中最快的第2、3名

8瓶液體,其中1瓶有毒藥,毒藥1小時(shí)后至死,請(qǐng)問最快找出毒藥,需要幾只老鼠?

1只老鼠可以斷定2瓶液體,2^3=8,所以需要3只老鼠即可,
對(duì)液體進(jìn)行編號(hào),001,010,011,100,101,110,111
給1號(hào)老鼠喂編碼個(gè)位數(shù)上是1的液體(001,011,101,111),
給2號(hào)老鼠喂編碼十位數(shù)上是1的液體(010,011,110,111),
給3號(hào)老鼠喂編碼百位數(shù)上是1的液體(100,101,110,111),
1小時(shí)后,
如果老鼠全活, 8號(hào)液體有毒,
如果全都死,7號(hào)液體有毒,
如果1號(hào)死,2,3活, 1號(hào)液體有毒
如果2號(hào)死, 1,3活,2號(hào)液體有毒
如果3號(hào)死,1,2活, 4號(hào)液體有毒
如果1,2號(hào)死,3活, 3號(hào)液體有毒
如果1,3號(hào)死,2活, 5號(hào)液體有毒
如果2,3號(hào)死,1活, 6號(hào)液體有毒

UIButton不響應(yīng)事件的原因

按鈕添加到了一個(gè)沒有開啟用戶交互的父View上,例如UIImageView,這時(shí)候開啟父試圖的交互 view.userInteractionEnabled = YES
按鈕自身被遮擋,點(diǎn)擊的時(shí)候根本就沒有點(diǎn)擊到button,而是他上面一層View,自然就不會(huì)響應(yīng)
按鈕的frame超出了父視圖的frame,這個(gè)是最容易出現(xiàn)的,按鈕的frame必須在父視圖的frame內(nèi)部點(diǎn)擊才有效
注意:超出父視圖不響應(yīng),但在父視圖里的會(huì)響應(yīng)。

webview的優(yōu)化,webview為什么會(huì)加載白屏

webview加載H5頁面過程
初始化 webview -> 請(qǐng)求頁面 -> 下載數(shù)據(jù) -> 解析HTML -> 請(qǐng)求 js/css 資源 -> dom 渲染 -> 解析 JS 執(zhí)行 -> JS 請(qǐng)求數(shù)據(jù) -> 解析渲染 -> 下載渲染圖片
優(yōu)化
前端優(yōu)化
合并資源,減少http請(qǐng)求數(shù)
加快請(qǐng)求速度:預(yù)解析DNS,減少域名數(shù),并行加載,CDN 分發(fā)
客戶端優(yōu)化
離線包方案:把一個(gè)個(gè)功能模塊的所有相關(guān)頁面和資源打包下發(fā)
提前初始化 webview,提供一個(gè)全局的webview。添加webview 池重用池,可以用兩個(gè)或多個(gè) webview 重復(fù)使用
預(yù)加載數(shù)據(jù)
總結(jié):緩存/預(yù)加載/并行,緩存一切網(wǎng)絡(luò)請(qǐng)求,盡量在用戶打開之前就加載好所有內(nèi)容,能并行做的事不串行做。

app啟動(dòng)優(yōu)化

App總啟動(dòng)時(shí)間 = pre-main耗時(shí) + main耗時(shí),可以通過添加環(huán)境變量:DYLD_PRINT_STATISTICS

啟動(dòng)流程
pre-main:系統(tǒng)dylib(動(dòng)態(tài)鏈接庫)和自身App可執(zhí)行文件的加載
main: main方法執(zhí)行之后到AppDelegate類中的didFinishLaunchingWithOptions方法執(zhí)行結(jié)束前這段時(shí)間,主要是構(gòu)建第一個(gè)界面,并完成渲染展示
pre-main優(yōu)化
減少類的數(shù)量,刪除無用代碼(未被調(diào)用的靜態(tài)變量、類和方法,抽象重復(fù)代碼
+load方法中做的事情延遲到+initialize中,或者在+load中做的事情不宜花費(fèi)過多時(shí)間
減少不必要的framework,或者優(yōu)化已有的framework
main階段優(yōu)化
didFinishLaunchingWithOptions,日志、統(tǒng)計(jì),某個(gè)功能的預(yù)加載,第三方SDK初始化,可以采用懶加載,或者分階段啟動(dòng)
首頁啟動(dòng)渲染的頁面優(yōu)化,對(duì)于viewDidLoad以及viewWillAppear方法中盡量去嘗試少做,晚做,不做,或者采用異步的方式去做。不使用xib或者storyboard,直接使用代碼

談?wù)勀銓?duì)KVC的理解?

KVC|可以通過(key)直接訪問對(duì)象的屬性,或者給對(duì)象的屬性賦值,這樣可以在運(yùn)行時(shí)動(dòng)態(tài)的訪問或修改對(duì)象的屬性當(dāng)調(diào)用setValue:屬性值forKey: @"name"的代碼時(shí),,底層的執(zhí)行機(jī)制如下∶

1、程序優(yōu)先調(diào)用set key>:屬性值方法,代碼通過(setter方法|完成設(shè)置。注意,這里的<key是指成員變量名,首字母大小寫要符合(KVC)的命名規(guī)則,下同

2、如果沒有找到setName:|方法,KVC機(jī)制會(huì)檢查(+(BOOL)accessInstancelariablesDirectly方法有沒有返回VYES ,默認(rèn)該方法會(huì)返回(VEs ,如果你重寫了該方法讓其返回NO的話,那么在這一步(KC 會(huì)執(zhí)行(setValue: forUndefinedKey:)方法,不過一般開發(fā)者不會(huì)這么做。所以KVC機(jī)制會(huì)搜索該類里面有沒有名為<kep)的成員變量,無論該變量是在類接口處定義,還是在類實(shí)現(xiàn)處定義,也無論用了什么樣的訪問修飾符,只在存在以<key命名的變量,KVC都可以對(duì)該成員變量賦值。

3、如果該類即沒有set<key>:方法,也沒有(_<key>成員變量,KVC機(jī)制會(huì)搜索(_is<Key>)的成員變量。

4、和上面一樣,如果該類即沒有set:方法,也沒有_和_is成員變量,KVC機(jī)制再會(huì)繼續(xù)搜索和is的成員變量。再給它們賦值。

談?wù)剬?duì)性能優(yōu)化的看法,如何做?

從用戶體驗(yàn)出發(fā):
1、程序logging不要太長(zhǎng)、
2、相同數(shù)據(jù)不做重復(fù)獲取、
3、昂貴資源要重用(cell、sqlite、date),
4、良好的編程習(xí)慣和程序設(shè)計(jì):選擇正確的集合對(duì)象和算法來進(jìn)行編程、選擇適合的數(shù)據(jù)存儲(chǔ)格式(plist、SQLite)、優(yōu)化SQLite查詢語句
5、數(shù)據(jù)資源方面的優(yōu)化(緩存和異步加載)
解決方案:
? 能夠發(fā)現(xiàn)問題
? 利用log或工具分析問題原因
? 假設(shè)問題原因
? 改進(jìn)代碼和設(shè)計(jì)

oc中可修改和不可以修改類型?

答:可修改不可修改的集合類,這個(gè)我個(gè)人簡(jiǎn)單理解就是可動(dòng)態(tài)添加修改和不可動(dòng)態(tài)添加修改
一樣。比如NSArray和NSMutableArray,前者在初始化后的內(nèi)存控件就是固定不可變的,后者可
以添加等,可以動(dòng)態(tài)申請(qǐng)新的內(nèi)存空間

說說響應(yīng)鏈

當(dāng)事件發(fā)生的時(shí)候,響應(yīng)鏈?zhǔn)紫缺话l(fā)送給第一個(gè)響應(yīng)者(往往是事件發(fā)生的視圖,也就是用戶觸摸屏幕的地方)。事件將沿著響應(yīng)者鏈一直向下傳遞,直到被接受并作出處理。一般來說,第一響應(yīng)這是個(gè)視圖對(duì)象或者其子類,當(dāng)其被觸摸后事件就交由它處理,如果他不處理,時(shí)間就會(huì)被傳遞給視圖控制器對(duì)象;
UIViewController(如果存在),然后是它的父視圖對(duì)象(superview),以此類推知道頂層視圖。接下來會(huì)沿著頂層視圖(top view)到窗口(UIwindow 對(duì)象) 再到程序的(UIApplication對(duì)象),如果整個(gè)過程都沒有響應(yīng)這個(gè)事件,則該事件被丟棄,一般情況下,在響應(yīng)鏈中只要有對(duì)象處理事件,事件就會(huì)被傳遞 ;
典型的響應(yīng)路線圖如: First Responser --> The Window -->The Applicationn --> App Delegate

熟悉哪些設(shè)計(jì)模式?

MVC 模式、單例模式、MVVM 模式、代理模式、工廠模式,觀察者模式

1.mvc 模式:model 保存應(yīng)用模型和處理數(shù)據(jù)邏輯、view 負(fù)責(zé) model 數(shù)據(jù)和交互控件的顯示、
controller 負(fù)責(zé) model 和 View 之間的通訊
2.單例模式:用一個(gè)靜態(tài)方法返回這個(gè)類的對(duì)象。這個(gè)對(duì)象是全局唯一的。整個(gè)項(xiàng)目里面只開
辟一塊內(nèi)層,比如登錄之后獲取的用戶數(shù)據(jù)存儲(chǔ)、NSNotificationcenter、NSUserdefaults,
sharedApplication。
缺點(diǎn):這塊內(nèi)層直到項(xiàng)目推出時(shí)才能釋放。
優(yōu)勢(shì):使用簡(jiǎn)單,延時(shí)求值,易于跨模塊, 便于資源共享控制,方便傳值和修改單例的屬性

談?wù)勀銓?duì)MVC的理解?為什么要用MVC?

MVC是Model-VIew-Controller,就是模型-視圖-控制器, MVC把軟件系統(tǒng)分為三個(gè)部分:Model,View,Controller。
Cocoa中所有的控件、窗口等都繼承自 UIView,對(duì)應(yīng)MVC中的 V。UIView及其子類主要負(fù)責(zé)UI的實(shí)現(xiàn),而UIView所產(chǎn)生的事件都可以采用委托的方式,交給UIViewController實(shí)現(xiàn)。對(duì)于不同的 UIView,都有相應(yīng)的UIViewController 對(duì)應(yīng)MVC中的C。比如在iPhone OS上常用的UITableView,它所對(duì)應(yīng)的Controller就是UITableViewController。至于MVC中的M,那需要根據(jù)用 戶自己的需求來實(shí)現(xiàn)了。
MVC可以幫助確保幫助實(shí)現(xiàn)程序最大程度的可重用性。各MVC元素彼此獨(dú)立運(yùn)作,通過分開這些元素,可以構(gòu)建可維護(hù),可獨(dú)立更新的程序組建。

簡(jiǎn)述NotificationCenter、KVC、KVO、Delegate?并說明它們之間的區(qū)別?

Notification:觀察者模式,controller向defaultNotificationCenter添加自己的 notification,其他類注冊(cè)這個(gè)notification就可以收到通知,這些類可以在收到通知時(shí)做自己的操作(多觀察者默認(rèn)隨機(jī)順序發(fā)通知給 觀察者們,而且每個(gè)觀察者都要等當(dāng)前的某個(gè)觀察者的操作做完才能輪到他來操作,可以用NotificationQueue的方式安排觀察者的反應(yīng)順序,也 可以在添加觀察者中設(shè)定反映時(shí)間,取消觀察需要在viewDidUnload 跟dealloc中都要注銷);
KVC鍵值編碼,可以直接通過字符串的名字(key)來間接訪問屬性的機(jī)制,而不是通過調(diào)用getter和setter方法訪問;
KVO:觀測(cè)指定對(duì)象的屬性,當(dāng)指定對(duì)象的屬性更改之后會(huì)通知相應(yīng)的觀察者;
delegate:一對(duì)一,delegate遵循某個(gè)協(xié)議并實(shí)現(xiàn)協(xié)議聲明的方法;

怎么用 copy 關(guān)鍵字?

NSString、NSArray、NSDictionary 等等經(jīng)常使用 copy 關(guān)鍵字,是因?yàn)樗麄冇袑?duì)應(yīng)的可變類型:
NSMutableString、NSMutableArray、NSMutableDictionary;
block 也經(jīng)常使用 copy 關(guān)鍵字,具體原因見官方文檔:Objects Use Properties to Keep Track
of Blocks:
MRC 中,方法內(nèi)部的 block 是在棧區(qū)的,使用 copy 可以把它放到堆區(qū).在 ARC 中寫不寫都行:對(duì)于 block 使用 copy 還是 strong 效果是一樣的,但寫上 copy 也無傷大雅,還能時(shí)刻?醒我們:編譯器自動(dòng)對(duì) block 進(jìn)行了 copy操作。如果不寫 copy ,該類的調(diào)用者有可能會(huì)忘記或者根本不知道“編譯器會(huì)自動(dòng)對(duì) block進(jìn)行了 copy 操作”,他們有可能會(huì)在調(diào)用之前自行拷貝屬性值。這種操作多余而低效。
copy 此特質(zhì)所表達(dá)的所屬關(guān)系與 strong 類似。然而設(shè)置方法并不保留新值,而是將其“拷 貝” (copy)。 當(dāng)屬性類型為 NSString 時(shí),經(jīng)常用此特質(zhì)來保護(hù)其封裝性,因?yàn)閭鬟f給設(shè)置方法的新值有可能指向一個(gè) NSMutableString 類的實(shí)例。這個(gè)類是 NSString 的子類,表示一種可修改其值的字符串,此時(shí)若是不拷貝字符串,那么設(shè)置完屬性之后,字符串的值就可能會(huì)在對(duì)象不知情的情況下遭人更改。所以,這時(shí)就要拷貝一份“不可變” (immutable)的字符串,確保對(duì)象中的字符串值不會(huì)無意間變動(dòng)。

談?wù)勀銓?duì)多線程開發(fā)的理解?

好處:
1.使多線程可以把占據(jù)時(shí)間長(zhǎng)的程序中的任務(wù)放到后臺(tái)去處理
2.用戶界面可以更加吸引力,這樣比如用戶點(diǎn)擊了一個(gè)按鈕去觸發(fā)某些事件的處理,
可以彈出一個(gè)進(jìn)度條來顯示處理的進(jìn)度
3.程序的運(yùn)行速度可能加快
缺點(diǎn):
1.如果有大量的線程,會(huì)影響性能,因?yàn)椴僮飨到y(tǒng)需要在它們之間切換。
2.更多的線程需要更多的內(nèi)存空間。

ios中有幾種實(shí)現(xiàn)多線程的方法?

多線程參考鏈接:http://www.itdecent.cn/p/f28a50f72bb1

1.NSThread
2.NSOperationQueue
3.GCD Thread

是這三種范式里面相對(duì)輕量級(jí)的,但也是使用起來最負(fù)責(zé)的,你需要自己管理thread的生命周期,線程之間的同步。線程共享同一應(yīng)用程序的部分內(nèi)存空間, 它們擁有對(duì)數(shù)據(jù)相同的訪問權(quán)限。你得協(xié)調(diào)多個(gè)線程對(duì)同一數(shù)據(jù)的訪問,一般做法是在訪問之前加鎖,這會(huì)導(dǎo)致一定的性能開銷。在 iOS 中我們可以使用多種形式的 thread: Cocoa threads: 使用NSThread 或直接從 NSObject 的類方法 performSelectorInBackground:withObject: 來創(chuàng)建一個(gè)線程。如果你選擇thread來實(shí)現(xiàn)多線程,那么 NSThread 就是官方推薦優(yōu)先選用的方式。
Cocoa operations是基于 Obective-C實(shí)現(xiàn)的,類 NSOperation 以面向?qū)ο蟮姆绞椒庋b了用戶需要執(zhí)行的操作,我們只要聚焦于我們需要做的事情,而不必太操心線程的管理,同步等事情,因?yàn)镹SOperation已經(jīng)為我 們封裝了這些事情。 NSOperation 是一個(gè)抽象基類,我們必須使用它的子類。iOS 提供了兩種默認(rèn)實(shí)現(xiàn):NSInvocationOperation 和 NSBlockOperation。
Grand Central Dispatch (GCD): iOS4 才開始支持,它提供了一些新的特性,以及運(yùn)行庫來支持多核并行編程,它的關(guān)注點(diǎn)更高:如何在多個(gè) cpu 上提升效率。

具體實(shí)施

這三種編程方式從上到下,抽象度層次是從低到高的,抽象度越高的使用越簡(jiǎn)單,也是Apple最推薦使用的。

三種方式的優(yōu)缺點(diǎn)介紹:
1)NSThread:
優(yōu)點(diǎn):NSThread 比其他兩個(gè)輕量級(jí)
缺點(diǎn):需要自己管理線程的生命周期,線程同步。線程同步對(duì)數(shù)據(jù)的加鎖會(huì)有一定的系統(tǒng)開銷

NSThread實(shí)現(xiàn)的技術(shù)有下面三種:
一般使用cocoa thread 技術(shù)。
(一)NSThread的使用*
NSThread 有兩種直接創(chuàng)建方式:

  • (id)initWithTarget:(id)target selector:(SEL)selector object:(id)argument
  • (void)detachNewThreadSelector:(SEL)aSelector toTarget:(id)aTarget withObject:(id)anArgument

參數(shù)的意義:
selector :線程執(zhí)行的方法,這個(gè)selector只能有一個(gè)參數(shù),而且不能有返回值。
target :selector消息發(fā)送的對(duì)象
argument:傳輸給target的唯一參數(shù),也可以是nil

第一種方式會(huì)直接創(chuàng)建線程并且開始運(yùn)行線程,第二種方式是先創(chuàng)建線程對(duì)象,然后再運(yùn)行線程操作,在運(yùn)行線程操作前可以設(shè)置線程的優(yōu)先級(jí)等線程信息

不顯式創(chuàng)建線程的方法:
用NSObject的類方法 performSelectorInBackground:withObject: 創(chuàng)建一個(gè)線程:
[Obj performSelectorInBackground:@selector(doSomething) withObject:nil];

參考鏈接:http://www.itdecent.cn/p/686dbf4bbb52

(二) NSOperation

優(yōu)點(diǎn):不需要關(guān)心線程管理,數(shù)據(jù)同步的事情,可以把精力放在自己需要執(zhí)行的操作上。
Cocoa operation 相關(guān)的類是 NSOperation ,NSOperationQueue。
NSOperation是個(gè)抽象類,使用它必須用它的子類,可以實(shí)現(xiàn)它或者使用它定義好的兩個(gè)子類:NSInvocationOperation 和 NSBlockOperation。
創(chuàng)建NSOperation子類的對(duì)象,把對(duì)象添加到NSOperationQueue隊(duì)列里執(zhí)行。

NSOperation 實(shí)現(xiàn)多線程的使用步驟分為三步:

創(chuàng)建操作:先將需要執(zhí)行的操作封裝到一個(gè) NSOperation 對(duì)象中。
創(chuàng)建隊(duì)列:創(chuàng)建 NSOperationQueue 對(duì)象。
將操作加入到隊(duì)列中:將 NSOperation 對(duì)象添加到 NSOperationQueue 對(duì)象中。
之后呢,系統(tǒng)就會(huì)自動(dòng)將 NSOperationQueue 中的 NSOperation 取出來,在新線程中執(zhí)行操作。

NSOperationQueue 控制串行執(zhí)行、并發(fā)執(zhí)行

之前我們說過,NSOperationQueue 創(chuàng)建的自定義隊(duì)列同時(shí)具有串行、并發(fā)功能,上邊我們演示了并發(fā)功能,那么他的串行功能是如何實(shí)現(xiàn)的?

這里有個(gè)關(guān)鍵屬性 maxConcurrentOperationCount,叫做最大并發(fā)操作數(shù)。用來控制一個(gè)特定隊(duì)列中可以有多少個(gè)操作同時(shí)參與并發(fā)執(zhí)行。

注意:這里 maxConcurrentOperationCount 控制的不是并發(fā)線程的數(shù)量,而是一個(gè)隊(duì)列中同時(shí)能并發(fā)執(zhí)行的最大操作數(shù)。而且一個(gè)操作也并非只能在一個(gè)線程中運(yùn)行。
最大并發(fā)操作數(shù):maxConcurrentOperationCount
maxConcurrentOperationCount 默認(rèn)情況下為-1,表示不進(jìn)行限制,可進(jìn)行并發(fā)執(zhí)行。
maxConcurrentOperationCount 為1時(shí),隊(duì)列為串行隊(duì)列。只能串行執(zhí)行。
maxConcurrentOperationCount 大于1時(shí),隊(duì)列為并發(fā)隊(duì)列。操作并發(fā)執(zhí)行,當(dāng)然這個(gè)值不應(yīng)超過系統(tǒng)限制,即使自己設(shè)置一個(gè)很大的值,系統(tǒng)也會(huì)自動(dòng)調(diào)整為 min{自己設(shè)定的值,系統(tǒng)設(shè)定的默認(rèn)最大值}。

參考鏈接:http://www.itdecent.cn/p/4b1d77054b35

(三)GCD
Grand Central Dispatch (GCD)是Apple開發(fā)的一個(gè)多核編程的解決方法。在iOS4.0開始之后才能使用。GCD是一個(gè)替代諸如NSThread, NSOperationQueue, NSInvocationOperation等技術(shù)的很高效和強(qiáng)大的技術(shù)。現(xiàn)在的iOS系統(tǒng)都升級(jí)到7了,所以不用擔(dān)心該技術(shù)不能使用。

使用 GCD 有很多好處啊,具體如下:

  • GCD 可用于多核的并行運(yùn)算;
  • GCD 會(huì)自動(dòng)利用更多的 CPU 內(nèi)核(比如雙核、四核);
  • GCD 會(huì)自動(dòng)管理線程的生命周期(創(chuàng)建線程、調(diào)度任務(wù)、銷毀線程);
  • 程序員只需要告訴 GCD 想要執(zhí)行什么任務(wù),不需要編寫任何線程管理代碼。

GCD 擁有以上這么多的好處,而且在多線程中處于舉足輕重的地位。那么我們就很有必要系統(tǒng)地學(xué)習(xí)一下 GCD 的使用方法。


2. GCD 任務(wù)和隊(duì)列

學(xué)習(xí) GCD 之前,先來了解 GCD 中兩個(gè)核心概念:『任務(wù)』『隊(duì)列』

任務(wù):就是執(zhí)行操作的意思,換句話說就是你在線程中執(zhí)行的那段代碼。在 GCD 中是放在 block 中的。執(zhí)行任務(wù)有兩種方式:『同步執(zhí)行』『異步執(zhí)行』。兩者的主要區(qū)別是:是否等待隊(duì)列的任務(wù)執(zhí)行結(jié)束,以及是否具備開啟新線程的能力。

  • 同步執(zhí)行(sync)
    • 同步添加任務(wù)到指定的隊(duì)列中,在添加的任務(wù)執(zhí)行結(jié)束之前,會(huì)一直等待,直到隊(duì)列里面的任務(wù)完成之后再繼續(xù)執(zhí)行。
    • 只能在當(dāng)前線程中執(zhí)行任務(wù),不具備開啟新線程的能力。
  • 異步執(zhí)行(async)
    • 異步添加任務(wù)到指定的隊(duì)列中,它不會(huì)做任何等待,可以繼續(xù)執(zhí)行任務(wù)。
    • 可以在新的線程中執(zhí)行任務(wù),具備開啟新線程的能力。

舉個(gè)簡(jiǎn)單例子:你要打電話給小明和小白。
『同步執(zhí)行』 就是:你打電話給小明的時(shí)候,不能同時(shí)打給小白。只有等到給小明打完了,才能打給小白(等待任務(wù)執(zhí)行結(jié)束)。而且只能用當(dāng)前的電話(不具備開啟新線程的能力)。
『異步執(zhí)行』 就是:你打電話給小明的時(shí)候,不用等著和小明通話結(jié)束(不用等待任務(wù)執(zhí)行結(jié)束),還能同時(shí)給小白打電話。而且除了當(dāng)前電話,你還可以使用其他一個(gè)或多個(gè)電話(具備開啟新線程的能力)。

注意:異步執(zhí)行(async)雖然具有開啟新線程的能力,但是并不一定開啟新線程。這跟任務(wù)所指定的隊(duì)列類型有關(guān)(下面會(huì)講)。

隊(duì)列(Dispatch Queue):這里的隊(duì)列指執(zhí)行任務(wù)的等待隊(duì)列,即用來存放任務(wù)的隊(duì)列。隊(duì)列是一種特殊的線性表,采用 FIFO(先進(jìn)先出)的原則,即新任務(wù)總是被插入到隊(duì)列的末尾,而讀取任務(wù)的時(shí)候總是從隊(duì)列的頭部開始讀取。每讀取一個(gè)任務(wù),則從隊(duì)列中釋放一個(gè)任務(wù)。隊(duì)列的結(jié)構(gòu)可參考下圖:

image

在 GCD 中有兩種隊(duì)列:『串行隊(duì)列』『并發(fā)隊(duì)列』。兩者都符合 FIFO(先進(jìn)先出)的原則。兩者的主要區(qū)別是:執(zhí)行順序不同,以及開啟線程數(shù)不同。

  • 串行隊(duì)列(Serial Dispatch Queue)
    • 每次只有一個(gè)任務(wù)被執(zhí)行。讓任務(wù)一個(gè)接著一個(gè)地執(zhí)行。(只開啟一個(gè)線程,一個(gè)任務(wù)執(zhí)行完畢后,再執(zhí)行下一個(gè)任務(wù))
  • 并發(fā)隊(duì)列(Concurrent Dispatch Queue)
    • 可以讓多個(gè)任務(wù)并發(fā)(同時(shí))執(zhí)行。(可以開啟多個(gè)線程,并且同時(shí)執(zhí)行任務(wù))

注意:并發(fā)隊(duì)列 的并發(fā)功能只有在異步(dispatch_async)方法下才有效。

參考鏈接:http://www.itdecent.cn/p/2d57c72016c6

ViewController生命周期

按照?qǐng)?zhí)?順序排列:

  1. initWithCoder:通過nib?件初始化時(shí)觸發(fā)。
  2. awakeFromNib:nib文件被加載的時(shí)候,會(huì)發(fā)生一個(gè)awakeFromNib的消息到nib文件中的每個(gè)對(duì)象。
  3. loadView:開始加載視圖控制器?帶的view。
  4. viewDidLoad:視圖控制器的view被加載完成。
  5. viewWillAppear:視圖控制器的view將要顯示在window上。
  6. updateViewConstraints:視圖控制器的view開始更新AutoLayout約束。
  7. viewWillLayoutSubviews:視圖控制器的view將要更新內(nèi)容視圖的位置。
  8. viewDidLayoutSubviews:視圖控制器的view已經(jīng)更新視圖的位置。
  9. viewDidAppear:視圖控制器的view已經(jīng)展示到window上。
  10. viewWillDisappear:視圖控制器的view將要從window上消失。
  11. viewDidDisappear:視圖控制器的view已經(jīng)從window上消失。

struct、Class的區(qū)別

class可以繼承,struct不可以
class是引用類型,struct是值類型
struct在function里修改property時(shí)需要mutating關(guān)鍵字修飾

NSArray與NSSet的區(qū)別?

NSArray內(nèi)存中存儲(chǔ)地址連續(xù),而NSSet不連續(xù)
NSSet效率高,內(nèi)部使用hash查找;NSArray查找需要遍歷
NSSet通過anyObject訪問元素,NSArray通過下標(biāo)訪問

NSHashTable與NSMapTable?

NSHashTable是NSSet的通用版本,對(duì)元素弱引用,可變類型;可以在訪問成員時(shí)copy
NSMapTable是NSDictionary的通用版本,對(duì)元素弱引用,可變類型;可以在訪問成員時(shí)copy
(注:NSHashTable與NSSet的區(qū)別:NSHashTable可以通過option設(shè)置元素弱引用/copyin,只有可變類型。但是添加對(duì)象的時(shí)候NSHashTable耗費(fèi)時(shí)間是NSSet的兩倍。
NSMapTable與NSDictionary的區(qū)別:同上)

屬性關(guān)鍵字assign、retain、weak、copy

assign:用于基本數(shù)據(jù)類型和結(jié)構(gòu)體。如果修飾對(duì)象的話,當(dāng)銷毀時(shí),屬性值不會(huì)自動(dòng)置nil,可能造成野指針。
weak:對(duì)象引用計(jì)數(shù)為0時(shí),屬性值也會(huì)自動(dòng)置nil
retain:強(qiáng)引用類型,ARC下相當(dāng)于strong,但block不能用retain修飾,因?yàn)榈韧赼ssign不安全。
strong:強(qiáng)引用類型,修飾block時(shí)相當(dāng)于copy。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容