iOS開發——你面試能用到的iOS面試題(二)

> 爲你們總結一份完整的2020年《大廠最新常問iOS面試題+答案》,**面試題合集答案**、**複習資料**,均有**完整PDF版**,須要的小夥伴加iOS技術分享羣:761407670,羣文件直接獲取!git

 

題目來源自這裏,筆者對知識類問題和經驗類問題作了解答,答案有遺漏的地方但願你們能補充,這是你能用到的面試題(一)github

Push Notification 是如何工做的?

  • 推送通知分爲兩種,一個是本地推送,一個是遠程推送
    • 本地推送:不須要聯網也能夠推送,是開發人員在APP內設定特定的時間來提醒用戶幹什麼
    • 遠程推送:須要聯網,用戶的設備會於蘋果APNS服務器造成一個長鏈接,用戶設備會發送uuid和Bundle idenidentifier給蘋果服務器,蘋果服務器會加密生成一個deviceToken給用戶設備,而後設備會將deviceToken發送給APP的服務器,服務器會將deviceToken存進他們的數據庫,這時候若是有人發送消息給我,服務器端就會去查詢個人deviceToken,而後將deviceToken和要發送的信息發送給蘋果服務器,蘋果服務器經過deviceToken找到個人設備並將消息推送到個人設備上,這裏還有個狀況是若是APP在線,那麼APP服務器會於APP產生一個長鏈接,這時候APPF服務器會直接經過deviceToken將消息推送到設備上

什麼是 Runloop?

是一個與線程相關的機制,能夠理解爲一個循環,在這個循環裏面等待事件而後處理事件.而這個循環是基於線程的,在Cocoa中每一個線程都有它的runroop,經過他這樣的機制,線程能夠在沒有事件要處理的時候休息,有事件運行,減輕CPU壓力,這題能夠衍生出爲何在滑動時會致使定時器失敗,在下面有解答面試

Toll-Free Bridging 是什麼?什麼狀況下會使用?

Toll-Free Bridging用於在Foundation對象與Core Foundation對象之間交換數據,俗稱橋接數據庫

  • 在ARC環境下,Foundation對象轉成 Core Foundation對象
    • 使用__bridge橋接之後ARC會自動2個對象
    • 使用__bridge_retained橋接須要手動釋放Core Foundation對象
  • 在ARC環境下, Core Foundation對象轉成 Foundation對象
    • 使用__bridge橋接,若是Core Foundation對象被釋放,Foundation對象也同時不能使用了,須要手動管理Core Foundation對象
    • 使用__bridge_transfer橋接,系統會自動管理2個對象

當系統出現內存警告時會發生什麼?

  • 會將不在當前窗口上的view暫時移除
  • 若是聽任內存警告,最終會致使軟件強制被系統關閉

什麼是 Protocol,Delegate 通常是怎麼用的?

  • 協議是一個方法簽名的列表,在其中能夠定義若干個方法,遵照該協議的類能夠實現協議裏的方法,在協議中使用@property只會生成setter和getter方法的聲明
  • delegate用法:成爲一個類的代理,能夠去實現協議裏的方法

autorelease 對象在什麼狀況下會被釋放?

  • 分兩種狀況:手動干預釋放和系統自動釋放
    • 手動干預釋放就是指定autoreleasepool,當前做用域大括號結束就當即釋放
    • 系統自動去釋放:不手動指定autoreleasepool,Autorelease對象會在當前的 runloop 迭代結束時釋放
      • kCFRunLoopEntry(1):第一次進入會自動建立一個autorelease
      • kCFRunLoopBeforeWaiting(32):進入休眠狀態前會自動銷燬一個autorelease,而後從新建立一個新的autorelease
      • kCFRunLoopExit(128):退出runloop時會自動銷燬最後一個建立的autorelease

爲何 NotificationCenter 要 removeObserver? 如何實現自動 remove?

  • 若是不移除的話,萬一註冊通知的類被銷燬之後又發了通知,程序會崩潰.由於向野指針發送了消息
  • 實現自動remove:經過自釋放機制,經過動態屬性將remove轉移給第三者,解除耦合,達到自動實現remove

