可能碰到的iOS筆試面試題(5)--Objective-C

面試筆試都是必考語法知識的。請認真復習和深入研究OC。

Objective-C

方法和選擇器有何不同?(Difference between method and selector?)

  • selector是一個方法的名字,method是一個組合體,包含了名字和實現.

Core Foundation的內存管理

  • 凡是帶有Create、Copy、Retain等字眼的函數,創建出來的對象,都需要在最后做一次release
  • 比如CFRunLoopObserverCreate release函數:CFRelease(對象);

malloc和New的區別

  • new 是c++中的操作符,malloc是c 中的一個函數

  • new 不止是分配內存,而且會調用類的構造函數,同理delete會調用類的析構函數,而malloc則只分配內存,不會進行初始化類成員的工作,同樣free也不會調用析構函數

  • 內存泄漏對于malloc或者new都可以檢查出來的,區別在于new可以指明是那個文件的那一行, 而malloc沒有這些信息。

  • new 和 malloc效率比較

  • new可以認為是malloc加構造函數的執行。

  • new出來的指針是直接帶類型信息的。

你是否接觸過OC中的反射機制?簡單聊一下概念和使用

  • class反射
  • 通過類名的字符串形式實例化對象
    Class class NSClassFromString@(@"student");
    Student *stu = [[class alloc ]init];
  • 將類名變為字符串
    Class class =[Student class];
    NSString *className = NSStringFromClass(class);
  • SEL的反射
  • 通過方法的字符串形式實例化方法
    SEL selector = NSSelectorFromClass(@"setName");
    [stu performSelector:selector withObject:@"Mike"];
  • 將方法變成字符串
    NSStringFomrSelector(@selector*(setName:))

什么是SEL?如何聲明一個SEL?通過那些方法能夠,調用SEL包裝起來的方法?

  • SEL就是對方法的一種包裝。包裝的SEL類型數據它對應相應的方法地址,找到方法地址就可以調用方法。在內存中每個類的方法都存儲在類對象中,每個方法都有一個與之對應的SEL類型的數據,根據一個SEL數據就可以找到對應的方法地址,進而調用方法。

  • SEL s1 = @selector(test1); // 將test1方法包裝成SEL對象

  • SEL s2 = NSSelectorFromString(@"test1"); // 將一個字符串方法轉換成為SEL對象

  • 調用方法有兩種方式:

  • 1.直接通過方法名來調用 [person text]

  • 2.間接的通過SEL數據來調用 SEL aaa=@selector(text); [person performSelector:aaa];

協議中<NSObject>是什么意思?子類繼承了父類,那么子類會遵守父類中遵守的協議嗎?協議中能夠定義成員變量?如何約束一個對象類型的變量要存儲的地址是遵守一個協議對象?

  • 遵守NSObject協議
  • 能,但是只在頭文件中聲明,編譯器是不會自動生成實例變量的。需要自己處理getter和setter方法
  • id<xxx>

NS/CF/CG/CA/UI這些前綴分別是什么含義

  • 函數歸屬于屬于cocoa Fundation框架
  • 函數歸屬于屬于core Fundation框架
  • 函數歸屬于屬于CoreGraphics.frameworks框架
  • 函數歸屬于屬于CoreAnimation.frameworks框架
  • 函數歸屬于屬于UIkit框架

面向對象都有哪些特征以及你對這些特征的理解。

  • 繼承:繼承是從已有類得到繼承信息創建新類的過程。提供繼承信息的類被稱為父類(超類、基類);得到繼承信息的類被稱為子類(派生類)。 繼承讓變化中的軟件系統有了一定的延續性,同時繼承也是封裝程序中可變因素的重要手段。

  • 封裝:封裝是把數據和操作數據的方法綁定起來,對數據的訪問只能通過已定義的接口。我們在類中編寫的方法就是對實現細節的一種封裝;我們編寫一個類就是對數據和數據操作的封裝。可以說,封裝就是隱藏一切可隱藏的東西,只向外界提供最簡單的編程接口。

  • 多態性:多態性是指允許不同子類型的對象對同一消息作出不同的響應。簡單的說就是用同樣的對象引用調用同樣的方法但是做了不同的事情。多態性分為編譯時的多態性和運行時的多態性。方法重載(overload)實現的是編譯時的多態性(也稱為前綁定),而方法重寫(override)實現的是運行時的多態性(也稱為后綁定)。運行時的多態是面向對象最精髓的東西,要實現多態需要做兩件事:1. 方法重寫(子類繼承父類并重寫父類中已有的或抽象的方法);2. 對象造型(用父類型引用引用子類型對象,這樣同樣的引用調用同樣的方法就會根據子類對象的不同而表現出不同的行為)。

  • 抽象:抽象是將一類對象的共同特征總結出來構造類的過程,包括數據抽象和行為抽象兩方面。抽象只關注對象有哪些屬性和行為,并不關注這些行為的細節是什么。

