iOS 面試題 1

一、    簡述OC中內存管理機制。與retain配對使用的方法是dealloc仍是release,爲何?須要與alloc配對使用的方法是dealloc仍是release,爲何?readwrite,readonly,assign,retain,copy,nonatomic 、atomic、strong、weak屬性的做用?
OC使用了一種叫作引用計數的機制來管理對象,若是對一個對象使用了alloc、[Mutable]copy,retain,那麼你必須使用相應的realease或者autorelease。也能夠理解爲本身生成的對象,本身持有。非本身生成的對象,本身也能持有。不在須要本身持有的對象時釋放。非本身持有的對象沒法釋放。生成並持有對象<alloc,new,copy,mutableCopy等>,持有對象<retain>,釋放對象<release>,廢棄對象<dealloc>。html

readwrite(默認):可讀可寫,表示既有getter方法,也有setter方法。ios

readonly:表示只有getter方法,沒有setter方法。程序員

nonatomic:不考慮線程安全。編程

atomic(默認):線程操做安全。數組

strong(默認):ARC下和MRC下retain同樣,安全

weak(ARC下):和(MRC下)assign相似,區別是當weak指向的內存釋放掉後自動置爲nil,防止野指針。數據結構

unsafe_unretained聲明一個若引用,但不會自動置爲nil,可能會出現野指針。多線程

線程安全下的setter和getter方法:併發

-      (NSString *)value{app

@synchronized(self){

return [[_value retain] autorelease];

}

}

-      (void)setValue:(NSString *)aValue{

@synchronized(self){

[aValue retain];

[_value release];

_value = aValue;

}

}

二、    類變量的@protected ,@private,@public,@package,聲明各有什麼含義?
上面的幾個聲明代表的時類成員的做用域,@private做用範圍只能在自身類(外界既不可訪問,又不能繼承);@protected做用範圍在自身類和子類,若是什麼都不加修飾,默認是@protected(外界不可訪問,可是能夠繼承);@public做用範圍最大,能夠在任何地方被訪問(外界便可訪問,又能夠繼承);@package做用範圍在某個框架內

三、    線程是什麼?進程是什麼?兩者有什麼區別和聯繫?
線程是CPU獨立運行和獨立調度的基本單位(能夠理解爲一個進程中執行的代碼片斷),進程是資源分配的基本單位(進程是一塊包含了某些資源的內存區域)。進程是線程的容器,真正完成代碼執行的是線程,而進程則做爲線程的執行環境。一個程序至少包含一個進程,一個進程至少包含一個線程,一個進程中的多個線程共享當前進程所擁有的資源。

四、    談談你對多線程開發的理解?ios中有幾種實現多線程的方法?
好處:
一、使用線程能夠把程序中佔據時間長的任務放到後臺去處理,如圖片、視頻的下載
二、發揮多核處理器的優點,併發執行讓系統運行的更快、更流暢,用戶體驗更好
缺點:
一、大量的線程下降代碼的可讀性,
二、更多的線程須要更多的內存空間
三、當多個線程對同一個資源出現爭奪的時候要注意線程安全的問題。
iOS有三種多線程編程的技術:
一、NSThread(兩種建立方式)
[NSThread detachNewThreadSelector:@selector(doSomething:) toTarget:self withObject:nil];
NSThread *myThread = [[NSThread alloc] initWithTarget:self selector:@selector(doSomething:) object:nil];

[myThread start];
二、NSOperationQueue

NSOperationQueue *oprationQueue = [[NSOperationQueue alloc] init];

  • oprationQueue addOperationWithBlock:^{

//這個block語句塊在子線程中執行

}

http://alloc.sinaapp.com/wp/?p=237

三、Grand Central Dispatch (GCD)

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

    // 耗時的操做

    dispatch_async(dispatch_get_main_queue(), ^{

        // 更新界面

    });

});

http://blog.csdn.net/totogo2010/article/details/8016129

 

PS:不顯示的建立線程的方法:
用NSObject的類方法  performSelectorInBackground:withObject: 建立一個線程:
[Obj performSelectorInBackground:@selector(doSomething) withObject:nil];