當 TableView 的 Cell 改變時,如何讓這些改變以動畫的形式呈現?

這裏舉個例子,點擊cell之後以動畫形式改變cell高度數組

@interface ViewController () @property (nonatomic, strong) NSIndexPath *index; @end @implementation ViewController static NSString *ID = @"cell"; - (void)viewDidLoad { [super viewDidLoad]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID]; cell.textLabel.text = [NSString stringWithFormat:@"%ld",(long)indexPath.row]; return cell; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return 20; } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { if(self.index == indexPath){ return 120; } return 60; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { self.index = indexPath; [tableView deselectRowAtIndexPath:indexPath animated:TRUE]; // 重點是這2句代碼實現的功能 [tableView beginUpdates]; [tableView endUpdates]; } 

爲何 UIScrollView 的滾動會致使 NSTimer 失效?

定時器裏面有個runoop mode,通常定時器是運行在defaultmode上可是若是滑動了這個頁面,主線程runloop會轉到UITrackingRunLoopMode中,這時候就不能處理定時器了,形成定時器失效,緣由就是runroop mode選錯了,解決辦法有2個,一個是更改mode爲NSRunLoopCommonModes(不管runloop運行在哪一個mode,都能運行),還有種辦法是切換到主線程來更新UI界面的刷新服務器

爲何當 Core Animation 完成時,layer 又會恢復到原先的狀態?

由於這些產生的動畫只是假象,並無對layer進行改變.那麼爲何會這樣呢,這裏要講一下圖層樹裏的呈現樹.呈現樹其實是模型圖層的複製,可是它的屬性值表示了當前外觀效果,動畫的過程實際上只是修改了呈現樹,並無對圖層的屬性進行改變,因此在動畫結束之後圖層會恢復到原先狀態網絡

你會如何存儲用戶的一些敏感信息,如登陸的 token

  • 使用keychain來存儲,也就是鑰匙串,使用keychain須要導入Security框架

自定義一個keychain的類app

#import <Security/Security.h> @implementation YCKKeyChain + (NSMutableDictionary *)getKeychainQuery:(NSString *)service { return [NSMutableDictionary dictionaryWithObjectsAndKeys: (__bridge_transfer id)kSecClassGenericPassword,(__bridge_transfer id)kSecClass, service, (__bridge_transfer id)kSecAttrService, service, (__bridge_transfer id)kSecAttrAccount, (__bridge_transfer id)kSecAttrAccessibleAfterFirstUnlock,(__bridge_transfer id)kSecAttrAccessible, nil]; } + (void)save:(NSString *)service data:(id)data { // 得到搜索字典 NSMutableDictionary *keychainQuery = [self getKeychainQuery:service]; // 添加新的刪除舊的 SecItemDelete((__bridge_retained CFDictionaryRef)keychainQuery); // 添加新的對象到字符串 [keychainQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:data] forKey:(__bridge_transfer id)kSecValueData]; // 查詢鑰匙串 SecItemAdd((__bridge_retained CFDictionaryRef)keychainQuery, NULL); } + (id)load:(NSString *)service { id ret = nil; NSMutableDictionary *keychainQuery = [self getKeychainQuery:service]; // 配置搜索設置 [keychainQuery setObject:(id)kCFBooleanTrue forKey:(__bridge_transfer id)kSecReturnData]; [keychainQuery setObject:(__bridge_transfer id)kSecMatchLimitOne forKey:(__bridge_transfer id)kSecMatchLimit]; CFDataRef keyData = NULL; if (SecItemCopyMatching((__bridge_retained CFDictionaryRef)keychainQuery, (CFTypeRef *)&keyData) == noErr) { @try { ret = [NSKeyedUnarchiver unarchiveObjectWithData:(__bridge_transfer NSData *)keyData]; } @catch (NSException *e) { NSLog(@"Unarchive of %@ failed: %@", service, e); } @finally { } } return ret; } + (void)delete:(NSString *)service { NSMutableDictionary *keychainQuery = [self getKeychainQuery:service]; SecItemDelete((__bridge_retained CFDictionaryRef)keychainQuery); } 

在別的類實現存儲,加載,刪除敏感信息方法框架

// 用來標識這個鑰匙串 static NSString * const KEY_IN_KEYCHAIN = @"com.yck.app.allinfo"; // 用來標識密碼 static NSString * const KEY_PASSWORD = @"com.yck.app.password"; + (void)savePassWord:(NSString *)password { NSMutableDictionary *passwordDict = [NSMutableDictionary dictionary]; [passwordDict setObject:password forKey:KEY_PASSWORD]; [YCKKeyChain save:KEY_IN_KEYCHAIN data:passwordDict]; } + (id)readPassWord { NSMutableDictionary *passwordDict = (NSMutableDictionary *)[YCKKeyChain load:KEY_IN_KEYCHAIN]; return [passwordDict objectForKey:KEY_PASSWORD]; } + (void)deletePassWord { [YCKKeyChain delete:KEY_IN_KEYCHAIN]; } 

有用過一些開源組件吧,能簡單說幾個麼,大概說說它們的使用場景實現。

