iOS面試 | 基礎知識 | <1>

1.簡述OC中內存管理機制
  • 答:內存管理機制:使用引用計數管理,分為ARC和MRC,MRC需要程序員自己管理內存,ARC則不需要.但是并不是 所有對象在ARC環境下均不需要管理內存,子線程和循環引用并不是這樣.與retain配對使用的是release,retain代表引用計 數+1,release代表引用計數-1,當引用計數減為0時,對象則被系統自動銷毀.與alloc配對使用的是dealloc,alloc代表為對象開 辟內存空間,dealloc則代表銷毀對象的內存空間.
2.readwrite,readonly,assign,retain,copy,nonatomic,atomic,strong,weak的作用?
  • 答:讀寫屬性:readonly和readwrite; 語義屬性:assign/retain/copy; 原子性:nonatomic.
    • ① readwrite代表可讀,可寫,即有setter和getter方法,是默認屬性.readonly代表只可讀,即只有get方法,因為不會生成setter方法,所以它不可以和copy/retain/assign組合使用.

    • ② weak和assign均是弱引用,assign修飾基本數據類型,weak修飾對象類型.strong和weak用于ARC下(ARC下的代理使用 weak,block塊使用copy).strong相當于retain.weak相當于assign;assign/retain/copy這些屬性用 于指定set訪問器的語義,也就是說,這些屬性決定了以何種方式對數據成員賦值.
      assign,直接賦值,引用計數不改變,適用于基本數據類型.
      retain,淺拷貝,使用的是原來的內存空間,只能適用于Objective-C對象類型,而不能適用于Core Foundation對象(retain會增加對象的引用計數,而基本數據和Core Foundation對象都沒有引用計數).
      copy:對象的拷貝,新申請一塊內存空間,并把原始內容復制到那片空間.新對象的引用計數為1,此屬性只對那些遵循了NSCopy協議的對象類型有效.

    • ③nonatomic,非原子性訪問,不加同步,是異步操作.默認為atomic,原子操作,atomic是Objc使用的一種線程保護技術,基本上來 講,是防止在寫未完成的時候被另外一個線程讀取,造成數據錯誤,而這種機制是消耗系統內存資源的,所以在移動端,都選擇nonatomic.

    • 另: 內存分為5個區,分別是棧區,堆區,全局區,文字常量區,程序代碼區.

      • 棧區:由編譯器自動分配釋放,不需要管理內存.
      • 堆區:一般有程序員分配釋放.
      • 全局區:存放全局變量和靜態變量.
      • 文字常量區:存放常量字符串.
      • 程序代碼區:存放二進制代碼.
3.類變量的@protected,@private,@public,@package,聲明各有什么含義?
  • @protected 受保護的.本類,子類可見.
  • @private 私有的,類內可用
  • @public 公有的,類內,子類,外部均可用
  • @package 可見度在@protected和@public之間,這個類型最常用于框架類的實例變量.
4.線程是什么?進程又是什么?區別和聯系.
  • 進程:正在運行的程序,負責程序的內存分配.
  • 線程:線程是進程中一個獨立執行的控制單元(路徑),一個進程至少包含一條線程,即主線程.
    創建線程的目的:開辟一條新的執行路徑,運行指定的代碼,與主線程的代碼實現同時執行.
5.對多線程開發的理解,iOS中有幾種實現多線程的方式.
  • 多線程的使用場景:防止卡頓,可以同時完成多個任務,且不影響主線程,把耗時操作放在子線程中執行,但是會消耗內存.
  • 實現多線程的方式
    • ①NSThread(內存需要自己管理.觸發)
    • ②NSOperationQueue(不再關注線程,當前可執行任務個數queue.maxConcurrentOperationCount)
    • ③GCD
      詳解三種實現多線程的方式:
      GCD:
      GCD里面包含了串行隊列、并行隊列、主隊列、全局隊列。
