iOS最新面試題匯總(三)

iOS最新面試題匯總:
iOS最新面試題匯總(一)
iOS最新面試題匯總(二)
iOS最新面試題匯總(三)
iOS最新面試題匯總(四)

  1. 下面的代碼輸出什么?
    @implementation Son : Father
    - (id)init {
       if (self = [super init]) {
           NSLog(@"%@", NSStringFromClass([self class])); // Son
           NSLog(@"%@", NSStringFromClass([super class])); // Son
       }
       return self;
    }
    @end
    // 解析:
    self 是類的隱藏參數,指向當前調用方法的這個類的實例。
    super是一個Magic Keyword,它本質是一個編譯器標示符,和self是指向的同一個消息接收者。
    不同的是:super會告訴編譯器,調用class這個方法時,要去父類的方法,而不是本類里的。
    上面的例子不管調用[self class]還是[super class],接受消息的對象都是當前 Son *obj 這個對象。
  1. 寫一個完整的代理,包括聲明、實現
    // 創建
    @protocol MyDelagate
    @required
    -(void)eat:(NSString *)foodName; 
    @optional
    -(void)run;
    @end

    //  聲明 .h
    @interface person: NSObject<MyDelagate>

    @end

    //  實現 .m
    @implementation person
    - (void)eat:(NSString *)foodName { 
       NSLog(@"吃:%@!", foodName);
    } 
    - (void)run {
       NSLog(@"run!");
    }

    @end
  1. isKindOfClass、isMemberOfClass、selector作用分別是什么
    isKindOfClass:作用是某個對象屬于某個類型或者繼承自某類型。
    isMemberOfClass:某個對象確切屬于某個類型。
    selector:通過方法名,獲取在內存中的函數的入口地址。

4. ####delegate 和 notification 的區別

    1). 二者都用于傳遞消息,不同之處主要在于一個是一對一的,另一個是一對多的。
    2). notification通過維護一個array,實現一對多消息的轉發。
    3). delegate需要兩者之間必須建立聯系,不然沒法調用代理的方法;notification不需要兩者之間有聯系。
  1. 什么是block?
    閉包(block):閉包就是獲取其它函數局部變量的匿名函數。
  1. block反向傳值

    在控制器間傳值可以使用代理或者block,使用block相對來說簡潔。

    在前一個控制器的touchesBegan:方法內實現如下代碼。

      // OneViewController.m
      TwoViewController *twoVC = [[TwoViewController alloc] init];
      twoVC.valueBlcok = ^(NSString *str) {
        NSLog(@"OneViewController拿到值:%@", str); 
      };
      [self presentViewController:twoVC animated:YES completion:nil];

      // TwoViewController.h   (在.h文件中聲明一個block屬性)
      @property (nonatomic ,strong) void(^valueBlcok)(NSString *str);

      // TwoViewController.m   (在.m文件中實現方法)
    - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
        // 傳值:調用block
        if (_valueBlcok) {
            _valueBlcok(@"123456");
        }
    }
  1. block的注意點
    1). 在block內部使用外部指針且會造成循環引用情況下,需要用__week修飾外部指針:
        __weak typeof(self) weakSelf = self; 
    2). 在block內部如果調用了延時函數還使用弱指針會取不到該指針,因為已經被銷毀了,需要在block內部再將弱指針重新強引用一下。
        __strong typeof(self) strongSelf = weakSelf;
    3). 如果需要在block內部改變外部棧區變量的話,需要在用__block修飾外部變量。
  1. BAD_ACCESS在什么情況下出現?
    答:這種問題在開發時經常遇到。原因是訪問了野指針,比如訪問已經釋放對象的成員變量或者發消息、死循環等。
  1. lldb(gdb)常用的控制臺調試命令?
    1). p 輸出基本類型。是打印命令,需要指定類型。是print的簡寫
        p (int)[[[self view] subviews] count]
    2). po 打印對象,會調用對象description方法。是print-object的簡寫
        po [self view]
    3). expr 可以在調試時動態執行指定表達式,并將結果打印出來。常用于在調試過程中修改變量的值。
    4). bt:打印調用堆棧,是thread backtrace的簡寫,加all可打印所有thread的堆棧
    5). br l:是breakpoint list的簡寫
  1. 你一般是怎么用Instruments的?
    Instruments里面工具很多,常用:
    1). Time Profiler: 性能分析
    2). Zombies:檢查是否訪問了僵尸對象,但是這個工具只能從上往下檢查,不智能。
    3). Allocations:用來檢查內存,寫算法的那批人也用這個來檢查。
    4). Leaks:檢查內存,看是否有內存泄露。
  1. iOS中常用的數據存儲方式有哪些?