五、    線程同步和異步的區別?IOS中如何實現多線程的同步?
同步:一個線程要等待上一個線程執行完以後才能執行當前的線程,生活中的例子(上廁所)。
異步:同時去作兩件或者多件事。好比邊聽歌邊看報。
原子操做(atomic)、加鎖(NSLock、NSRecursive、NSConditionLock)、@synchronized    參考(http://blog.csdn.net/lifengzhong/article/details/7487505)

六、    假設有一個字符串aabcad,請寫一段程序,去掉字符串中不相鄰的重複字符串,即上述字符串處理以後的輸出結果爲:aabcd

本題的題意是以第一個出現的字母做爲參照,只要以後出現相同的字母而且和第一個字母不相鄰,那麼就刪除。爲防止刪除某些字符以後,把以前不相鄰的重複字符串轉化爲相鄰字符串,因此能夠先用空格替換掉須要刪除的字符,最後對數組裏面的空格進行處理。
-(void)removeRepeat:(NSString *)aNum

{

    NSMutableArray *mArr = [[NSMutableArray alloc]initWithCapacity:10];

    for (int i = 0;i < aNum.length;i++)

    {

        [mArr addObject:[aNum substringWithRange:NSMakeRange(i,1)]];

    }

    NSLog(@"- %@", mArr);

    [self compareNum:mArr];

    NSLog(@"%@",mArr);

   

}

//比較是否相等

-(NSMutableArray *)compareNum:(NSMutableArray *)mArr

{

    int count = mArr.count;//從新定義了,count不會減一

    for (int j = 0; j < count - 1; j++)

    {

        for (int i = j; i < count - 1-1-1; i++)

        {

            NSLog(@" %@  %@",[mArr objectAtIndex:j],[mArr objectAtIndex:i + 2]);

            NSString *a = [mArr objectAtIndex:j];

            NSString *b = [mArr objectAtIndex:i+2];

           

            if ([a isEqualToString:b])

            {

                [mArr replaceObjectAtIndex:i + 2 withObject:@" "];

            }

        }

    }

   

    return mArr;

}

 

七、    獲取一臺設備惟一標識的方法有哪些?
MAC地址,udid,keychain

參考連接< http://www.2cto.com/kf/201308/237648.html >。

八、    iOS類是否能夠多繼承?若是沒有,那能夠用其餘方法實現嗎?簡述實現過程。
不能夠,能夠經過delegate和protocol來實現相似多繼承。

九、    堆和棧的區別?

堆棧是一種先進後出的數據結構,是一種只容許在其一端進行插入或刪除的線性表。

棧是由系統自動分配,速度較快;能從棧得到的空間較小;

堆須要程序員本身申請,並指明大小;堆得到的空間比較靈活,也比較大。


棧區(stack)--由編譯器自動分配釋放,存放函數的參數值、局部變量的值。
堆區(heap)--通常由程序員分配釋放。
全局區(靜態區)(static)--全局變量和靜態變量。程序結束後由系統釋放。

文字常量區--常量字符串存放在這裏。程序結束後由系統釋放。

程序代碼區—存放函數體的二進制文件。

棧:只要棧的剩餘空間大於所申請空間,系統將爲程序提供內存,不然將報異常提示棧溢 出。

堆:首先應該知道操做系統有一個記錄空閒內存地址的鏈表,當系統收到程序的申請時,會遍歷該鏈表,尋找第一個空間大於所申請空間的堆結點,而後將該結點從空閒結點鏈表中刪除,並將該結點的空間分配給程序,另外,對於大多數系統,會在這塊內存空間中的首地址處記錄本次分配的大小,這樣,代碼中的delete語句才能正確的釋放本內存空間。另外,因爲找到的堆結點的大小不必定正好等於申請的大小,系統會自動的將多餘的那部分從新放入空閒鏈表中。

十、  iOS本地數據存儲都有哪幾種方式?iOS如何實現複雜對象的存儲?

一、     NSKeyedArchiver(歸檔)採用歸檔的形式來保存數據,該數據對象須要遵照NSCoding協議,而且該對象對應的類必須提供encodeWithCoder:和initWithCoder:方法。

二、     NSUserDefaults:用來保存應用程序設置和屬性、用戶保存的數據。用戶再次打開程序或開機後這些數據仍然存在。NSUserDefaults能夠存儲的數據類型包括:NSData、NSString、NSNumber、NSDate、NSArray、NSDictionary。

三、     Write寫入方式:永久保存在磁盤中。

四、     SQLite(FMDB、CoreData)

NSCoding + NSKeyedArchiver實現複雜對象的存儲。

十一、  iOS的動態性
iOS的動態性來自三個方面:動態類型、動態綁定、動態載入、SEL類型

一、動態類型<弱類型>(id):在代碼的運行階段判斷代碼的類型,使用id類型可讓應用在「運行時」使用任何類型來替換。動態類型讓程序更加靈活,可是會使數據的統一性下降和代碼的可讀性。咱們經常使用靜態類型<強類型>(如NSString),使用靜態類型編譯器能夠徹底分析你的代碼,這讓代碼的性能和可預知性更高。
二、動態綁定:讓代碼在運行時判斷須要調用什麼方法,而不是在編譯時。 動態類型和動態綁定使得選擇哪一個接收者已經調用什麼方法都放到運行
      時去完成。    

三、動態載入:應用程序能夠根據須要加載可執行代碼以及資源,而不是在啓動時就加載全部資源。

四、SEL類型 iOS在編譯的時候會根據方法的名字(包括參數序列),生成一個用來區分這個方法的惟一的ID,這個ID是SEL類型的,SEL的本質就是類方法的編號[函數地址]。(相似C語言裏面的函數指針,可是OC的類不能直接使用函數指針,這樣只能作一個@selector語法來取。注意:@selector是查找當前類(含子類)的方法。)

12.寫出方法獲取ios內存使用狀況。

// 獲取當前設備可用內存及所佔內存的頭文件

#import <sys/sysctl.h>

#import <mach/mach.h>

 

// 獲取當前設備可用內存(單位:MB)

- (double)availableMemory

{

  vm_statistics_data_t vmStats;

  mach_msg_type_number_t infoCount = HOST_VM_INFO_COUNT;

  kern_return_t kernReturn = host_statistics(mach_host_self(), 

                                             HOST_VM_INFO, 

                                             (host_info_t)&vmStats, 

                                             &infoCount);

  

  if (kernReturn != KERN_SUCCESS) {

    return NSNotFound;

  }

  

  return ((vm_page_size *vmStats.free_count) / 1024.0) / 1024.0;

}

 

// 獲取當前任務所佔用的內存(單位:MB)

- (double)usedMemory

{

  task_basic_info_data_t taskInfo;

  mach_msg_type_number_t infoCount = TASK_BASIC_INFO_COUNT;

  kern_return_t kernReturn = task_info(mach_task_self(), 

                                       TASK_BASIC_INFO, 

                                       (task_info_t)&taskInfo, 

                                       &infoCount);

 

  if (kernReturn != KERN_SUCCESS

      ) {

    return NSNotFound;

  }

  

  return taskInfo.resident_size / 1024.0 / 1024.0;}

1三、         深拷貝和淺拷貝的理解?
深拷貝拷貝的是內容,淺拷貝拷貝的是指針。深拷貝和淺拷貝最大的區別就是子類對象的地址是否改變,若是子類對象的地址改變那麼就是深拷貝。

1四、怎樣實現一個singleton的類。
static LOSingleton * shareInstance;

+( LOSingleton *)sharedInstance{

    @synchronized(self){//這個東西其實就是 一個加鎖。若是self 其餘線程訪問,則會阻塞。這樣作通常是用來對單例 進行一個死鎖的保護

        if (shareInstance == nil) {

            shareInstance = [[super allocWithZone:NULL] init];

        }

    }

return shareInstance;

}

//第二種方式

+ (LOSingleton *) sharedInstance

{

    static  LOSingleton *sharedInstance = nil ;

    static  dispatch_once_t onceToken;  // 鎖

    dispatch_once (& onceToken, ^ {     // 最多調用一次

        sharedInstance = [[self  alloc] init];

    });

    return  sharedInstance;

}

1五、什麼是安全釋放?

在對象release以後把指針置爲nil

1六、         RunLoop是什麼?
一個RunLoop就是一個時間處理的循環,用來不停的調度工做以及處理輸入時間。使用runloop的目的是讓你的線程在有工做的時候忙於工做,而沒工做的時候處於休眠狀態。runloop的設計是爲了減小cpu無謂的空轉。

1七、         什麼是序列化和反序列化,能夠用來作什麼?如何在OC中實現複雜對象的存儲?
若是你須要存儲一個複雜的對象的話,常常要以二進制的方法序列化這個對象,這個過程叫Archiving。若是一個對象須要進行序列化,那麼須要遵循NScoding協議,主要有兩個方法:
-(id)initWithCoder:(NSCoder*)coder;//從coder中讀取數據,保存到相應變量中,即反序列化數據。
-(void)encodeWithCoder:(NSCoder*)coder;//讀取實例變量,並把這些數據寫到coder中去,即序列化數據。

1八、         寫一個標準宏MIN,這個宏輸入兩個參數並返回較小的一個?
#define kMIN(X,Y)  ((X)  > (Y)) ? (Y) :(X)

1九、         iphone os有沒有垃圾回收機制?簡單闡述一下OC內存管理。
iphone os沒有垃圾回收機制。
垃圾回收機制用於在空閒時間以不定時的方式動態的回收無任何引用的對象佔據的內存空間。

20、         簡述應用程序按Home鍵進入後臺時的生命週期,以及從後臺回到前臺時的生命週期?
應用程序的狀態:
Not running 未運行,程序沒啓動
Inactive    未激活,程序在前臺運行,不過沒接受到事件,沒有事件處理的狀態下一般處於這個狀態。
Active      激活   程序在前臺而且接收到了時間
Backgound  後臺   程序在後臺並且能執行代碼,大多數程序進入這個狀態後會在在這個狀態上停留一會。
Suspended   掛起  程序在後臺不能執行代碼。
- (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
       //當程序從後臺將要從新回到前臺時候調用,這個恰好跟上面的那個方法相反。


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

2一、 ViewController 的 alloc,loadView, viewDidLoad,viewWillAppear,viewDidUnload,dealloc、init分別是在何時調用的?在自定義ViewController的時候這幾個函數裏面應該作什麼工做?

alloc初始化當前的ViewController

loadView:沒有正在使用nib視圖頁面,子類將會建立本身的自定義視圖層

viewDidLoad:試圖被加載後調用

viewWillAppear:試圖即將出現的時候調用

viewDidUnload:<iOS6以後廢棄>當系統內存吃緊的時候會調用該方法,釋放掉當前未在window中顯示的試圖和對應的控制器

相關文章
相關標籤/搜索