dispatch_queue_t q = dispatch_queue_create(“qqq”,DISPATCH_QUEUE_SERIAL);//創建一個串行隊列
dispatch_sync(q,^{
 
});//開啟同步任務
dispatch_async(q,^{
});//開啟異步任務
并行隊列:DISPATCH_QUEUE_CONCURRENT
主隊列:dispatch_queue_t q = dispatch_get_main_queue();
全局隊列:dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);

NSThread
獲取當前線程:NSThread * current = [NSThread currentThread];
獲取主線程:NSThread * main = [NSThread mainThread];
使用NSThread創建線程的兩種方式:

- (id)initWithTarget:(id)target selector:(SEL)selector object:(id)argument;
+ (void)detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)argument; 

暫停當前線程:
[NSThread sleepForTimeInterval:2];
NSOperationQueue
創建一個操作隊列:NSOperationQueue * queue = [[NSOperationQueue alloc]init];
添加NSOperation到NSOperationQueue中:[queue addOperation:operation];
添加一組operation:[queue addOperations:operations waitUntilFinished:NO];
添加一個block形式的operation:[queue addOperationWithBlock:^(){
}];
添加NSOperation的依賴對象:[operation2 addDependency:operation1];
設置隊列的最大操作數:[queue setMaxConcurrentOperationCount:1];
等待options完成:[operation waitUntilFinished];
暫停、繼續queue:[queue setSuspended:YES] [queue setSuspend:NO]

6.線程同步和異步的區別?ios中如何實現線程的同步?
  • 同步:任務順序執行,下一個任務依賴于上一任務的完成.
  • 異步:任務執行順序不定,一起執行.
  • 實現:設置依賴:NSOpreationQueue GCD中的串行隊列.
7.iOS類是否可以多繼承,如果沒有,怎么實現?
  • 不可以多繼承.
  • 可以通過類目,延展,協議實現多繼承.
    • 類目:類目也叫分類,英文category,在沒有原類.m文件的基礎上,給該類添加方法.類目里不能添加實例變量,不 能添加和原始類方法名相同的方法,否則會發生覆蓋.一個類可以添加多個類目,類目中的方法可以成為原始類的一部分,和原始類方法級別相同,可以被子類繼 承.
    • 延展:Extension,是一種特殊形式的類目,主要是在一個類的.m里面聲明與實現.作用:就是給某類添加私有方法或者私有變量.
      雖然延展是給一個類定義私有方法,但是OC沒有絕對的私有方法,其實還是可以調用的,延展里面聲明的變量只能在該類內部 使用,外界訪問不了.如果是新建文件建的的某類延展.h文件,則不能添加實例變量,如果括號里沒有類目名,則認為延展里面的方法為全都必須實現,如果有, 則可選實現.
      類目寫的方法必須實現,延展寫的方法非必須.
8.棧和堆的區別?
  • 棧:內存系統管理(系統開辟,系統釋放),先進后出.
  • 堆:內存自己管理(自己開辟,自己釋放).先進先出.
9.iOS本地數據存儲都有幾種方式?
  • ①.NSkeyedArchiver:采用歸檔的形式來保存數據,該數據對象需要遵守NSCoding協議,并且該對象 對應的類必須提供encodeWithCoder:和initWithCoder:方法.前一個方法告訴系統怎么對對象進行編碼,而后一個方法則是告訴系 統怎么對對象進行解碼.
  • ②.NSUserDefaults:用來保存應用程序設置和屬性,用戶保存的數據.用戶再次打開程序或者開機后這些數據 仍然存在.NSUserDefaults可以存儲的數據類型包 括:NSData,NSString,NSNumber,NSDate,NSArray.NSDictionary,其他類型的數據需要先行轉換.
  • ③.Write寫入方式:永久保存在磁盤中.具體:a.獲得文件保存的路徑.b.生成該路徑下的文件,c,往文件中寫入數據.d.從文件中讀出數據.
  • ④.SQLite:采用SQLite數據庫來存儲數據,SQLite作為一種輕量級數據庫.具體:a.添加SQLite 相關的庫以及頭文件,b.使用數據庫存數數據:打開數據庫,編寫數據庫語句,執行,關閉數據庫.另:寫入數據庫,字符串可以采用char方式,而從數據庫 中取出char類型,當char類型有表示中文字符時,會出現亂碼,這是因為數據庫默認使用ascII編碼方式,所以想要正確從數據庫中取出中文,需要使 用NSString來接受從數據庫取出的字符串.
  • ⑤.CoreData:原理是對SQLite的封裝,開發者不需要接觸sql語句,就可以對數據庫進行操作.