我們說的Objective-C是動態運行時語言是什么意思? (When we call objective c is runtime language what does it mean?)

  • 主要是將數據類型的確定由編譯時,推遲到了運行時。這個問題其實淺涉及到兩個概念,運行時和多態。

  • 簡單來說, 運行時機制使我們直到運行時才去決定一個對象的類別,以及調用該類別對象指定方法。

  • 多態:不同對象以自己的方式響應相同的消息的能力叫做多態。

  • 意思就是假設生物類(life)都擁有一個相同的方法-eat;那人類屬于生物,豬也屬于生物,都繼承了life后,實現各自的eat,但是調用是我們只需調用各自的eat方法。也就是不同的對象以自己的方式響應了相同的消 息(響應了eat這個選擇器)。因此也可以說,運行時機制是多態的基礎.

readwrite, readonly, assign, retain, copy, nonatomic屬性的作用?

  • readwrite 是可讀可寫特性;需要生成getter方法和setter方法;
  • readonly 是只讀特性 只會生成getter方法 不會生成setter方法 ,不希望屬性在類外改變;
  • assign 是賦值特性,setter方法將傳入參數賦值給實例變量;僅設置變量時; assign用于簡單數據類型,如NSInteger,double,bool;
  • retain 表示持有特性,setter方法將傳入參數先保留,再賦值,傳入參數的引用計數retaincount會+1;
  • copy 表示賦值特性,setter方法將傳入對象復制一份;需要完全一份新的變量時;
  • nonatomic 非原子操作,決定編譯器生成的setter getter是否是原子操作;
  • atomic表示多線程安全,一般使用 nonatomic。

簡述NotificationCenter、KVC、KVO、Delegate?并說明它們之間的區別?(重點)

  • KVO(Key-Value- Observing):一對多, 觀察者模式,鍵值觀察機制,它提供了觀察某一屬性變化的方法,極大簡化了代碼。

  • KVC(Key-Value-Coding):是鍵值編碼, 一個對象在調用setValue的時候,

    • 檢查是否存在相應key的set方法,存在就調用set方法。

    • set方法不存在,就查找_key的成員變量是否存在,存在就直接賦值。

    • 如果_key沒找到,就查找相同名稱的key,存在就賦值。

    • 如果沒有就調用valueForUndefinedkey和setValue:forUndefinedKey。

  • Delegate: 通常發送者和接收者的關系是直接的一對一的關系。

    • 代理的目的是改變或傳遞控制鏈。允許一個類在某些特定時刻通知到其他類,而不需要獲取到那些類的指針。

    • 可以減少框架復雜度。消息的發送者(sender)告知接收者(receiver)某個事件將要發生,delegate同意然然后發送者響應事件,delegate機制使得接收者可以改變發送者的行為。

  • Notification: 觀察者模式, 通常發送者和接收者的關系是間接的多對多關系。 消息的發送者告知接收者事件已經發生或者將要發送,僅此而已,接收者并不能反過來影響發送者的行為。

  • 區別

    • 效率肯定是delegate比NSNotification高。
    • delegate方法比notification更加直接,需要關注返回值,所以delegate方法往往包含should這個很傳神的詞。相反的,notification最大的特色就是不關心結果。所以notification往往用did這個詞匯。
    • 兩個模塊之間聯系不是很緊密,就用notification傳值,例如多線程之間傳值用notificaiton。
    • delegate只是一種較為簡單的回調,且主要用在一個模塊中,例如底層功能完成了,需要把一些值傳到上層去,就事先把上層的函數通過delegate傳到底層,然后在底層call這個delegate,它們都在一個模塊中,完成一個功能,例如說 NavgationController 從 B 界面到A 點返回按鈕 (調用popViewController方法) 可以用delegate比較好。

懶加載(What is lazy loading ?)

  • 就是懶加載,只在用到的時候才去初始化。也可以理解成延時加載。我覺得最好也最簡單的一個列子就是tableView中圖片的加載顯示了, 一個延時加載, 避免內存過高,一個異步加載,避免線程堵塞提高用戶體驗

OC有多繼承嗎?沒有的話可以用什么方法替代?

  • 多繼承即一個子類可以有多個父類,它繼承了多個父類的特性。
  • Object-c的類沒有多繼承,只支持單繼承,如果要實現多繼承的話,可以通過類別和協議的方式來實現。
  • protocol(協議)可以實現多個接口,通過實現多個接口可以完成多繼承;
  • Category(類別)一般使用分類,用Category去重寫類的方法,僅對本Category有效,不會影響到其他類與原有類的關系。

分別描述類別(categories)和延展(extensions)是什么?以及兩者的區別?繼承和類別在實現中有何區別?為什么Category只能為對象添加方法,卻不能添加成員變量?

  • 類別: 在沒有原類.m文件的基礎上,給該類添加方法;
  • 延展:一種特殊形式的類別,主要在一個類的.m文件里聲明和實現延展的作用,就是給某類添加私有方法或是私有變量。
  • 兩個的區別:
    • 延展可以添加屬性并且它添加的方法是必須要實現的。延展可以認為是一個私有的類目。
    • 類別可以在不知道,不改變原來代碼的情況下往里面添加新的方法,只能添加,不能刪除修改。
    • 并且如果類別和原來類中的方法產生名稱沖突,則類別將覆蓋原來的方法,因為類別具有更高的優先級。
  • 繼承可以增加,修改刪除方法,添加屬性。
  • Category只能為對象添加方法,卻不能添加成員變量的原因:如果可以添加成員變量,添加的成員變量沒有辦法初始化

