iOS面試題總結(jié)

1.說下線程和進(jìn)程的區(qū)別
答:(1)一個(gè)線程只能屬于一個(gè)進(jìn)程,而一個(gè)進(jìn)程可以有多個(gè)線程,但至少有一個(gè)線程。線程是操作系統(tǒng)可識(shí)別的最小執(zhí)行和調(diào)度單位。

(2)資源分配給進(jìn)程,同一進(jìn)程的所有線程共享該進(jìn)程的所有資源。 同一進(jìn)程中的多個(gè)線程共享代碼段(代碼和常量),數(shù)據(jù)段(全局變量和靜態(tài)變量),擴(kuò)展段(堆存儲(chǔ))。但是每個(gè)線程擁有自己的棧段,棧段又叫運(yùn)行時(shí)段,用來存放所有局部變量和臨時(shí)變量。

(3)處理機(jī)分給線程,即真正在處理機(jī)上運(yùn)行的是線程。

(4)線程在執(zhí)行過程中,需要協(xié)作同步。不同進(jìn)程的線程間要利用消息通信的辦法實(shí)現(xiàn)同步。
2.如何保證線程安全

一塊資源可能會(huì)被多個(gè)線程共享,也就是多個(gè)線程可能會(huì)訪問同一塊資源,比如多個(gè)線程訪問同一個(gè)對(duì)象、同一個(gè)變量、同一個(gè)文件。當(dāng)多個(gè)線程訪問同一塊資源時(shí),很容易引發(fā)數(shù)據(jù)錯(cuò)亂和數(shù)據(jù)安全問題。此時(shí),我們需要用線程鎖來解決。

(1)nonatomic atomic:

使用atomic多線程原子性控制,atomic的原理給setter加上鎖, getter不會(huì)加鎖。OC在定義屬性時(shí)有nonatomic和atomic兩種選擇
atomic:原子屬性,為setter方法加鎖(默認(rèn)就是atomic)
nonatomic:非原子屬性,不會(huì)為setter方法加鎖

(2)使用GCD實(shí)現(xiàn)atomic操作:給某字段的setter和getter方法加上同步隊(duì)列:

- (void)setCount:(NSInteger)newcount{
    dispatch_sync(_synQueue, ^{ count = newcount; });
}
- (NSInteger)count
{
   __block NSInteger localCount;
   dispatch_sync(_synQueue, ^{
        localCount = count;
   });
   return localCount;
}

(3)使用NSLock

- (void)threadRunLock
 {
       _lock = [[NSLock alloc]init];
       while (true) 
       {
            [_lock lock];
            if (self.number > 0 ) 
           {
               [NSThread sleepForTimeInterval:0.5];
               self.number --;
               NSLog(@"thread:%@ ---> %ld",[[NSThread currentThread] name],self.number);
           }
           [_lock unlock];
       }
 }

相當(dāng)于給代碼片段加上lock了,所以依次輸出9-0
(4)使用互斥鎖
使用格式