10.ios動態類型和動態綁定
  • 多態:父類指針指向子類對象.
    動態類型:只有在運行期,才能確定其真正類型.
    動態加載:根據不同的條件,加載不同的資源.32和64位.
11.深拷貝和淺拷貝的理解.
  • 深拷貝;拷貝的內容.
  • 淺拷貝:拷貝的指針.
    深拷貝如:
NSMutableDictionary  * dic = [@{} mutableCopy];
NSMutableArray  * ary = [@[] mutableCopy];
12.怎么實現一個singleton的類.
  • 單例是一種設計模式,對象只有一個.缺點:對象不會被釋放,如果創建很多的話會占用很多內存,優點:可以當做工具類使用.
static SortDetailsModelDown * single = nil;
+(SortDetailsModelDown *)shareSortDetailsModelDown { 
    @synchronized(self){
         if (!single) { 
              single = [[SortDetailsModelDown alloc]init];            } 
} return single;
}

13.什么是安全釋放?

先釋放再置空.

14.RunLoop是什么?

事件循環,是線程里面的一個組件.主線程的RunLoop是自動開啟的.分為:計時源(timer source),事件源(輸入源):input source.防止CPU中斷(保證程序執行的線程不會被系統終止).

Runloop提供了一種異步執行代碼的機制,并不能并行執行任務,是事件接收和分發機制的一個實現.每一個線程都有其對應的RunLoop,但是默認非主線程的RunLoop是沒有運行的,需要為RunLoop添加至少一個事件源,然后run它.

一般情況下我們是沒有必要去啟動線程的RunLoop的,除非你在一個單獨的線程中需要長時間的檢測某個事件.

RunLoop,正如其名所示,是線程進入和被線程用來響應事件以及調用事件處理函數的地方.

input source傳遞異步事件,通常是來自其他線程和不同程序的消息.

timer source傳遞同步事件.

當有事件發生時,RunLoop會根據具體的事件類型通知應用程序作出響應.

當沒有事件發生時,RunLoop會進入休眠狀態,從而到達省電的目的.

當事件再次發生時,RunLoop會被重新喚醒,處理事件.

一般在開發中很少會主動創建RunLoop,而通常會把事件添加到RunLoop中.

15.什么是序列化和反序列化,可以用來做什么?如何在OC中實現復雜對象的存儲.

序列化和反序列化:歸檔和反歸檔,進行本地化,進行數據存儲.

CoreData:數據托管.有四種存儲方式:xml,sqlite,二進制,內存.

遵循NSCoding協議之后,進行歸檔即可實現復雜對象的存儲.

16.寫一個標準宏MIN,這個宏輸入兩個參數并返回較小的一個.

define MIN(A,B) (A)>(B)?(B):(A)

17.iPhone OS 有沒有垃圾回收機制,簡易闡述一下OC內存管理.

木有.引用計數,ARC和MRC,swift(自動引用計數).

18.簡述應用程序按HOME鍵進入后臺時的生命周期,以及從后臺進入前臺時的生命周期.
//前者:HOME->后臺
- (void)applicationWillResignActive:(UIApplication *)application
- (void)applicationDidEnterBackground:(UIApplication *)application
//后者:后臺->前臺
- (void)applicationWillEnterForeground:(UIApplication *)application     
- (void)applicationDidBecomeActive:(UIApplication *)application