Objective-C有私有方法么?私有變量呢?如多沒有的話,有沒有什么代替的方法?

  • objective-c類里面的方法只有兩種,靜態方法和實例方法.但是可以通過把方法的聲明和定義都放在.m文件中來實現一個表面上的私有方法。有私有變量,可以通過@private來修飾,或者把聲明放到.m文件中。在Objective‐C中,所有實例變量默認都是私有的, 所有實例方法默認都是公有的

include與#import的區別? #import與@class的區別?

  • import指令是Object-C針對#include的改進版本,#import確保引用的文件只會被引用一次,這樣你就不會陷入遞歸包含的問題中。

  • import與@class二者的區別在于:

    • import會鏈入該頭文件的全部信息,包括實例變量和方法等;而@class只是告訴編譯器,其后面聲明的名稱是類的名稱,至于這些類是如何定義的,暫時不用考慮。

    • 在頭文件中一般使用@class來聲明這個名稱是類的名稱,不需要知道其內部的實體變量和方法.
    • 而在實現類里面,因為會用到這個引用類的內部的實體變量和方法,所以需要使用#import來包含這個被引用類的頭文件。
    • 在編譯效率方面,如果你有100個頭文件都#import了同一個頭文件,或者這些文件是依次引用的,如A–>B, B–>C, C–>D這樣的引用關系。當最開始的那個頭文件有變化的話,后面所有引用它的類都需要重新編譯,如果你的類有很多的話,這將耗費大量的時間。而是用@class則不會。
    • 如果有循環依賴關系,如:A–>B, B–>A這樣的相互依賴關系,如果使用#import來相互包含,那么就會出現編譯錯誤,如果使用@class在兩個類的頭文件中相互聲明,則不會有編譯錯誤出現。

淺復制(拷貝)和深復制的區別? (Difference between shallow copy and deep copy?)

  • 淺復制(copy):只復制指向對象的指針,而不復制引用對象本身。

  • 深復制(mutableCopy):復制引用對象本身。深復制就好理解了,內存中存在了兩份獨立對象本身, 當修改A時,A_copy不變。

類變量的@protected,@private,@public,@package聲明各有什么含義?

變量的作用域不同。

  • @protected 該類和子類中訪問,是默認的;
  • @private 只能在本類中訪問;
  • @public 任何地方都能訪問;
  • @package 本包內使用,跨包不可以

Objective-C與C、C+++之間的聯系和區別?

  • Objective-C和C++都是C的面向對象的超集。
  • Object與C++的區別主要點:Objective-C是完全動態的,支持在運行時動態類型決議(dynamic typing),動態綁定(dynamic binding)以及動態裝載(dynamic loading);而C++是部分動態的,編譯時靜態綁定,通過嵌入類(多重繼承)和虛函數(虛表)來模擬實現。
  • Objective-C 在語言層次上支持動態消息轉發,其消息發送語法為 [object function]; 而且C++ 為 object->function()。 兩者的語義也不同,在 Objective-C 里是說發送消息到一個對象上,至于這個對象能不能響應消息以及是響應還是轉發消息都不會 crash; 而在 C++ 里是說對象進行了某個操作,如果對象沒有這個操作的話,要么編譯會報錯(靜態綁定),要么程序會 crash 掉的(動態綁定)。

目標-動作機制

  • 目標是動作消息的接收者。一個控件,或者更為常見的是它的單元,以插座變量的形式保有其動作消息的目標。
  • 動作是控件發送給目標的消息,或者從目標的角度看,它是目標為了響應動作而實現的方法. 程序需要某些機制來進行事件和指令的翻譯。這個機制就是目標-動作機制。

Objective-C優點和缺點

  • 優點:1.Cateogies 2.Posing 3.動態識別 4.指標計算 5.彈性訊息傳遞 6.不是一個過度復雜的C衍生語言 7.Objective-C與C++可混合編程

  • 缺點:1.不支持命名空間 2.不支持運算符重載 3.不支持多重繼承 4.使用動態運行時類型,所有的方法都是函數調用,所以很多編譯時優化方法都用不到。(如內聯函數等),性能低劣。

C語言的函數調用和oc的消息機制有什么區別?

  • 對于C語言,函數的調用在編譯的時候會決定調用哪個函數。編譯完成之后直接順序執行。
  • OC的函數調用成為消息發送。屬于動態調用過程。在編譯的時候并不能決定真正調用哪個函數(事實證明,在編譯階段,OC可以調用任何函數,即使這個函數并未實現,只要申明過就不會報錯。而C語言在編譯階段就會報錯)。只有在真正運行的時候才會根據函數的名稱找到對應的函數來調用。

什么是謂詞

謂詞就是通過NSPredicate給定的邏輯條件作為約束條件,完成對數據的篩選。

//定義謂詞對象,謂詞對象中包含了過濾條件

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"age<%d",30];

//使用謂詞條件過濾數組中的元素,過濾之后返回查詢的結果

NSArray *array = [persons filteredArrayUsingPredicate:predicate];

//可以使用&&進行多條件過濾