@synchronized(鎖對(duì)象) { // 需要鎖定的代碼  }
注意:鎖定1份代碼只用1把鎖,用多把鎖是無效的
-(void)sellTickets
{
    while (true) 
    {
        @synchronized(self)
        {
            //只能加一把鎖
            //1.先檢查票數(shù)
            int count=self.leftTicketsCount;
            if (count>0) 
            {
                //暫停一段時(shí)間
                [NSThread sleepForTimeInterval:0.002];
                //2.票數(shù)-1
                self.leftTicketsCount= count-1;
                //獲取當(dāng)前線程
                NSThread *current=[NSThread currentThread];
                NSLog(@"%@--賣了一張票,還剩余%d張票",current,self.leftTicketsCount);
             }
             else
            {
               //退出線程
               [NSThread exit];
            }
        }
    }
 }

互斥鎖的優(yōu)缺點(diǎn):

優(yōu)點(diǎn):能有效防止因多線程搶奪資源造成的數(shù)據(jù)安全問題
缺點(diǎn):需要消耗大量的CPU資源

3、了解哪些設(shè)計(jì)模式

(1)代理模式
(2)觀察者模式
(3)MVC模式
(4)單例模式

4、堆和棧的區(qū)別,工程項(xiàng)目中的哪些數(shù)據(jù)是儲(chǔ)存在堆中、哪些在棧中

在引入堆和棧之前,先要知道,iOS中的內(nèi)存管理范圍:

oc對(duì)象需要進(jìn)行內(nèi)存管理,非oc對(duì)象不需要進(jìn)行內(nèi)存管理,比如基本數(shù)據(jù)類型

所以:

OC對(duì)象存放于堆里面(堆內(nèi)存要程序員手動(dòng)回收)
非OC對(duì)象一般放在棧里面(棧內(nèi)存會(huì)被系統(tǒng)自動(dòng)回收)
堆里面的內(nèi)存是動(dòng)態(tài)分配的,所以也就需要程序員手動(dòng)的去添加內(nèi)存、回收內(nèi)存

堆和棧的區(qū)別:

棧是吃了吐 LIFO(先進(jìn)后出)
堆是吃了拉 FIFO(先進(jìn)先出)

5、iOS中的NSCopying協(xié)議,copy,MutableCopy的區(qū)別

首先我們先說兩個(gè)兩個(gè)概念:

淺復(fù)制:不拷貝對(duì)象本身,僅僅是拷貝指向?qū)ο蟮闹羔?br> 深復(fù)制:是直接拷貝整個(gè)對(duì)象內(nèi)存到另一塊內(nèi)存中

然后我們?cè)賮砜碿opy關(guān)鍵字的特點(diǎn):

修改源對(duì)象的屬性和行為,不會(huì)影響副本對(duì)象
修改副本對(duì)象的屬性和行為,不會(huì)影響源對(duì)象
一個(gè)對(duì)象可以通過copy和mutableCopy方法來創(chuàng)建一個(gè)副本對(duì)象
copy:創(chuàng)建的是不可變副本(NSString,NSArray,NSDictionary)
mutableCopy:創(chuàng)建的是可變副本(NSMutableString,NSMutableArray,NSMutableDictionary)
6、解釋屬性修飾關(guān)鍵詞的作用(weak,strong,copy,readOnly,assgin,nonatomic等)
1.assgin
此標(biāo)記說明設(shè)置器直接進(jìn)行賦值,這也是默認(rèn)值且setter方法直接將傳入?yún)?shù)賦值給實(shí)例變量,不涉及引用計(jì)數(shù)的變化,也沒有引用技術(shù)可以供管理;
主要用于非指針變量(也可以修飾指針變量,但是平時(shí)都不這么用),即用于基礎(chǔ)數(shù)據(jù)類型(例如NSInteger)和C的數(shù)據(jù)類型(int, float, double, char)另外還有id類型的屬性,總而言之,前面不需要加"*"的就可以用assign修飾;
2.retian :
表示持有特性,一般用于指針對(duì)象,例如數(shù)組(NSMutableArray,NSArray),字典對(duì)象,視圖對(duì)象(UIView ),控制器對(duì)象(UIViewController)等,這些屬性需要保存引用計(jì)數(shù);
就是說你定義了一個(gè)變量,然后這個(gè)變量在程序的運(yùn)行過程中會(huì)被更改,并且影響到其他方法,當(dāng)用retain時(shí),會(huì)釋放舊的對(duì)象,將輸入對(duì)象的索引計(jì)數(shù)+1,然后將輸入對(duì)象的值賦予新對(duì)象。
3.copy :
其setter方法是進(jìn)行Copy操作,與retain處理流程基本一樣,先舊對(duì)象release,再Copy出新的對(duì)象,retainCount為1,這是為了減少對(duì)上下文的依賴而引入的機(jī)制,區(qū)別在于copy主要用于NSString;retain是指針拷貝,copy是內(nèi)容拷貝然后新的對(duì)象開辟新內(nèi)存,引用計(jì)數(shù)為1,原來對(duì)象計(jì)數(shù)不變
4.weak:
weak是弱引用,是由ARC引入的對(duì)象變量的屬性,相當(dāng)于assign,只有在你打開ARC時(shí)才會(huì)被要求使用(但是weak只能修飾對(duì)象即指針類型的屬性和id類型的屬性,所以在ARC中修飾基本數(shù)據(jù)類型的屬性還是要用assign);
weak比assign多了一個(gè)功能,就是對(duì)象消失后把指針置為nil,避免了野指針,不是null指針,是指向“垃圾”內(nèi)存(不可用的內(nèi)存)的指針;
5.strong:
strong是強(qiáng)引用,是ARC新引入的對(duì)象變量屬性,簡(jiǎn)單講strong等同retain,只有在你打開ARC時(shí)才會(huì)被要求使用;
但是對(duì)于strong來說,它會(huì)自己判斷是選擇retain還是copy,比較方便。
6.readonly:
此標(biāo)記說明屬性是只讀的,默認(rèn)的標(biāo)記是讀寫,如果你指定了只讀,在@implementation中只需要一個(gè)讀取器,如果你使用@synthesize關(guān)鍵字,也只有讀取器方法被解析,即只會(huì)生成getter方法,不會(huì)生成setter方法;
不希望屬性在類外改變時(shí)候使用。
7.readwrite:
此標(biāo)記說明屬性會(huì)被當(dāng)成讀寫的,這也是默認(rèn)屬性。設(shè)置器和讀取器都需要在@implementation中實(shí)現(xiàn)。如果使用@synthesize關(guān)鍵字,讀取器和設(shè)置器都會(huì)被解析,即會(huì)同時(shí)生成getter和setter方法;
8.nonatomic:
非原子性訪問,對(duì)屬性賦值的時(shí)候不加鎖,不加同步,多線程并發(fā)訪問會(huì)提高性能。如果不加此屬性,則默認(rèn)是兩個(gè)訪問方法都為原子型事務(wù)訪問;
非原子操作,會(huì)簡(jiǎn)單的操作屬性的值,這會(huì)加快屬性存取的速度,但沒辦法保證在多線程環(huán)境下不出錯(cuò)。
9.atomc:
原子操作,這是默認(rèn)的,在多線程環(huán)境下,本方法設(shè)定為原子操作提供了可靠的屬性存取方法,而不用擔(dān)心并發(fā)時(shí)會(huì)產(chǎn)生問題;
這也就是說,在多線程環(huán)境下,解析的訪問器提供一個(gè)對(duì)屬性的安全訪問,從獲取器得到的返回值或者通過設(shè)置器設(shè)置的值可以一次完成,即便是別的線程也正在對(duì)其進(jìn)行訪問。
7. Object-c的類可以多重繼承么?可以實(shí)現(xiàn)多個(gè)接口么?Category是什么?重寫一個(gè)類的方式用繼承好還是分類好?為什么?

