iOS 面試題總結

isa指針:

在Objective-C中,任何類的定義都是對象。類和類的實例(對象)沒有任何本質上的區別。任何對象都有 isa 指針。面試

isa 是一個Class 類型的指針。 每一個實例對象有個 isa 的指針,他指向對象的類,而Class裏也有個 isa 的指針, 指向 meteClass (元類)。元類保存了類方法的列表。當類方法被調用時,先會從自己查找類方法的實現,若是沒有,元類會向他父類查找該方法。同時注意的是:元類也是類,它也是對象。元類也有 isa 指針,它的 isa 指針最終指向的是一個根元類。根元類的 isa 指針指向自己,這樣造成了一個封閉的內循環。數據庫

實例:類對象的isa指針結構圖.png

const 含義

  • 面試題編程

    const int a;
    int const a;
    const int *a;
    int const *a;
    int * const a;
    int const * const a;
    複製代碼
    1. 前兩個的做用是同樣:a 是一個常整型數
    2. 第3、四個意味着 a 是一個指向常整型數的指針(整型數是不可修改的,但指針能夠)
    3. 第五個的意思:a 是一個指向整型數的常指針(指針指向的整型數是能夠修改的,但指針是不可修改的)
    4. 最後一個意味着:a 是一個指向常整型數的常指針(指針指向的整型數是不可修改的,同時指針也是不可修改的)
  • 合理地使用關鍵字const可使編譯器保護那些不但願被改變的參數,防止其被無心的代碼修改,減小bug。json

    1. 欲阻止一個變量被改變,可使用 const 關鍵字。在定義該 const 變量時,一般須要對它進行初始化,由於之後就沒有機會再去改變它了;
    2. 對指針來講,能夠指定指針自己爲 const,也能夠指定指針所指的數據爲 const,或兩者同時指定爲 const;
    3. 在一個函數聲明中,const 能夠修飾形參,代表它是一個輸入參數,在函數內部不能改變其值;
    4. 對於類的成員函數,若指定其爲 const 類型,則代表其是一個常函數,不能修改類的成員變量;
    5. 對於類的成員函數,有時候必須指定其返回值爲 const 類型,以使得其返回值不爲「左值」。

static關鍵字

  1. 函數體內 static 變量的做用範圍爲該函數體,不一樣於 auto 變量,該變量的內存只被分配一次,所以其值在下次調用時仍維持上次的值;
  2. 在模塊內的 static 全局變量能夠被模塊內所用函數訪問,但不能被模塊外其它函數訪問;
  3. 在模塊內的 static 函數只可被這一模塊內的其它函數調用,這個函數的使用範圍被限制在聲明它的模塊內;
  4. 在類中的 static 成員變量屬於整個類所擁有,只會初始化一次,而且在程序退出時纔會回收內存;
  5. 在類中的 static 成員函數屬於整個類所擁有,這個函數不接收 this 指針,於是只能訪問類的 static 成員變量。
  • static 用途
    1. 限制變量的做用域
    2. 設置變量的存儲域

volatile關鍵字

volatile 的變量是說這變量可能會被意想不到地改變,這樣,編譯器就不會去假設這個變量的值了。精確地說就是,優化器在用到這個變量時必須每次都當心地從新讀取這個變量的值,而不是使用保存在寄存器裏的備份。下面是設計模式

  • volatile 變量的幾個例子
    1. 並行設備的硬件寄存器(如:狀態寄存器)
    2. 一箇中斷服務子程序中會訪問到的非自動變量(Non-automatic variables)
    3. 多線程應用中被幾個任務共享的變量
  • 一個參數既能夠是 const 還能夠是 volatile 嗎?解釋爲何。
    是的。一個例子是隻讀的狀態寄存器。它是 volatile 由於它可能被意想不到地改變。它是 const 由於程序不該該試圖去修改它
  • 一個指針能夠是 volatile 嗎?解釋爲何。
    是的。儘管這並不很常見。一個例子是當一箇中服務子程序修該一個指向一個buffer的指針時。

self. 跟 self-> 區別?

self. 是調用 get 方法或者 set 方法 self 是當前自己,是一個指向當前對象的指針 self-> 是直接訪問成員變量數組

懶加載

懶加載——也稱爲延遲加載,只在用到的時候纔去初始化,好比控制器的view,在第一次用到view時纔會調用loadView方法進行建立,所謂懶加載,寫的是其get方法。我以爲最好也最簡單的一個列子就是tableView中圖片的加載顯示了。一個延時載,避免內存太高,一個異步加載,避免線程堵塞。
注意:若是是懶加載的話則必定要注意先判斷是否已經有了,若是沒有那麼再去進行實例化緩存

  • 懶加載的好處:
    1. 沒必要將建立對象的代碼所有寫在viewDidLoad方法中,代碼的可讀性更強
    2. 每一個控件的 getter 方法中分別負責各自的實例化處理,代碼彼此之間的獨立性強,鬆耦合