predicate = [NSPredicate predicateWithFormat:@"name='1' && age>40"];

array = [persons filteredArrayUsingPredicate:predicate];

//包含語句的使用

predicate = [NSPredicate predicateWithFormat:@"self.name IN {'1','2','4'} || self.age IN{30,40}"];

//指定字符開頭和指定字符結尾,是否包含指定字符

//name以a開頭的

predicate = [NSPredicate predicateWithFormat:@"name BEGINSWITH 'a'"];

//name以ba結尾的

predicate = [NSPredicate predicateWithFormat:@"name ENDSWITH 'ba'"];

//name中包含字符a的

predicate = [NSPredicate predicateWithFormat:@"name CONTAINS 'a'"];

//like進行匹配多個字符

//name中只要有s字符就滿足條件

predicate = [NSPredicate predicateWithFormat:@"name like 's'"];

//?代表一個字符,下面的查詢條件是:name中第二個字符是s的

predicate = [NSPredicate predicateWithFormat:@"name like '?s'"];

C與OC混用

處理.m可以識別c和oc,.mm可以識別c c++ oc 但是cpp只能用c/c++

atomic和nonatomic的區別

  • atomic提供多線程安全,防止讀寫未完成的時候被另外一個線程讀寫,造成數據錯誤。
  • nonatomic在自己管理內存的環境中,解析的訪問器保留并自動釋放返回值,若指定了nonatomic,那么訪問器只是簡單的返回這個值。

常見的oc數據類型哪些,和c的基本類型有啥區別

  • 常見的:NSInteger CGFloat NSString NSNumber NSArray NSDate
  • NSInteger根據32或者64位系統決定本身是int還是long
  • CGFloat根據32或者64位系統決定本身是float還是double
  • NSString NSNumber NSArray NSDate都是指針類型的對象,在堆中分配內存,c語言中的char int 等都是在棧中分配空間

id和nil代表什么

  • id類型的指針可以指向任何OC對象
  • nil代表空值(空指針的值,0)

nil和NULL的區別?

  • 從oc的官方語法上看,nil表示對象的指針 即對象的引用為空
  • null表示指向基礎數據類型變量 即c語言變量的指針為空
  • 在非arc中 兩個空可以互換,但是在arc中 普通指針和對象引用被嚴格限制,不能互換

nil、Nil、NULL和NSNull區別

  • nil和C語言的NULL相同,在objc/objc.h中定義。nil表示Objective-C對象的值為空。在C語言中,指針的空值用NULL表示。在Objective-C中,nil對象調用任何方法表示什么也不執行,也不會崩潰。
  • Nil:那么對于我們Objective-C開發來說,Nil也就代表((void *)0)。但是它是用于代表空類的. 比如:Class myClass = Nil;
  • NULL: 在C語言中,NULL是無類型的,只是一個宏,它代表空. 這就是在C/C++中的空指針。對于我們Objective-C開發來說,NULL就表示((void*)0).
  • NSNull:NSNull是繼承于NSObject的類型。它是很特殊的類,它表示是空,什么也不存儲,但是它卻是對象,只是一個占位對象。使用場景就不一樣了,比如說服務端接口中讓我們在值為空時,傳空。NSDictionry *parameters = @{@"arg1" : @"value1",@"arg2" : arg2.isEmpty ? [NSNull null] : arg2};

  • NULL、nil、Nil這三者對于Objective-C中值是一樣的,都是(void *)0,那么為什么要區分呢?又與NSNull之間有什么區別:

  • NULL是宏,是對于C語言指針而使用的,表示空指針

  • nil是宏,是對于Objective-C中的對象而使用的,表示對象為空

  • Nil是宏,是對于Objective-C中的類而使用的,表示類指向空

  • NSNull是類類型,是用于表示空的占位對象,與JS或者服務端的null類似的含意

向一個nil對象發送消息會發生什么?

  • 向nil發送消息是完全有效的——只是在運行時不會有任何作用。

  • 如果一個方法返回值是一個對象,那么發送給nil的消息將返回0(nil)

  • 如果方法返回值為指針類型,其指針大小為小于或者等于sizeof(void*),float,double,long double 或者long long的整型標量,發送給nil的消息將返回0。

-如果方法返回值為結構體,正如在《Mac OS X ABI 函數調用指南》,發送給nil的消息將返回0。結構體中各個字段的值將都是0。其他的結構體數據類型將不是用0填充的。

  • 如果方法的返回值不是上述提到的幾種情況,那么發送給nil的消息的返回值將是未定義的。

self.和self->的區別

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

類方法和實例方法的本質區別和聯系

類方法 實例方法
屬于類對象 屬于實例對象
只能類對象調用 實例對象調用
self是類對象 self是實例對象
類方法可以調用其他類方法 實例方法可以調用實例方法
類方法不能訪問成員變量 實例方法可以訪問成員變量
類方法不能直接調用對象方法 實例方法可以調用類方法

_block/weak修飾符區別

  • _block在arc和mrc環境下都能用,可以修飾對象,也能修飾基本數據類型
  • _weak只能在arc環境下使用,只能修飾對象(NSString),不能修飾基本數據類型(int)
  • _block對象可以在block中重新賦值,_weak不行。