答:Object-c的類不可以多重繼承;可以實(shí)現(xiàn)多個(gè)接口,通過實(shí)現(xiàn)多個(gè)接口可以完成C++的多重繼承;Category是類別,一般情況用分類好,用Category去重寫類的方法,僅對(duì)本Category有效,不會(huì)影響到其他類與原有類的關(guān)系。

8.#import 跟#include 又什么區(qū)別,@class呢, #import<> 跟 #import”"又什么區(qū)別?

答:#import是Objective-C導(dǎo)入頭文件的關(guān)鍵字,#include是C/C++導(dǎo)入頭文件的關(guān)鍵字,使用#import頭文件會(huì)自動(dòng)只導(dǎo)入一次,不會(huì)重復(fù)導(dǎo)入,相當(dāng)于#include和#pragma once;@class告訴編譯器某個(gè)類的聲明,當(dāng)執(zhí)行時(shí),才去查看類的實(shí)現(xiàn)文件,可以解決頭文件的相互包含;#import<>用來包含系統(tǒng)的頭文件,#import””用來包含用戶頭文件。

9.這段代碼有什么問題嗎:
答:@implementation Person
- (void)setAge:(int)newAge {
    self.age = newAge;
}
@end

正確寫法
{
    if(_age){
        [_age release];
    }
    _age = [newAge retain];
}

死循環(huán)(擴(kuò)展:知道如何正確寫setter和getter方法)