Objective C中的selector 是什麼?

你能夠理解 @selector()就是取類方法的編號,他的行爲基本能夠等同C語言的中函數指針,只不過C語言中,能夠把函數名直接賦給一個函數指針,而 Objective-C的類不能直接應用函數指針,這樣只能作一個@selector語法來取.它的結果是一個SEL類型。這個類型本質是類方法的編號 (函數地址)。 方法和選擇器有何不一樣? 答案:selector是一個方法的名字,method是一個組合體,包含了名字和實現。經過一個selector能夠找到方法地址,進而調用一個方法安全

其餘

  • [[NSMutableArray alloc]init][NSMutableArray array]bash

    • [[NSMutableArray alloc]init] alloc 分配內存,init 初始化,須要手動釋放;
    • [NSMutableArray array] 不須要手動 release,遵循 autoreleasepool 機制
    • 在ARC(自動引用計數)中兩種方式並沒什麼區別
  • newalloc/init 兩種方式建立對象如今基本上同樣,區別就是使用 new 只能默認 init 進行初始化,alloc 方式可使用其它的 init 開頭的方法進行初始化。網絡

  • 子線程要主動開啓 runloop

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{  
         [self performSelector:@selector(fireBlock:) withObject:^{  
            NSLog(@"hello world");  
         } afterDelay:0.3];  
     }); 
    複製代碼

    上面的代碼片斷原有的目的是異步延遲0.3秒後輸出Hello world。可是運行以後發現不會輸出Hello world。
    緣由是:非主線程的NSRunLoop默認沒有開啓,而 - (void)performSelector:(SEL)aSelector withObject:(nullable id)anArgument afterDelay:(NSTimeInterval)delay; 函數內部是經過NSTimer定時器實現,在NSRunLoop沒有開啓的狀況下,NSTimer不會獲得正常運行。

  • 類的加載和初始化

    • + (void)load;
      調用:程序一啓動的時候就會把全部的類加載進內存
      做用:加載類的時候調用
    • + (void)initialize;
      調用:當第一次使用這個類或者子類的時候調用
      做用:初始化類
  • 代碼佈局仍是 storyboard ?
    對於複雜的、動態生成的界面,建議使用手工編寫界面。
    對於須要統一風格的按鈕或UI控件,建議使用手工用代碼來構造。方便以後的修改和複用。
    對於須要有繼承或組合關係的 UIView 類或 UIViewController 類,建議用代碼手工編寫界面。
    對於那些簡單的、靜態的、非核心功能界面,能夠考慮使用 xib 或 storyboard 來完成。

  • 有些圖片加載的比較慢怎麼處理?你是怎麼優化程序的性能的?

    1. 圖片的下載放在異步的線程
    2. 圖片的下載過程使用佔位圖片
    3. 若是圖片較大,能夠考慮多線程斷點下載
  • Foundation對象與Core Foundation對象有什麼區別

    • Foundation對象是OC的,Core Foundation對象是C對象
    • 數據類型之間的轉換
      ARC: __bridge_retained__bridge_transfer
      非ARC: __bridge
  • 寫 個「標準」宏,這個宏輸出兩個參數並返回較大的 #define MIN(X,Y) ((X)>(Y)?(Y):(X))

  • iPhone OS中有沒有垃圾回收? 沒有

  • self.name=「object」 和 name=「object」有什麼區別?
    前者其實是調用了set 方法給變量賦值, 後者是直接給變量賦值

  • Objective-c中有私有方法嗎?私有變量呢?
    沒有私有法,但能夠將方法直接實如今.m文件中不在.h 件中聲明時,外部也不能訪問。
    有私有變量

  • Objective-c中有多重繼承麼?不是的話有聲明替代?
    沒有多繼承,能夠經過協議模擬多繼承

  • 多態性
    答案:不一樣對象以本身的方式響應相同的消息的能力叫作多態。意思就是假設生物類(life)都用有一個相同的方法-eat;那人類屬於生物,豬也屬於生物,都繼承了life後,實現各自的eat,可是調用是咱們只需調用各自的eat方法。
    多態。 主要是將數據類型的肯定由編譯時,推遲到了運行時。好比運行的時候修改某個方法的實現,或者枚舉某個對象都有哪些屬性等等。也就是不一樣的對象以本身的方式響應了相同的消息(響應了eat這個選擇器)。所以也能夠說,運行時機制是多態的基礎。
    多態,子類指針能夠賦值給父類。關於多態,繼承和封裝基本最好都有個自我意識的理解。
    站在編程的角度來講,就是以C語言的視角看待OC中的對象、類、方法等等 也就是能夠理爲類、對象、方法被映射成了一些結構體、函數、指針等等 好比你要枚舉某個對象有哪些屬性,就能夠調運行時裏的一些函數。 JSonModel、YYModel就是基於運行時實現的,其經過枚舉model裏有哪些屬性、及屬性的類型,去對應的json(數組和字典)來找相應的字段,進而完成解析

  • obj-c的優缺點

    • 優勢
      1. Cateogies
      2. Posing
      3. 運行時特性
      4. 指標計算
      5. 彈性訊息傳遞
      6. 不是一個過分複雜的 C 衍生語言
      7. Objective-C 與 C++ 可混合編程
    • 缺點:
      1. 不支援命名空間,對於命名衝突,可使用長命名法或特殊前綴解決,若是是引入的第三方庫之間的命名衝突,可使用link命令及flag解決衝突
      2. 不支持運算符重載
      3. 不支持多重繼承
      4. 使用動態運行時類型,全部的方法都是函數調用,因此不少編譯時優化方法都用不到。(如內聯函數等),性能低劣。
  • 靜態語言:你寫的源代碼編譯以後徹底變成了機器碼 效率高
    動態語言:你寫的源代碼沒有徹底編譯成機器碼

  • 全局變量和局部變量在內存中是否有區別?若是有,是什麼區別?
    全局變量儲存在靜態數據庫,局部變量在堆棧

  • id 聲明的變量有什麼特性?

    1. 沒有 * 號
    2. 動態數據類型
    3. id聲明的變量能指向任何OC對象(設置是nil),而不關心其具體類型
    4. 在運行時檢查其具體類型
    5. 能夠對其發送任何(存在的)消息
  • 蘋果的安全機制:

    1. 沒通過用戶贊成,你不能隨便獲取用戶信息。
    2. 全部的程序都在沙盒裏運行,B程序不能進入A程序的運行範圍。
    3. 若是跟錢有關,好比說支付寶,這些底層的實現都是保密的,只提供接口供開發者調用,這樣的話安全性獲得保障。
    4. 若是要防止代碼被反編譯,能夠將本身的代碼中的.m文件封裝成靜態庫(.a文件)或者是framework文件,只提供給其它人.h文件。這樣就保證了我的代碼的安全性。
    5. 網絡登陸的話跟用戶名跟密碼相關要發送POST請求,若是是GET請求的話密碼會直接在URL中顯示。而後同時要對賬號密碼採用加密技術,加一句:咱們公司用的是MD5,可是如今MD5有一個專門的網站來破解,爲了防止這個,能夠採用加鹽技術。
  • 寫一個NSString類的實現

    + (id)stringWithCString: (c*****t char*)nullTerminatedCString  encoding: (NSStringEncoding)encoding { 
      NSString  *obj; 
      obj = [self allocWithZone: NSDefaultMallocZone()]; 
      obj = [obj initWithCString: nullTerminatedCString encoding: encoding]; 
      return AUTORELEASE(obj); 
    } 
    複製代碼
  • 什麼是平衡二叉樹?
    左右子樹都是平衡二叉樹且左右子樹的深度差值的絕對值不大於1

  • 局部變量可否和全局變量重名?
    能,局部會屏蔽全局。要用全局變量,須要使用"::"
    局部變量能夠與全局變量同名,在函數內引用這個變量時,會用到同名的局部變量,而不會用到全局變量。對於有些編譯器而言,在同一個函數內能夠定義多個同名的局部變量,好比在兩個循環體內都定義一個同名的局部變量,而那個局部變量的做用域就在那個循環體內

  • 如何引用一個已經定義過的全局變量?
    答:能夠用引用頭文件的方式,也能夠用extern關鍵字,若是用引用頭文件方式來引用某個在頭文件中聲明的全局變量,假定你將那個變寫錯了,那麼在編譯期間會報錯,若是你用extern方式引用時,假定你犯了一樣的錯誤,那麼在編譯期間不會報錯,而在鏈接期間報錯。

  • NSString 和 NSMutableString 有什麼區別:
    NSString 至關於一個 const char* 不能夠改變。
    NSMutableString 至關於 char* 能夠改變內部的內容。

  • 圖片操做:
    imageNamed: 優勢是當加載時會緩存圖片。圖片使用頻繁的使用比較好,通常用於加載小圖片。
    iamgeWithContentsFile: 大圖片。每次調用,會佔緩存。
    imageWithContentsOfFile:僅加載圖片,圖像數據不會緩存。所以對於較大的圖片以及使用狀況較少時,那就能夠用該方法,下降內存消耗。

  • 類實例(成員)變量的 @protected , @private, @public 聲明各有什麼含義?
    @protected :受保護的,該實例變量只能在該類和其子類內訪問,其餘類內不能訪問。
    @private :私有的,該實例變量只能在該類內訪問,其餘類內不能訪問。
    @public :共有的,該實例變量誰均可以訪問。

  • @dynamic 和 @synthesize
    @dynamic: 的意思是告訴編譯器,屬性的獲取與賦值方法由用戶本身實現, 不自動生成。對於只讀屬性須要提供 setter,對於讀寫屬性須要提供 setter 和 getter。
    @synthesize: 意思是,除非開發人員已經作了,不然由編譯器生成 getter 和 setter 屬性聲明。

  • UIscrollVew 到了什麼設計模式?還能再foundation庫中找到相似的嗎?
    組合模式(composition):全部的container view都用了這個模式
    觀察者模式(observer):全部的UIResponder都用了這個模式。
    模板模式(Template):全部datasource和delegate接口都是模板模式的典型應用

  • _btn.frame.origin.y = 10 錯誤
    緣由:OC語法規定不容許直接修改某個對象的結構體屬性的成員。_btn 是個對象,frame是個結構體。
    對象和結構體是不同的,結構體是C語言中的,裏面能夠定義許多屬性,可是不能定義方法,而對象是便可以定義屬性又能夠定義方法的,是典型的面向對象語法。
    如何改變對象中結構體屬性的成員:

    // 先取出結構體
    CGRect frame = _btn.frame;
    // 修改結構體
    frame.origin.y -= 10;
    // 將修改後的結構體從新賦值回去
    _btn.frame = frame;
    複製代碼

    或者

    // 先取出y值
    CGFloat y = _btn.frame.origin.y;
    // 修改y值
    y -= 10;
    // 從新設置_btn的y值,其餘屬性和_btn保持不變
    _btn.frame = CGRectMake(_btn.frame.origin.x, y, _btn.frame.size.width, _btn.frame.size.height);
    複製代碼
  • 若是想讓同一個控件同時即改變位置的移動,又放大。這樣設置是無效果的。這樣操做是建立新的transform而後賦值,給按鈕的transform,第二次賦值的會把以前賦值的給覆蓋,因此會達不到想要的效果。

    _btn.transform = CGAffineTransformMakeTranslation(0, 100);
    _btn.transform = CGAffineTransformMakeScale(1.2, 1.2);
    複製代碼

    解決方法:

    _btn.transform = CGAffineTransformMakeTranslation(0, 100);
    // 在以前的transform狀況下,繼續添加縮放的形變。
    _btn.transform = CGAffineTransformScale(_btn.transform, 1.2, 1.2);
    複製代碼
  • 四捨五入問題

    float i = 1.7;
    // 會自動四捨五入,不保留小數
    NSLog(@"%0.f",i); // 打印結果2
    // 強轉類型不會四捨五入
    int j = (int)i;
    NSLog(@"%d",j); // 打印結果1
    複製代碼
  • id、nil表明什麼?

    • id 和 void *並不是徹底同樣。在上面的代碼中,id是指向struct objc_object的一個指針,這個意思基本上是說,id是一個指向任何一個繼承了Object(或者NSObject)類的對象。須要注意的是id是一個指針,因此你在使用id的時候不須要加星號。好比id foo=nil定義了一個nil指針,這個指針指向NSObject的一個任意子類。而id *foo=nil則定義了一個指針,這個指針指向另外一個指針,被指向的這個指針指向NSObject的一個子類。
    • nil和C語言的NULL相同,在objc/objc.h中定義。nil表示一個Objctive-C對象,這個對象的指針指向空(沒有東西就是空)。
      首字母大寫的Nil和nil有一點不同,Nil定義一個指向空的類(是Class,而不是對象)。
  • 常見的object-c的數據類型有那些,和C的基本數據類型有什麼區別?如:NSInteger和int 答:object-c的數據類型有NSString,NSNumber,NSArray,NSMutableArray,NSData等等,這些都是class,建立後即是對象,而C語言的基本數據類型int,只是必定字節的內存空間,用於存放數值;NSInteger是基本數據類型,並非NSNumber的子類,固然也不是NSObject的子類。NSInteger是基本數據類型Int或者Long的別名(NSInteger的定義typedef long NSInteger),它的區別在於,NSInteger會根據系統是32位仍是64位來決定是自己是int仍是Long。

相關文章
相關標籤/搜索