寫一個NSString類的實現

NSString *str = [[NSString alloc]initWithCString:nullTerminatedCString encoding:encoding];

為什么標準頭文件都有類似以下的結構?

ifndef __INCvxWorksh

define __INCvxWorksh

ifdef __cplusplus

extern "C" {

endif

ifdef __cplusplus

}

endif

endif

顯然,頭文件中的編譯宏“#ifndef __INCvxWorksh、#define __INCvxWorksh、#endif” 的作用是防止該頭文件被重復引用

init和initwithobject區別(語法)?
  • 后者給屬性賦值

@property的本質是什么?ivar、getter、setter是如何生成并添加到這個類中的?

@property的本質:
@property = ivar(實例變量) + getter(取方法) + setter(存方法)
“屬性” (property)有兩大概念:ivar(實例變量)、存取方法(access method = getter + setter)
ivar、getter、setter如何生成并添加到類中:
這是編譯器自動合成的,通過@synthesize關鍵字指定,若不指定,默認為@synthesize propertyName = _propertyName;若手動實現了getter/setter方法,則不會自動合成。
現在編譯器已經默認為我們添加@synthesize propertyName = _propertyName;因此不再需要手動添加了,除非你真的要改成員變量名。
生成getter方法時,會判斷當前屬性名是否有_,比如聲明屬性為@property (nonatomic, copy) NSString *_name;那么所生成的成員變量名就會變成__name,如果我們要手動生成getter方法,就要判斷是否以_開頭了。
不過,命名都要有規范,是不允許聲明屬性是使用_開頭的,不規范的命名,在使用runtime時,會帶來很多的不方便的。

這個寫法會出什么問題:@property (copy) NSMutableArray *array;

  • 沒有指明為nonatomic,因此就是atomic原子操作,會影響性能。該屬性使用了同步鎖,會在創建時生成一些額外的代碼用于幫助編寫多線程程序,這會帶來性能問題,通過聲明nonatomic可以節省這些雖然很小但是不必要額外開銷。在我們的應用程序中,幾乎都是使用nonatomic來聲明的,因為使用atomic并不能保證絕對的線程安全,對于要絕對保證線程安全的操作,還需要使用更高級的方式來處理,比如NSSpinLock、@syncronized等
  • 因為使用的是copy,所得到的實際是NSArray類型,它是不可變的,若在使用中使用了增、刪、改操作,則會crash

@protocol和category中如何使用 @property

?   在protocol中使用@property只會生成setter和getter方法聲明,我們使用屬性的目的是希望遵守我協議的對象能實現該屬性
?   category使用@property也是只會生成setter和getter方法的聲明,如果我們真的需要給category增加屬性的實現,需要借助于運行時的兩個函數:
?   objc_setAssociatedObject
?   objc_getAssociatedObject

@property中有哪些屬性關鍵字?

  1. 原子性 (atomic,nonatomic)

  2. 讀寫(readwrite, readonly)

  3. 內存管理(assign, strong, weak, unsafe_unretained,copy)

  4. getter、setter

isa指針問題

  • isa:是一個Class 類型的指針. 每個實例對象有個isa的指針,他指向對象的類,而Class里也有個isa的指針, 指向meteClass(元類)。元類保存了類方法的列表。當類方法被調用時,先會從本身查找類方法的實現,如果沒有,元類會向他父類查找該方法。同時注意的是:元類(meteClass)也是類,它也是對象。元類也有isa指針,它的isa指針最終指向的是一個根元類(root meteClass).根元類的isa指針指向本身,這樣形成了一個封閉的內循環。

如何訪問并修改一個類的私有屬性?

  • 一種是通過KVC獲取
  • 通過runtime訪問并修改私有屬性

如何為 Class 定義一個對外只讀對內可讀寫的屬性?

在頭文件中將屬性定義為readonly,在.m文件中將屬性重新定義為readwrite

Objective-C 中,meta-class 指的是什么?

meta-class 是 Class 對象的類,為這個Class類存儲類方法,當一個類發送消息時,就去這個類對應的meta-class中查找那個消息,每個Class都有不同的meta-class,所有的meta-class都使用基類的meta-class(假如類繼承NSObject,那么他所對應的meta-class也是NSObject)作為他們的類

Objective-C 的class是如何實現的?Selector是如何被轉化為 C 語言的函數調用的?

  • 當一個類被正確的編譯過后,在這個編譯成功的類里面,存在一個變量用于保存這個類的信息。我們可以通過[NSClassFromString]或[obj class]。這樣的機制允許我們在程序執行的過程當中,可以Class來得到對象的類,也可以在程序執行的階段動態的生成一個在編譯階段無法確定的一個對象。 (isa指針)
  • @selector()基本可以等同C語言的中函數指針,只不過C語言中,可以把函數名直接賦給一個函數指針,而Object-C的類不能直接應用函數指針,這樣只能做一個@selector語法來取.

    @interface foo
    -(int)add:int val;
    @end
    
    SEL class_func ; //定義一個類方法指針
    class_func = @selector(add:int);
    
  • @selector是查找當前類的方法,而[object @selector(方法名:方法參數..) ] ;是取object對應類的相應方法.

  • 查找類方法時,除了方法名,方法參數也查詢條件之一.

  • 可以用字符串來找方法 SEL 變量名 = NSSelectorFromString(方法名字的字符串);

  • 可以運行中用SEL變量反向查出方法名字字符串。NSString *變量名 = NSStringFromSelector(SEL參數);

  • 取到selector的值以后,執行seletor。 SEL變量的執行.用performSelecor方法來執行.
    [對象 performSelector:SEL變量 withObject:參數1 withObject:參數2];