  • AFN:網絡請求
  • FMDB:使用數據庫
  • MJExtension: JSON與Model互轉
  • SVProgressHUD:提示HUD
  • Masonry:自動佈局
  • MJRefresh:下拉和上拉刷新

何時會發生 EXC BAD ACCESS 異常?

  • 訪問一個殭屍對象,訪問殭屍對象的成員變量或者向其發消息
  • 死循環

NSNotification 和 KVO 的使用場景?

  • KVO使用場景:當一個對象的特定屬性改變的時候,須要被通知一個或者多個對象的時候
  • NSNotification使用場景:跨層級傳遞值,多個對象通知多個對象

使用 Block 時須要注意哪些問題?

  • 在block內部使用外部指針且會形成循環引用狀況下,須要用__weak修飾外部指針
    __weak typeof(self) weakSelf = self;
  • 在block內部若是調用了延時函數還使用弱指針會取不到該指針,由於已經被銷燬了,須要在block內部再將弱指針從新強引用一下__strong typeof(self) strongSelf = weakSelf;
  • 若是須要在block內部改變外部變量的話,須要在用__block修飾外部變量
    筆者也寫過一篇block博客

performSelector:withObject:afterDelay: 內部大概是怎麼實現的,有什麼注意事項麼?

  • 建立一個定時器,時間結束後系統會使用runtime經過方法名稱(Selector本質就是方法名稱)去方法列表中找到對應的方法實現並調用方法
  • 注意事項
    • 調用performSelector:withObject:afterDelay:方法時,先判斷但願調用的方法是否存在respondsToSelector:
    • 這個方法是異步方法,必須在主線程調用,在子線程調用永遠不會調用到想調用的方法

使用 NSUserDefaults 時,如何處理布爾的默認值?(好比返回 NO,不知道是真的 NO 仍是沒有設置過)

if([[NSUserDefaults standardUserDefaults] objectForKey:ID] == nil){ NSLog(@"沒有設置"); } 

哪些途徑可讓 ViewController 瘦下來?

  • 把 Data Source 和其餘 Protocols 分離出來(將UITableView或者UICollectionView的代碼提取出來放在其餘類中)
  • 將業務邏輯移到 Model 中(和模型有關的邏輯所有在model中寫)
  • 把網絡請求邏輯移到 Model 層(網絡請求依靠模型)
  • 把 View 代碼移到 View 層(自定義View)

有哪些常見的 Crash 場景?

爲你們總結一份完整的2020年《大廠最新常問iOS面試題+答案》,面試題合集答案、複習資料,均有完整PDF版,須要的小夥伴加iOS技術分享羣:761407670,羣文件直接獲取!異步

相關文章
相關標籤/搜索