//另:各個程序運行狀態時代理的回調

//告訴代理進程啟動但還沒進入狀態保存
- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions

//告訴代理啟動基本完成程序準備開始運行
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

//當應用程序將要入非活動狀態執行,在此期間,應用程序不接收消息或事件,比如來電話了
- (void)applicationWillResignActive:(UIApplication *)application

//當應用程序入活動狀態執行,這個剛好跟上面那個方法相反
- (void)applicationDidBecomeActive:(UIApplication *)application

//當程序被推送到后臺的時候調用。所以要設置后臺繼續運行,則在這個函數里面設置即可
- (void)applicationDidEnterBackground:(UIApplication *)application

//當程序從后臺將要重新回到前臺時候調用,這個剛好跟上面的那個方法相反。
- (void)applicationWillEnterForeground:(UIApplication *)application

//當程序將要退出是被調用,通常是用來保存數據和一些退出前的清理工作。這個需要要設置UIApplicationExitsOnSuspend的鍵值。
- (void)applicationWillTerminate:(UIApplication *)application

//當程序載入后執行
- (void)applicationDidFinishLaunching:(UIApplication*)application

在上面8個方法對應的方法中鍵入NSLog打印。
現在啟動程序看看執行的順序:

  • 啟動程序
Log[40428:11303] willFinishLaunchingWithOptions
Log[40428:11303] didFinishLaunchingWithOptions
Log[40428:11303] applicationDidBecomeActive
  • 按下home鍵
Log[40428:11303] applicationWillResignActive
Log[40428:11303] applicationDidEnterBackground
  • 雙擊home鍵,再打開程序
Log[40428:11303] applicationWillEnterForeground
Log[40428:11303] applicationDidBecomeActive
19.ViewController的 alloc,loadView,viewDidLoad,viewWillAppear,viewDidUnload,dealloc,init分別是在 什么時候調用?在自定義ViewController的時候這幾個函數里面應該做什么工作?
  • alloc:申請內存時調用.
  • loadView:加載視圖時調用.
  • viewDidLoad;視圖已經加載后調用.
  • viewWillAppear:視圖將要出現時調用.
  • viewDidUnload:視圖已經加載但是沒有加載出來時調用.
  • dealloc:銷毀該視圖時調用.
  • init;初始化該視圖時調用.
20.描述應用程序的啟動順序.
  • a.程序入口main函數創建UIApplication實例和UIApplication代理實例.
  • b.在UIApplication代理實例中重寫啟動方法,設置根ViewController
  • c.在第一ViewController中添加控件,實現應用程序界面.
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • ? 深拷貝同淺拷貝的區別:淺拷貝是指針拷貝,對一個對象進行淺拷貝,相當于對指向對象的指針進行復制,產生一個新的指向...
    WSGNSLog閱讀 1,285評論 0 1
  • 1. 父類實現深拷貝時,子類如何實現深度拷貝。父類沒有實現深拷貝時,子類如何實現深度拷貝。 1.1 深拷貝同淺拷貝...
    iYeso閱讀 1,907評論 0 13
  • 父類實現深拷貝時,子類如何實現深度拷貝。父類沒有實現深拷貝時,子類如何實現深度拷貝。? 深拷貝同淺拷貝的區別:淺拷...
    JonesCxy閱讀 1,052評論 1 7
  • *面試心聲:其實這些題本人都沒怎么背,但是在上海 兩周半 面了大約10家 收到差不多3個offer,總結起來就是把...
    Dove_iOS閱讀 27,211評論 30 472
  • 我發現了一個秘密 我自認為最好的朋友她所認為的最好的朋友不是我 轉學以后,我還以為友誼真能天長地久 到頭來,只是我...
    非故意傷人罪閱讀 1,076評論 0 0