對于語句NSString *obj = [[NSData alloc] init]; ,編譯時和運行時obj分別是什么類型?

  • 編譯時是NSString類型 ,運行時是NSData類型.

@synthesize和@dynamic分別有什么作用?

- @property有兩個對應的詞,一個是 @synthesize,一個是 @dynamic。如果 @synthesize和 @dynamic都沒寫,那么默認的就是@syntheszie var = _var;
- @synthesize 的語義是如果你沒有手動實現 setter 方法和 getter 方法,那么編譯器會自動為你加上這兩個方法。
- @dynamic 告訴編譯器:屬性的 setter 與 getter 方法由用戶自己實現,不自動生成。(當然對于 readonly 的屬性只需提供 getter 即可)。假如一個屬性被聲明為 @dynamic var,然后你沒有提供 @setter方法和 @getter 方法,編譯的時候沒問題,但是當程序運行到 instance.var = someVar,由于缺 setter 方法會導致程序崩潰;或者當運行到 someVar = var 時,由于缺 getter 方法同樣會導致崩潰。編譯時沒問題,運行時才執行相應的方法,這就是所謂的動態綁定。

NSString 的時候用copy和strong的區別?

OC中NSString為不可變字符串的時候,用copy和strong都是只分配一次內存,但是如果用copy的時候,需要先判斷字符串是否是不可變字符串,如果是不可變字符串,就不再分配空間,如果是可變字符串才分配空間。如果程序中用到NSString的地方特別多,每一次都要先進行判斷就會耗費性能,影響用戶體驗,用strong就不會再進行判斷,所以,不可變字符串可以直接用strong。

NSArray、NSSet、NSDictionary與NSMutableArray、NSMutableSet、NSMutableDictionary的特性和作用(遇到copy修飾產生的變化)

  • 特性:
  • NSArray表示不可變數組,是有序元素集,只能存儲對象類型,可通過索引直接訪問元素,而且元素類型可以不一樣,但是不能進行增、刪、改操作;NSMutableArray是可變數組,能進行增、刪、改操作。通過索引查詢值很快,但是插入、刪除等效率很低。
  • NSSet表示不可變集合,具有確定性、互異性、無序性的特點,只能訪問而不能修改集合;NSMutableSet表示可變集合,可以對集合進行增、刪、改操作。集合通過值查詢很快,插入、刪除操作極快。
  • NSDictionary表示不可變字典,具有無序性的特點,每個key對應的值是唯一的,可通過key直接獲取值;NSMutableDictionary表示可變字典,能對字典進行增、刪、改操作。通過key查詢值、插入、刪除值都很快。
  • 作用:
  • 數組用于處理一組有序的數據集,比如常用的列表的dataSource要求有序,可通過索引直接訪問,效率高。
  • 集合要求具有確定性、互異性、無序性,在iOS開發中是比較少使用到的,筆者也不清楚如何說明其作用
  • 字典是鍵值對數據集,操作字典效率極高,時間復雜度為常量,但是值是無序的。在ios中,常見的JSON轉字典,字典轉模型就是其中一種應用。

請把字符串2015-04-10格式化日期轉為NSDate類型

NSString *timeStr = @"2015-04-10";
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
formatter.dateFormat = @"yyyy-MM-dd";
formatter.timeZone = [NSTimeZone defaultTimeZone];
NSDate *date = [formatter dateFromString:timeStr];
// 2015-04-09 16:00:00 +0000
NSLog(@"%@", date);

在一個對象的方法里:self.name=@object;和name=@object有什么不同

  • 這是老生常談的話題了,實質上就是問setter方法賦值與成員變量賦值有什么不同。通過點語法self.name實質上就是[self setName:@object];。而name這里是成員變量,直接賦值。
    一般來說,在對象的方法里成員變量和方法都是可以訪問的,我們通常會重寫Setter方法來執行某些額外的工作。比如說,外部傳一個模型過來,那么我會直接重寫Setter方法,當模型傳過來時,也就是意味著數據發生了變化,那么視圖也需要更新顯示,則在賦值新模型的同時也去刷新UI。這樣也不用再額外提供其他方法了。

怎樣使用performSelector傳入3個以上參數,其中一個為結構體