數據存儲有四種方案:NSUserDefault、KeyChain、file、DB。
    其中File有三種方式:plist、Archive(歸檔)
    DB包括:SQLite、FMDB、CoreData
  1. iOS的沙盒目錄結構是怎樣的?
沙盒結構:
1). Application:存放程序源文件,上架前經過數字簽名,上架后不可修改。
2). Documents:常用目錄,iCloud備份目錄,存放數據。(這里不能存緩存文件,否則上架不被通過)
3). Library:
        Caches:存放體積大又不需要備份的數據。(常用的緩存路徑)
        Preference:設置目錄,iCloud會備份設置信息。
4). tmp:存放臨時文件,不會被備份,而且這個文件下的數據有可能隨時被清除的可能。
  1. iOS多線程技術有哪幾種方式?
答:pthread、NSThread、GCD、NSOperation
  1. GCD 與 NSOperation 的區別:
GCD 和 NSOperation 都是用于實現多線程:
    GCD 基于C語言的底層API,GCD主要與block結合使用,代碼簡潔高效。
    NSOperation 屬于Objective-C類,是基于GCD更高一層的封裝。復雜任務一般用NSOperation實現。
  1. 寫出使用GCD方式從子線程回到主線程的方法代碼
答:dispatch_async(dispatch_get_main_queue(), ^{ });
  1. 如何用GCD同步若干個異步調用?(如根據若干個url異步加載多張圖片,然后在都下載完成后合成一張整圖)
// 使用Dispatch Group追加block到Global Group Queue,這些block如果全部執行完畢,就會執行Main Dispatch Queue中的結束處理的block。
// 創建隊列組
dispatch_group_t group = dispatch_group_create();
// 獲取全局并發隊列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_group_async(group, queue, ^{ /*加載圖片1 */ });
dispatch_group_async(group, queue, ^{ /*加載圖片2 */ });
dispatch_group_async(group, queue, ^{ /*加載圖片3 */ }); 
// 當并發隊列組中的任務執行完畢后才會執行這里的代碼
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
        // 合并圖片
});
  1. dispatch_barrier_async(柵欄函數)的作用是什么?
函數定義:dispatch_barrier_async(dispatch_queue_t queue, dispatch_block_t block);
作用:
    1.在它前面的任務執行結束后它才執行,它后面的任務要等它執行完成后才會開始執行。
    2.避免數據競爭

 // 1.創建并發隊列
 dispatch_queue_t queue = dispatch_queue_create("myQueue", DISPATCH_QUEUE_CONCURRENT);
// 2.向隊列中添加任務
dispatch_async(queue, ^{  // 1.2是并行的
    NSLog(@"任務1, %@",[NSThread currentThread]);
});
dispatch_async(queue, ^{
    NSLog(@"任務2, %@",[NSThread currentThread]);
});

 dispatch_barrier_async(queue, ^{
    NSLog(@"任務 barrier, %@", [NSThread currentThread]);
});

 dispatch_async(queue, ^{   // 這兩個是同時執行的
    NSLog(@"任務3, %@",[NSThread currentThread]);
});
 dispatch_async(queue, ^{
    NSLog(@"任務4, %@",[NSThread currentThread]);
});

 // 輸出結果: 任務1 任務2 ——》 任務 barrier ——》任務3 任務4 
// 其中的任務1與任務2,任務3與任務4 由于是并行處理先后順序不定。
  1. 以下代碼運行結果如何?
  - (void)viewDidLoad {
    [super viewDidLoad];
    NSLog(@"1");
    dispatch_sync(dispatch_get_main_queue(), ^{
        NSLog(@"2");
    });
    NSLog(@"3");
 }
// 只輸出:1。(主線程死鎖)
  1. 什么是 RunLoop
  從字面上講就是運行循環,它內部就是do-while循環,在這  個循環內部不斷地處理各種任務。
一個線程對應一個RunLoop,基本作用就是保持程序的持續運行,處理app中的各種事件。通過runloop,有事運行,沒事就休息,可以節省cpu資源,提高程序性能。

  主線程的run loop默認是啟動的。iOS的應用程序里面,程序啟動后會有一個如下的main()函數
  int main(int argc, char * argv[]) {
     @autoreleasepool {
         return UIApplicationMain(argc, argv, nil,   NSStringFromClass([AppDelegate class]));
     }
 }
  1. 什么是 Runtime

Runtime又叫運行時,是一套底層的C語言API,其為iOS內部的核心之一,我們平時編寫的OC代碼,底層都是基于它來實現的。

聯系

github地址:https://github.com/meetly
希望大家多多指教!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容