10. 屬性readwrite,readonly,assign,retain,copy,nonatomic 各是什么作用,在那種情況下用?
readwrite 是可讀可寫特性;需要生成getter方法和setter方法時(shí)
readonly 是只讀特性  只會(huì)生成getter方法 不會(huì)生成setter方法 ;不希望屬性在類外改變assign是賦值特性,setter方法將傳入?yún)?shù)賦值給實(shí)例變量;僅設(shè)置變量時(shí);retain表示持有特性,setter方法將傳入?yún)?shù)先保留,再賦值,傳入?yún)?shù)的retaincount會(huì)+1;copy表示拷貝特性,setter方法將傳入對(duì)象復(fù)制一份;需要完全一份新的變量時(shí)。nonatomic 非原子操作,決定編譯器生成的setter getter是否是原子操作,atomic表示多線程安全,一般使用nonatomic
11.截取字符串”20 | http://www.baidu.com”中,”|”字符前面和后面的數(shù)據(jù),分別輸出它們。
componentsSeparatedByString
NSString * str = @“20|http://www.baidu.com”;
for(NSString*s in [str componentsSeparatedByString]){
    NSLog(@“%@“,s);
}
12.指出下面代碼的問題- (void)willEndStepOne:(NSObject *)userInfo{ [NSThread detachNewThreadSelector:@selector(doSomeThing:) toTarget:self withObject:userInfo];}- (void)doSomeThing:(NSObject *)userInfo{ int max_loop_times = 999999; for (int i=0; i<max_loop_times; i++) { int randNum = rand(); NSString *tmpString = [NSString stringWithFormat:@"%d", randNum]; NSLog(@"%@", tmpString); }}
13.分析json、xml的區(qū)別?json、xml解析方式的底層是如何處理的?

http://www.open-open.com/bbs/view/1324367918671
http://hi.baidu.com/fevelen/item/a25253ab76f766756cd455b6

14.Objective-C如何對(duì)內(nèi)存管理的,說說你的看法和解決方法?

Objective-C的內(nèi)存管理主要有三種方式ARC(自動(dòng)內(nèi)存計(jì)數(shù))、手動(dòng)內(nèi)存計(jì)數(shù)、內(nèi)存池。

15.內(nèi)存管理的幾條原則時(shí)什么?按照默認(rèn)法則.那些關(guān)鍵字生成的對(duì)象

需要手動(dòng)釋放?在和property結(jié)合的時(shí)候怎樣有效的避免內(nèi)存泄露?
誰申請(qǐng),誰釋放
遵循Cocoa Touch的使用原則;
內(nèi)存管理主要要避免“過早釋放”和“內(nèi)存泄漏”,對(duì)于“過早釋放”需要注意@property設(shè)置特性時(shí),一定要用對(duì)特性關(guān)鍵字,對(duì)于“內(nèi)存泄漏”,一定要申請(qǐng)了要負(fù)責(zé)釋放,要細(xì)心。
關(guān)鍵字alloc 或new 生成的對(duì)象需要手動(dòng)釋放;
設(shè)置正確的property屬性,對(duì)于retain需要在合適的地方釋放,

16.What is lazy loading?

懶漢模式,只在用到的時(shí)候才去初始化。也可以理解成延時(shí)加載。我覺得最好也最簡(jiǎn)單的一個(gè)列子就是tableView中圖片的加載顯示了。一個(gè)延時(shí)載,避免內(nèi)存過高,一個(gè)異步加載,避免線程堵塞

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴(yán)謹(jǐn) 對(duì)...
    cosWriter閱讀 11,632評(píng)論 1 32
  • 把網(wǎng)上的一些結(jié)合自己面試時(shí)遇到的面試題總結(jié)了一下,以后有新的還會(huì)再加進(jìn)來。 1. OC 的理解與特性 OC 作為一...
    AlaricMurray閱讀 2,657評(píng)論 0 20
  • 1.Difference between shallow copy and deep copy?淺復(fù)制和深復(fù)制的區(qū)...
    小楓123閱讀 428評(píng)論 1 0
  • 1、#import跟 #include 有什么區(qū)別?@class有什么作用?#import<> 跟 #import...
    SuAdrenine閱讀 614評(píng)論 0 5
  • iOS 面試題總結(jié)(一) 101. 修改下面的代碼: typedef enum{ UserSex_Man,User...
    AlaricMurray閱讀 1,838評(píng)論 0 6

友情鏈接更多精彩內(nèi)容