- (id)performSelector:(SEL)aSelector;
- (id)performSelector:(SEL)aSelector withObject:(id)object;
- (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2;

因為系統提供的performSelector的api中,并沒有提供三個參數。因此,我們只能傳數組或者字典,但是數組或者字典只有存入對象類型,而結構體并不是對象類型,那么怎么辦呢?
沒有辦法,我們只能通過對象放入結構作為屬性來傳過去了:

ypedef struct HYBStruct {
  int a;
  int b;
} *my_struct;
 
@interface HYBObject : NSObject
 
@property (nonatomic, assign) my_struct arg3;
@property (nonatomic, copy)  NSString *arg1;
@property (nonatomic, copy) NSString *arg2;
 
@end
 
@implementation HYBObject
 
// 在堆上分配的內存,我們要手動釋放掉
- (void)dealloc {
  free(self.arg3);
}
 
@end

測試:

my_struct str = (my_struct)(malloc(sizeof(my_struct)));
str->a = 1;
str->b = 2;
HYBObject *obj = [[HYBObject alloc] init];
obj.arg1 = @"arg1";
obj.arg2 = @"arg2";
obj.arg3 = str;
 
[self performSelector:@selector(call:) withObject:obj];
  
// 在回調時得到正確的數據的
- (void)call:(HYBObject *)obj {
    NSLog(@"%d %d", obj.arg3->a, obj.arg3->b);
}

objc中向一個對象發送消息[obj foo]和objc_msgSend()函數之間有什么關系?

實際上,編譯器在編譯時會轉換成objc_msgSend,大概會像這樣:
((void (*)(id, SEL))(void)objc_msgSend)((id)obj, sel_registerName("foo"));
也就是說,[obj foo];在objc動態編譯時,會被轉換為:objc_msgSend(obj, @selector(foo));這樣的形式,但是需要根據具體的參數類型及返回值類型進行相應的類型轉換。

下面的代碼輸出什么?


@implementation Son : Father
 
- (id)init {
    self = [super init];
    if (self) {
        NSLog(@"%@", NSStringFromClass([self class]));
        NSLog(@"%@", NSStringFromClass([super class]));
    }
    return self;
}
 
@end
 
// 輸出
NSStringFromClass([self class]) = Son
NSStringFromClass([super class]) = Son
這個題目主要是考察關于Objective-C中對self和super的理解。我們都知道:self是類的隱藏參數,指向當前調用方法的這個類的實例。那super呢?
很多人會想當然的認為“super和self類似,應該是指向父類的指針吧!”。這是很普遍的一個誤區。其實 super是一個 Magic Keyword,它本質是一個編譯器標示符,和self 是指向的同一個消息接受者!他們兩個的不同點在于:super會告訴編譯器,調用class 這個方法時,要去父類的方法,而不是本類里的。
上面的例子不管調用[self class]還是[super class],接受消息的對象都是當前 Son *xxx 這個對象。
當使用self調用方法時,會從當前類的方法列表中開始找,如果沒有,就從父類中再找;而當使用super時,則從父類的方法列表中開始找。然后調用父類的這個方法。

若一個類有實例變量NSString *_foo,調用setValue:forKey:時,可以以foo還是_foo作為key?

  • 兩者都可以。

什么時候使用NSMutableArray,什么時候使用NSArray?

  • 當數組在程序運行時,需要不斷變化的,使用NSMutableArray,當數組在初始化后,便不再改變的,使用NSArray。需要指出的是,使用NSArray只表明的是該數組在運行時不發生改變,即不能往NSAarry的數組里新增和刪除元素,但不表明其數組內的元素的內容不能發生改變。NSArray是線程安全的,NSMutableArray不是線程安全的,多線程使用到NSMutableArray需要注意。

類NSObject的那些方法經常被使用?

  • NSObject是Objetive-C的基類,其由NSObject類及一系列協議構成。
  • 其中類方法alloc、class、 description 對象方法init、dealloc、– performSelector:withObject:afterDelay:等經常被使用

什么是簡便構造方法?

  • 簡便構造方法一般由CocoaTouch框架提供,如NSNumber的 + numberWithBool: + numberWithChar: + numberWithDouble: + numberWithFloat: + numberWithInt:
  • Foundation下大部分類均有簡便構造方法,我們可以通過簡便構造方法,獲得系統給我們創建好的對象,并且不需要手動釋放。

什么是構造方法,使用構造方法有什么注意點。

什么是構造方法:構造方法是對象初始化并一個實例的方法。

構造方法有什么用: 一般在構造方法里 對類進行一些初始化操作
注意點:方法開頭必須以init開頭,接下來名稱要大寫 例如 initWithName ,initLayout

創建一個對象需要經過那三個步驟?

  • 開辟內存空間
  • 初始化參數
  • 返回內存地址值

Get方法的作用是什么?

Get方法的作用:為調用者返回對象內部的成員變量

Set方法的作用是什么?Set方法的好處?

  • Set方法的作用:為外界提供一個設置成員變量值的方法。
  • Set方法的好處:
    • 不讓數據暴露在外,保證了數據的安全性
    • 對設置的數據進行過濾

結構體當中能定義oc對象嗎?

不能, 因為結構體當中只能是類型的聲明不能進行分配空間

點語法本質是什么,寫一個點語法的例子,并寫上注釋

  • 點語法的本質是方法的調用,而不是訪問成員變量,當使用點語法時,編譯器會自動展開成相應的方法。切記點語法的本質是轉換成相應的set和get方法,如果沒有set和get方法,則不能使用點語法。
  • 例如有一個Person類 通過@property定義了name和age屬性,再提供了一個run方法。
  • Person *person = [Person new];
  • person.name=@”itcast”;//調用了person的setName方法
  • int age = person.age; // 調用了person的age方法
  • person.run //調用了person的run方法

id類型是什么,instancetype是什么,有什么區別?

  • id類型:萬能指針,能作為參數,方法的返回類型。
  • instancetype:只能作為方法的范圍類型,并且返回的類型是當前定義類的類類型。

成員變量名的命名以下劃線開頭的好處?

  • 與get方法的方法名區分開來;
  • 可以和一些其他的局部變量區分開來,下劃線開頭的變量,通常都是類的成員變量。

這段代碼有什么問題嗎:

 @implementation Person
- (void)setAge:(int)newAge {
self.age = newAge; }
@end
會死循環,會重復調用自己!self.age 改為_age即可;
并且書寫不規范:setter方法中的newAge應該為age

截取字符串”20 | http://www.baidu.com”中,”|”字符前面和后面的數據,分別輸出它們。

   NSString * str = @"20 | http://www.baidu.com";
NSArray *array = [str componentsSeparatedByString:@"|"]; //這是分別輸出的截取后的字符串
for (int i = 0; i<[array count]; ++i) { NSLog(@"%d=%@",i,[array objectAtIndex:i]);
}

寫一個完整的代理,包括聲明,實現

//創建
@protocol MyDelagate
@required
-(void)eat:(NSString *)foodName;
@optional
-(void)run;
@end

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

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

isKindOfClass、isMemberOfClass、selector作用分別是什么

  • isKindOfClass,作用是,某個對象屬于某個類型或者繼承自某類型

  • isMemberOfClass:某個對象確切屬于某個類型

  • selector:通過方法名,獲取在內存中的函數的入口地址

請分別寫出SEL、id、@的意思?

  • SEL是“selector”的一個類型,表示一個方法的名字-------就是一個方法的入口地址

  • id是一個指向任何一個繼承了Object(或者NSObject)類的對象。需要注意的是id是一個指針,所以在使用id 的時候不需要加*。

  • @:OC中的指令符

unsigned int 和int 有什么區別。假設int長度為65535,請寫出unsigned int與 int的取值范圍

int:基本整型,當字節數為2時 取值范圍為-32768~32767,當字節數為4時 取值范圍
負的2的31次方 到 2的31次方減1
unsigned int:無符號基本整型,當字節數為2時 取值范圍為0~65535,當字節數為4時 取值范圍為0到2的32次方減1

Foundation對象與Core Foundation對象有什么區別

  • Foundation對象是OC的,Core Foundation對象是C對象
  • 數據類型之間的轉換
    • ARC:__bridge_retained(持有對象所有權,F->CF)、__bridge_transfer(釋放對象有所權CF->F)
    • 非ARC: __bridge

編寫一個函數,實現遞歸刪除指定路徑下的所有文件。

+ (void)deleteFiles:(NSString *)path;{
    // 1.判斷文件還是目錄
    NSFileManager * fileManger = [NSFileManager defaultManager];
    BOOL isDir = NO;
    BOOL isExist = [fileManger fileExistsAtPath:path isDirectory:&isDir];
    if (isExist) {
        // 2. 判斷是不是目錄
        if (isDir) {
        NSArray * dirArray = [fileManger contentsOfDirectoryAtPath:path error:nil];
            NSString * subPath = nil;
            for (NSString * str in dirArray) {
                subPath  = [path stringByAppendingPathComponent:str];
                BOOL issubDir = NO;
                 [fileManger fileExistsAtPath:subPath isDirectory:&issubDir];
                [self deleteFiles:subPath];
            }
            
           
        }else{
            NSLog(@"%@",path);
            [manager removeItemAtPath:filePath error:nil];  
        }
    }else{
        NSLog(@"你打印的是目錄或者不存在");
    }
}

文章如有問題,請留言,我將及時更正。

滿地打滾賣萌求贊,如果本文幫助到你,輕點下方的紅心,給作者君增加更新的動力。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,702評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,143評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,553評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,620評論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,416評論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 54,940評論 1 321
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,024評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,170評論 0 287
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,709評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,597評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,784評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,291評論 5 357
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,029評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,407評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,663評論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,403評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,746評論 2 370

推薦閱讀更多精彩內容

  • 轉至元數據結尾創建: 董瀟偉,最新修改于: 十二月 23, 2016 轉至元數據起始第一章:isa和Class一....
    40c0490e5268閱讀 1,745評論 0 9
  • 我們常常會聽說 Objective-C 是一門動態語言,那么這個「動態」表現在哪呢?我想最主要的表現就是 Obje...
    Ethan_Struggle閱讀 2,222評論 0 7
  • 轉載:http://yulingtianxia.com/blog/2014/11/05/objective-c-r...
    F麥子閱讀 753評論 0 2
  • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法,內部類的語法,繼承相關的語法,異常的語法,線程的語...
    子非魚_t_閱讀 31,707評論 18 399
  • 文/雨竹 又是一年的深秋,秋季本蕭瑟,但于我來說卻是最歡喜的日子,只因我的生日就在這深秋季節,在這個特別的日子,我...
    遼寧_雨竹閱讀 324評論 0 4