IOS面試

hither發表於2017-12-13

(一) 1.簡述你對協議的理解:

a想做一件事卻因為一些原因不能做,於是讓b遵循a的一些約定,這樣b就可以幫助a做事了。協議中包括了遵循方b需要實現的一些方法,以及b能夠做的事情。

2.如何理解ARC自動引用計數機制:

ARC--自動引用計數 可以用來管理物件的使用以及瞭解物件的使用情況,當物件引用計數不為0時,物件不會被釋放,當物件引用計數為0時 dealloc函式被呼叫 物件將會被釋放。

3.如何理解retain/copy/assign/release/autorelease/dealloc關鍵字:

retain讓物件引用計數加1,release讓物件引用計數減1,當物件引用計數為0時會呼叫dealloc 將物件進行釋放。copy是你不想讓a和b共享一塊記憶體時候,讓a和b有各自的記憶體。在使用基本資料型別的時候需要使用assgin,assgin是直接賦值,會引起物件引用計數加1.

(1)assign:普通賦值,一般用於基本資料型別,防止迴圈引用。
(2)retain:保留計數,獲得使用者的所有權。
(3)copy:用來賦值物件,一般字串使用copy,Foundation中的不可變物件使用copy效果相當於retain,只是引用計數+1.
(4)nonatomic:非原子性訪問,不加同步,多執行緒併發訪問會提高效能。
複製程式碼

4.請簡述類別和繼承有什麼聯絡和區別 以及weak和assgin的區別:

類別和繼承 都會使用父類的中原有的方法和屬性,類別是對父類進行擴充套件,繼承是將父類中的屬性、方法等保留下來,根據自己的實際情況進行實現。 weak用於各種UI控制元件和代理,assgin用於基本資料型別。 ####繼承可以增加,修改,刪除方法,還可以增加屬性; ####category只能新增屬性;

strong:
@property (nonatomic, strong) NSString *string1;   
@property (nonatomic, strong) NSString *string2;
self.string1 = @"String 1";   
self.string2 = self.string1;   
self.string1 = nil;  
NSLog(@"String 2 = %@", self.string2);  
 結果是:String 2 = String 1由於string2是strong定義的屬性,所以引用計數+1,使得它們所指向的值都是@"String 1"
weak:
@property (nonatomic, strong) NSString *string1;   
@property (nonatomic, weak) NSString *string2; 
 self.string1 = @"String 1";   
self.string2 = self.string1;   
self.string1 = nil;  
NSLog(@"String 2 = %@", self.string2);  
結果是:String 2 = null
 分析一下,由於self.string1與self.string2指向同一地址,且string2沒有retain記憶體地址,而self.string1=nil釋放了記憶體,所以string1為nil。宣告為weak的指標,指標指向的地址一旦被釋放,這些指標都將被賦值為nil。這樣的好處能有效的防止野指標。
複製程式碼

5.請簡述你對strong和weak關鍵字的理解 以及_unsafe_unretained與weak的區別:

strong相當於retain 讓物件引用計數加1,防止物件在異常情況下被提前釋放,導致crash。weak 弱引用防止產生迴圈應用無法釋放物件和產生野指標。

strong叫做強引用,在ARC中使用strong告訴編譯器幫組我們自動插入retain,weak是普通賦值相當於手動管理記憶體的assign。 _unsafe_unretained與weak功能一致,區別在於當指向的物件銷燬後,weak會將變數重置為nil,防止呼叫野指標,產生EXC_BAD_ACCESS這類的錯誤。

6.如何實現ARC和MRC的混合程式設計:

在targets的build phases選項下Compile Sources下選擇要使用arc編譯的檔案:  在targets的build phases選項下Compile Sources下選擇要不使用arc編譯的檔案, 就會出報錯。方法如下,雙擊它 輸入 -fno-objc-arc 即可。  如果在ARC 工程中 加MRC   加 -fno-objc-arc    如果在MRC 工程中 加 ARC  加 -fobjc-arc

7.Objective-C是否支援多繼承:

不支援多繼承 因為訊息機制名字查詢發生在執行時而非編譯時,很難解決多個基類可能導致的二義性問題 。可以通過訊息轉發 協議 類別實現與多繼承相似的功能。

8.Objective-C中變數預設是私有的麼?方法預設是私有的麼?

變數預設是private,方法預設是public。

9.#import"".h 和@class+類名的區別:

#import"".h為匯入標頭檔案,@class+類名 為前向引用申明。 1.import會包含這個類的所有資訊,包括實體變數和方法,而@class只是告訴編譯器,其後面宣告的名稱是類的名稱,至於這些類是如何定義的,暫時不用考慮,後面會再告訴你。 2.在標頭檔案中, 一般只需要知道被引用的類的名稱就可以了。 不需要知道其內部的實體變數和方法,所以在標頭檔案中一般使用@class來宣告這個名稱是類的名稱。 而在實現類裡面,因為會用到這個引用類的內部的實體變數和方法,所以需要使用#import來包含這個被引用類的標頭檔案。 3.在編譯效率方面考慮,如果你有100個標頭檔案都#import了同一個標頭檔案,或者這些檔案是依次引用的,如A–>B, B–>C, C–>D這樣的引用關係。當最開始的那個標頭檔案有變化的話,後面所有引用它的類都需要重新編譯,如果你的類有很多的話,這將耗費大量的時間。而是用@class則不會。 4.如果有迴圈依賴關係,如:A–>B, B–>A這樣的相互依賴關係,如果使用#import來相互包含,那麼就會出現編譯錯誤,如果使用@class在兩個類的標頭檔案中相互宣告,則不會有編譯錯誤出現。 所以,一般來說,@class是放在interface中的,只是為了在interface中引用這個類,把這個類作為一個型別來用的。 在實現這個介面的實現類中,如果需要引用這個類的實體變數或者方法之類的,還是需要import在@class中宣告的類進來.

10.請簡述頁面傳值都有哪些實現方法:

Block、 委託協議、 通知、 單例、NSUserDefaults

11.請簡述深拷貝和淺拷貝的區別:

深拷貝會重新在堆上開闢一塊記憶體空間 是一個全新的物件 指標地址和原來不一樣 淺拷貝不會重新開闢一塊記憶體空間 指標和原來是一樣的。 深拷貝和淺拷貝的本質是地址相同,就是淺拷貝,地址不同就是深拷貝。  淺拷貝是拷貝操作後,並沒有進行真正的複製,而是另一個指標也指向了同一個地址。深拷貝操作後,是真正的複製了一份,另一個指標指向了拷貝後的地址。 ######淺拷貝:在複製操作時,對於被複制的物件的每一層複製都是指標複製。    ######深拷貝:在複製操作時,對於被複制的物件至少有一層複製是物件複製。   完全複製:在複製操作時,對於被複制的物件的每一層複製都是物件複製。

###淺拷貝好比你的影子,你沒了,你的影子也沒有了; ###深拷貝好比你的克隆人,你沒了,你的克隆人還在 ; 備註: retain:始終是淺複製。引用計數每次加一。返回物件是否可變與被複制的物件保持一致。 copy:對於可變物件為深複製,引用計數不改變;對於不可變物件是淺複製,引用計數每次加一。始終返回一個不可變物件。 mutableCopy:始終是深複製,引用計數不改變。始終返回一個可變物件。 不可變物件:值發生改變,其記憶體首地址隨之改變。    可變物件:無論值是否改變,其記憶體首地址都不隨之改變。    引用計數:為了讓使用者清楚的知道,該物件有多少個擁有者(即有多少個指標指向同一記憶體地址)。

12.系統中有哪些物件是單例:

NSTimer、NSNotification、UIWindow、UIApplication 自己寫單例需要注意: 不使用GCD:

 // 單例模式實現要點:
// 1. 廢掉構造方法(呼叫的時候丟擲異常)
// 2. 提供一個類方法向外界返回該類的唯一例項
- (instancetype)init {
    @throw [NSException exceptionWithName:@"CDSingleton" reason:@"不允許呼叫構造方法" userInfo:nil];
    // return nil;
}
// 此方法由於沒有在.h檔案中暴露介面相當於是私有方法
- (instancetype) initPrivate {
    if(self = [super init]) {
        _value = arc4random();
    }
    return self;
}
+ (instancetype) sharedInstance {
    // static型別的變數擁有全域性的生命週期
    static CDSingleton *instance = nil;
    // 使用同步塊保證在多執行緒環境下仍然是單例
    //同步加鎖,在多執行緒中使用,可以使執行緒安全
    @synchronized(self) {
        if(!instance) {
            instance = [[self alloc] initPrivate];
        }
    }
    return instance;
}
複製程式碼

使用GCD:

+(instancetype)sharedInstance{
    static HCDSingleton *singleton = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        singleton = [[HCDSingleton alloc]init];
    });
    return singleton;
}
複製程式碼

13.簡述你對MVC設計模式的理解:

MVC : Model - View - Controller 模型負責資料任務 試圖負責呈現 以及和用於進行互動 控制器用來控制試圖

model 模型:主要負責儲存和運算元據
view 檢視:主要負責展⽰示資料和⽤使用者互動
controller 主要負責將model和view聯絡起來:
從網路獲取資料->賦值給資料模型->將model的資料傳遞給view展⽰示(響應view的delegate和datasource⽅方法)->重新整理view
複製程式碼

14.IOS中那些技術符合觀察者模式:

Key-Value Observing,它提供一種機制,當指定的物件的屬性被修改後,則物件就會接受到通知。每次指定的被觀察的物件的屬性被修改後,KVO自動通知相應的觀察者。

model中定義:
@interface StockData : NSObject { NSString * stockName; float price;}
@end
@implementation StockData
@end
複製程式碼
controller中使用,這裡相當於跟模型說,我要收聽你的更新廣播
- (void)viewDidLoad{
 [super viewDidLoad]; 
stockForKVO = [[StockData alloc] init];
 [stockForKVO setValue:@"searph" forKey:@"stockName"]; 
[stockForKVO setValue:@"10.0" forKey:@"price"]; 
[stockForKVO addObserver:self forKeyPath:@"price" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:NULL];
 myLabel = [[UILabel alloc]initWithFrame:CGRectMake(100, 100, 100, 30 )];
 myLabel.textColor = [UIColor redColor];
 myLabel.text = [stockForKVO valueForKey:@"price"]; 
[self.view addSubview:myLabel]; 
UIButton * b = [UIButton buttonWithType:UIButtonTypeRoundedRect];
 b.frame = CGRectMake(0, 0, 100, 30); 
[b addTarget:self action:@selector(buttonAction) forControlEvents:UIControlEventTouchUpInside];
 [self.view addSubview:b];
}
複製程式碼
使用者單擊View中的button呼叫控制器中的action去更改模型中的資料
-(void) buttonAction{
 [stockForKVO setValue:@"20.0" forKey:@"price"];
}
複製程式碼
控制器需要實現的回撥,相當於收到廣播後我應該做啥事
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context

    if([keyPath isEqualToString:@"price"])
     {
       myLabel.text = [stockForKVO valueForKey:@"price"];
     }
}
複製程式碼
注意使用通知和KVO一定要記著移除,否則會導致crash
檢視dealloc需要取消觀察
- (void)dealloc{
 [super dealloc];
 [stockForKVO removeObserver:self forKeyPath:@"price"]; [stockForKVO release];
}
複製程式碼

15.簡述你對工廠方法的理解:

建立物件的時候,我們一般是alloc一個物件,如果需要建立100個這樣的物件,如果是在一個for迴圈中還好說,直接一句alloc就行了,但是事實並不那麼如意,我們可能會在不同的地方去建立這個物件,那麼我們可能需要寫100句alloc 了,但是如果我們在建立物件的時候,需要在這些物件建立完之後,為它的一個屬性新增一個固定的值,比方說都是某某學校的學生,那麼可能有需要多些100行重複的程式碼了,那麼,如果寫一個-(void)createObj方法,把建立物件和學校屬性寫在這個方法裡邊,那麼就是會省事很多,也就是說我們可以alloc 建立物件封裝到一個方法裡邊,直接呼叫這個方法就可以了,這就是簡單工廠方法。

16.什麼是代理模式,實現代理需要注意什麼:

代理模式:幫助別人完成別人委託你完成的事情。你需要注意遵守別人給你定的約定,和你是否擁有完成這件事的能力。

17.簡述StoryBoard和Xib的聯絡和區別:

StoryBoard可以在上面實現整個專案介面的搭建,可以清楚得看到各個試圖控制器之間的關係,XIB實現自定義要素和良好部件重用性複雜的UI。

18.請簡述UITableView對CELL的重用機制:

比如一個螢幕可以放下5個UITableViewCell  總共會建立6個  設定CELL的重用標誌符  一旦可以重用就重用  不能重用再建立,減少記憶體的消耗。
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    static NSString *cellIdentifier = @"healthNewsTableViewCell";
    healthNewsTableViewCell *cell = [myTableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
    if (!cell) {
        cell = (healthNewsTableViewCell*)[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier: @"healthNewsTableViewCell"];
    }
    return cell;
}
//再將資料繫結寫在WillDisPlayCell中
//讓UITableView稍微順滑點的方法  在顯示cell前被呼叫
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath{
    healthNewsTableViewCell *MyCell = (healthNewsTableViewCell *)cell;
    MyCell.model = dataArray[indexPath.row];
    MyCell.backgroundColor = [UIColor colorWithRed:0.936 green:0.941 blue:0.936 alpha:1.000];
    
}
複製程式碼

19.如何使用UIScrollView實現無限載入多張圖片:

寫一個NSTimer 每隔0.5秒 執行以下回撥方法changPic 如果圖片數量有限 進行一個if判斷 當超過圖片總數時候,顯示第一張,重新開始從第一張顯示。

20.請簡述試圖控制器的生命週期:

#####當一個檢視控制器被建立,並在螢幕上顯示的時候。 程式碼的執行順序 1、 alloc 建立物件,分配空間 2、init (initWithNibName) 初始化物件,初始化資料 3、loadView 從nib載入檢視 ,通常這一步不需要去幹涉。除非你沒有使用xib檔案建立檢視 4、viewDidLoad 載入完成,可以進行自定義資料以及動態建立其他控制元件 5、viewWillAppear 檢視將出現在螢幕之前,馬上這個檢視就會被展現在螢幕上了 6、viewDidAppear 檢視已在螢幕上渲染完成 #####當一個檢視被移除螢幕並且銷燬的時候的執行順序,這個順序差不多和上面的相反 1、viewWillDisappear 檢視將被從螢幕上移除之前執行 2、viewDidDisappear 檢視已經被從螢幕上移除,使用者看不到這個檢視了 3、dealloc 檢視被銷燬,此處需要對你在init和viewDidLoad中建立的物件進行釋放

21.UITableView有哪些優化方式:

1.圖片使用非同步載入如SDWebImage。 2.使用重用識別符號reuseIdentifier,將重用標識標示符static NSString *CellIdentifier = @"XXX"; 3.將資料繫結寫在WillDisPlay這個協議方法中。 4.儘量在CELL中少使用不透明的View。 5.如果不是必須,減少使用reloadData全部cell。

22.簡述IOS中的事件傳遞機制:

舉例:如果view是控制器的view,就傳遞給控制器;如不是,則將其傳遞給它的父檢視 在檢視層次結構的最頂級檢視,如果也不能處理收到的事件或訊息,則其將事件或訊息傳遞給window物件進行處理 如果window物件也不處理,則其將事件或訊息傳遞給UIApplication物件 如果UIApplication也不能處理該事件或訊息,則將其丟棄 #####注意:為什麼用佇列管理事件,而不用棧? 佇列先進先出,能保證先產生的事件先處理。棧先進後出。

23.UITableView有哪些必須要實現的資料來源方法:

// 獲得section包含的cell個數
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section; 
//建立UITableViewCell
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
複製程式碼
//看情況實現的資料來源方法:
//TableView中分組數目
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView; 
//分組頭的標題
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section;   
//分組尾的標題
- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section;
複製程式碼
個人習慣在此方法中實現給模型繫結資料
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
複製程式碼

24.簡述Http協議中get請求和post請求的區別:

get 是從伺服器獲取資料 ,post是向伺服器傳送資料

GET安全性較低,POST安全性較高。因為GET在傳輸過程,資料被放在請求的URL中,而如今現有的很多伺服器、代理伺服器或者使用者代理都會將請求URL記錄到日誌檔案中,然後放在某個地方,這樣就可能會有一些隱私的資訊被第三方看到。另外,使用者也可以在瀏覽器上直接看到提交的資料,一些系統內部訊息將會一同顯示在使用者面前。POST的所有操作對使用者來說都是不可見的。 ###備註: GET請求,將引數直接寫在訪問路徑上。操作簡單,不過容易被外界看到,安全性不高,地址最多255位元組; POST請求,將引數放到body裡面。POST請求操作相對複雜,需要將引數和地址分開,不過安全性高,引數放在body裡面,不易被捕獲。

25.簡述你對非同步請求資料的理解:

直白點 更好的使用者體驗: 減少卡頓 假死的現象。因為非同步請求資料 不會一直等待某個任務完成才執行另外一個任務,可以執行其他的操作。

26.IOS中有哪些技術可以實現開闢執行緒,他們之間有什麼聯絡: 由一個單例方法的實現推出多執行緒使用:

第一種,使用@synchronized(self)
static LocationController *sharedInstance;
+ (LocationController *)sharedInstance {
     @synchronized(self)//使用一個同步保護 保證一個執行緒使用時,其他執行緒無法進入。  
 {
     if (!sharedInstance)
     sharedInstance=[[LocationController alloc] init];
 }
 return sharedInstance;
}
複製程式碼
第二種,使用GCD(Grand Central Dispatch:巨集中心派發)
當你呼叫dispatch_async,你通過一個dispatch佇列,在這個佇列上存有很多block,先進先出,依次執行。
這個佇列可以使用dispatch_create自己建立,也可以呼叫主執行緒佇列dispatch_get_main_queue。
這裡建立的佇列名稱是onceToken。
static LocationController *sharedInstance;
+ (LocationController *)sharedInstance {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        if (!sharedInstance)
            sharedInstance = [[self alloc] init];
    });
    return sharedInstance;
   }
複製程式碼
第三種,使用NSOperationQueue
static LocationController *sharedInstance;
+ (LocationController *)sharedInstance {
    NSOperationQueue *onceToken=[[NSOperationQueue alloc] init];
    [onceToken addOperationWithBlock:^(){
      if (!sharedInstance)
            sharedInstance = [[self alloc] init];
    });
    return sharedInstance; 
    }];
    }
複製程式碼

正式列舉實現單例的常用的3種方法:

  • ####NSThread: 建立方式主要有兩種:
//下面為兩種NSThread的建立方法:
[NSThread detachNewThreadSelector:@selector(myThreadMainMethod:) toTarget:self withObject:nil];
NSThread* myThread = [[NSThread alloc] initWithTarget:selfselector:@selector(myThreadMainMethod:)object:nil];
[myThread start]; //啟動執行緒
複製程式碼

這兩種方式的區別是:前一種一呼叫就會立即建立一個執行緒來做事情;而後一種雖然你 alloc 了也 init了,但是要直到我們手動呼叫 start 啟動執行緒時才會真正去建立執行緒。這種延遲實現思想在很多跟資源相關的地方都有用到。後一種方式我們還可以在啟動執行緒之前,對執行緒進行配置,比如設定 stack 大小,執行緒優先順序。此外還有一種間接的方式:利用NSObject的方法performSelectorInBackground:withObject: 來建立一個執行緒:

[myObj performSelectorInBackground:@selector(myThreadMainMethod) withObject:nil];
 //在後臺執行某一個方法其效果與 NSThread 的 detachNewThreadSelector:toTarget:withObject: 是一樣的。
複製程式碼
  • ####NSOperationQueue (操作佇列)
@interface ViewController () {
    // 操作佇列
    NSOperationQueue *queue;
}
@end
@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    // 併發佇列(佇列中的操作會併發執行)
    queue = [[NSOperationQueue alloc] init];
    queue.maxConcurrentOperationCount = 5;
 for (int i = 0; i < 5; i++) {
        CDCar *myCar = [[CDCar alloc] initWithX:20 + 70 * i andY:10];
        [myCar draw:self.view];
          NSOperation *op = [NSBlockOperation blockOperationWithBlock:^{
            [myCar run];
        }];
        [queue addOperation:op];
    }
}
@end
複製程式碼
  • ####GCD
dispatch_async(dispatch_get_global_queue(0, 0), ^{     
// 耗時的操作   比如網路資料資料請求
});  
dispatch_async(dispatch_get_main_queue(), ^{         
// 更新介面      
 }); 
複製程式碼

27.NSThread中執行緒是如何實現通訊的: 28.GCD中有哪些建立執行緒的方式:

dispatch_async(dispatch_get_global_queue(0, 0), ^{     
// 耗時的操作   比如網路資料資料請求
});  
dispatch_async(dispatch_get_main_queue(), ^{         
// 更新介面      
 }); 
複製程式碼

29.IOS中哪些技術可以保證執行緒的安全:

1.使用互斥鎖 互斥鎖使用格式

@synchronized(鎖物件)
 { 
// 需要鎖定的程式碼 
 }
注意:鎖定1份程式碼只用1把鎖,用多把鎖是無效的
複製程式碼
  • 互斥鎖的優缺點 優點:能有效防止因多執行緒搶奪資源造成的資料安全問題 缺點:需要消耗大量的CPU資源  互斥鎖的使用前提:多條執行緒搶奪同一塊資源  相關專業術語:執行緒同步,多條執行緒按順序地執行任務 互斥鎖,就是使用了執行緒同步技術

OC在定義屬性時有nonatomic和atomic兩種選擇 atomic:原子屬性,為setter方法加鎖(預設就是atomic) nonatomic:非原子屬性,不會為setter方法加鎖

@property (assign, atomic) int age;
 - (void)setAge:(int)age;
 {  
     @synchronized(self)
      { 
          _age = age;  
      }
 }
複製程式碼
  • 原子和非原子屬性的選擇 nonatomic和atomic對比 atomic:執行緒安全,需要消耗大量的資源 nonatomic:非執行緒安全,適合記憶體小的移動裝置

30.ASIHttpRequest的父類是什麼:

ASIHTTPRequest是一款極其強勁的HTTP訪問開源專案。讓簡單的API完成複雜的功能, 如:非同步請求,佇列請求,GZIP壓縮,快取,斷點續傳,進度跟蹤,上傳檔案,HTTP認證。

它是NSOperationQueues的擴充套件,小而強大。
但也與它的父類略有區別。
如,僅新增到佇列中其實並不能執行請求,只有呼叫[queue go]才會執行;
一個正在執行中的佇列,並不需要重複呼叫[queue go ]。
預設情況下,佇列中的一個請求如果失敗,它會取消所有未完成的請求。
可以設定[queue setShouldCancel];
複製程式碼

31.簡述AFNetWork的實現原理:

AFNetwork是一個輕量級的網路請求api類庫。是以NSURLConnection, NSOperation和其他方法為基礎的。

  • AFNewWork的基本使用: //建立一個下載任務
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
NSURL *URL = [NSURL URLWithString:@"http://example.com/download.zip"];NSURLRequest *request = [NSURLRequest requestWithURL:URL];
NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:request progress:nil destination:^NSURL *(NSURL *targetPath, NSURLResponse *response) { 
NSURL *documentsDirectoryURL = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil];
 return [documentsDirectoryURL URLByAppendingPathComponent:[response suggestedFilename]];
} completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error) {
 NSLog(@"File downloaded to: %@", filePath);
}];
[downloadTask resume];
複製程式碼

//建立一個上傳任務

NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
NSURL *URL = [NSURL URLWithString:@"http://example.com/upload"];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
NSURL *filePath = [NSURL fileURLWithPath:@"file://path/to/image.png"];
NSURLSessionUploadTask *uploadTask = [manager uploadTaskWithRequest:request fromFile:filePath progress:nil completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) { 
if (error) { 
NSLog(@"Error: %@", error);
 } else { 
NSLog(@"Success: %@ %@", response, responseObject); }
}];
[uploadTask resume];
複製程式碼

//帶進度的上傳任務

NSMutableURLRequest *request = [[AFHTTPRequestSerializer serializer] multipartFormRequestWithMethod:@"POST" URLString:@"http://example.com/upload" parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
 [formData appendPartWithFileURL:[NSURL fileURLWithPath:@"file://path/to/image.jpg"] name:@"file" fileName:@"filename.jpg" mimeType:@"image/jpeg" error:nil];
 } error:nil];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
NSURLSessionUploadTask *uploadTask;
uploadTask = [manager uploadTaskWithStreamedRequest:request progress:^(NSProgress * _Nonnull uploadProgress) { 
// This is not called back on the main queue. // You are responsible for dispatching to the main queue for UI updates dispatch_async(dispatch_get_main_queue(), ^{ 
//Update the progress view 
[progressView setProgress:uploadProgress.fractionCompleted]; 
}); } completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) { 
if (error) { 
NSLog(@"Error: %@", error);
 } else {
 NSLog(@"%@ %@", response, responseObject); 
} }];
[uploadTask resume];
複製程式碼

//請求資料的任務

NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
NSURL *URL = [NSURL URLWithString:@"http://httpbin.org/get"];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
NSURLSessionDataTask *dataTask = [manager dataTaskWithRequest:request completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
 if (error) { 
NSLog(@"Error: %@", error); 
} else { 
NSLog(@"%@ %@", response, responseObject); 
}}];
[dataTask resume];
複製程式碼

32.如何理解Block,block有什麼用途:

void (^block)() = ^(){};//實質就是儲存一段程式碼
//定義:
typedef void (^Block)();

@property (strong,nonatomic) Block 
複製程式碼

Block是沒有名字的匿名函式,類似於C語言中的函式指標。

IOS面試
可以用於頁面間傳值 進行回撥... 舉例: //第二個頁面:

.h
// 定義Block型別的屬性(用來儲存一段回撥程式碼)
// 屬性修飾符必須寫copy因為要從棧將Block拷貝到堆上
@property (nonatomic, copy) void(^myBlock)(NSString *);

複製程式碼
.m
- (IBAction)buttonClicked:(id)sender {
   if (_myBlock) {
        // 呼叫Block 語法跟呼叫C函式是一致的
        _myBlock([NSString stringWithFormat:@"你好, %@", _nameField.text]);
    }
    [self dismissViewControllerAnimated:YES completion:^{
        NSLog(@"回到第一個檢視控制器!!!");
    }];
}

複製程式碼

//第一個頁面 (接收頁面)

.m
- (IBAction)buttonClicked:(UIButton *)sender {
     CDSecondViewController *secondVC = [[CDSecondViewController alloc] init];
    // 給第二個檢視控制器的Block變數賦值
    secondVC.myBlock = ^(NSString *str) {
        _myLabel.text = str;
    };
    [self presentViewController:secondVC animated:YES completion:^{
        // NSLog(@"搞定第二個檢視控制器!!!");
    }];
}


具體使用block:

#import "ViewController.h"

typedef void (^otherBlock) ();

typedef void(^ResultBlock)(BOOL suc,NSString *plat,NSString *info);

@interface ViewController ()

//屬性定義block
@property (nonatomic,copy) void(^someBlock)();
//alias定義block
@property (nonatomic,copy) otherBlock oBlock;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
}

-(void)getDataFromServerWithResult:(otherBlock)oBlock{
    
}

-(void)getData:(ResultBlock)shareBlock{
    
}

- (void)pullDownRefreshWithFinishedCallBack:(void(^)())finishCallBack{
    
}

@end


複製程式碼

33.簡述TCP和UDP的區別:

TCP傳輸可靠有保證,它有三次握手機制,這一機制保證校驗了資料,保證了他的可靠性。而UDP就沒有了,所以不可靠。不過UDP的速度是TCP比不了的,而且UDP的反應速度更快,QQ就是用UDP協議傳輸的,HTTP是用TCP協議傳輸的。

34.如何保證定位更省電:

desiredAccuracy,這個屬性用來控制定位精度,精度越高耗電量越高,所以應該看實際情況設定這個屬性的值。

35.簡述SDWebImage的實現原理:

  • SDWebImage載入圖片的流程:
1.入口 setImageWithURL:placeholderImage:options: 會先把 placeholderImage 顯示,然後 SDWebImageManager 根據 URL 開始處理圖片。
2.進入 SDWebImageManager-downloadWithURL:delegate:options:userInfo:,交給 SDImageCache 從快取查詢圖片是否已經下載 queryDiskCacheForKey:delegate:userInfo:。
3.先從記憶體圖片快取查詢是否有圖片,如果記憶體中已經有圖片快取,SDImageCacheDelegate 回撥 imageCache:didFindImage:forKey:userInfo: 到 SDWebImageManager。
4.SDWebImageManagerDelegate 回撥 webImageManager:didFinishWithImage: 到 UIImageView+WebCache 等前端展示圖片。
5.如果記憶體快取中沒有,生成 NSInvocationOperation 新增到佇列開始從硬碟查詢圖片是否已經快取。
6.根據 URLKey 在硬碟快取目錄下嘗試讀取圖片檔案。這一步是在 NSOperation 進行的操作,所以回主執行緒進行結果回撥 notifyDelegate:。
7.如果上一操作從硬碟讀取到了圖片,將圖片新增到記憶體快取中(如果空閒記憶體過小,會先清空記憶體快取)。SDImageCacheDelegate 回撥 imageCache:didFindImage:forKey:userInfo:。進而回撥展示圖片。
8.如果從硬碟快取目錄讀取不到圖片,說明所有快取都不存在該圖片,需要下載圖片,回撥 imageCache:didNotFindImageForKey:userInfo:。
9.共享或重新生成一個下載器 SDWebImageDownloader 開始下載圖片。
10.圖片下載由 NSURLConnection 來做,實現相關 delegate 來判斷圖片下載中、下載完成和下載失敗。
11.connection:didReceiveData: 中利用 ImageIO 做了按圖片下載進度載入效果。
12.connectionDidFinishLoading: 資料下載完成後交給 SDWebImageDecoder 做圖片解碼處理。
13.圖片解碼處理在一個 NSOperationQueue 完成,不會拖慢主執行緒 UI。如果有需要對下載的圖片進行二次處理,最好也在這裡完成,效率會好很多。
14.在主執行緒 notifyDelegateOnMainThreadWithInfo: 宣告解碼完成,imageDecoder:didFinishDecodingImage:userInfo: 回撥給 SDWebImageDownloader。
15.imageDownloader:didFinishWithImage: 回撥給 SDWebImageManager 告知圖片下載完成。
16.通知所有的 downloadDelegates 下載完成,回撥給需要的地方展示圖片。
17.將圖片儲存到 SDImageCache 中,記憶體快取和硬碟快取同時儲存。寫檔案到硬碟也在以單獨 NSInvocationOperation 完成,避免拖慢主執行緒。
18.SDImageCache 在初始化的時候會註冊一些訊息通知,在記憶體警告或退到後臺的時候清理記憶體圖片快取,應用結束的時候清理過期圖片。
19.SDWI 也提供了 UIButton+WebCache 和 MKAnnotationView+WebCache,方便使用。
20.SDWebImagePrefetcher 可以預先下載圖片,方便後續使用。

複製程式碼

36.簡述XML和JSON資料各有哪些優勢:

(1).可讀性方面。JSON和XML的資料可讀性基本相同,JSON和XML的可讀性可謂不相上下,一邊是建議的語法,一邊是規範的標籤形式,XML可讀性較好些。 (2).可擴充套件性方面。XML天生有很好的擴充套件性,JSON當然也有,沒有什麼是XML能擴充套件,JSON不能的。 (3).編碼難度方面。XML有豐富的編碼工具,比如Dom4j、JDom等,JSON也有json.org提供的工具,但是JSON的編碼明顯比XML容易許多,即使不借助工具也能寫出JSON的程式碼,可是要寫好XML就不太容易了。 (4).解碼難度方面。XML的解析得考慮子節點父節點,讓人頭昏眼花,而JSON的解析難度幾乎為0。這一點XML輸的真是沒話說。 (5).流行度方面。XML已經被業界廣泛的使用,而JSON才剛剛開始,但是在Ajax這個特定的領域,未來的發展一定是XML讓位於JSON。到時Ajax應該變成Ajaj(Asynchronous Javascript and JSON)了。 (6).解析手段方面。JSON和XML同樣擁有豐富的解析手段。 (7).資料體積方面。JSON相對於XML來講,資料的體積小,傳遞的速度更快些。 (8).資料互動方面。JSON與JavaScript的互動更加方便,更容易解析處理,更好的資料互動 (9).資料描述方面。JSON對資料的描述性比XML較差。 (10).傳輸速度方面。JSON的速度要遠遠快於XML。

37.簡述執行緒和程式有什麼聯絡和區別:

看到過一篇部落格 部落格上面,在這裡引用部落格中對執行緒和程式的理解:

1.計算機的核心是CPU,它承擔了所有的計算任務。它就像一座工廠,時刻在執行。 2.假定工廠的電力有限,一次只能供給一個車間使用。也就是說,一個車間開工的時候,其他車間都必須停工。背後的含義就是,單個CPU一次只能執行一個任務。 3.程式就好比工廠的車間,它代表CPU所能處理的單個任務。任一時刻,CPU總是執行一個程式,其他程式處於非執行狀態。 4.一個車間裡,可以有很多工人。他們協同完成一個任務。執行緒就好比車間裡的工人。一個程式可以包括多個執行緒。 5.車間的空間是工人們共享的,比如許多房間是每個工人都可以進出的。這象徵一個程式的記憶體空間是共享的,每個執行緒都可以使用這些共享記憶體。 6.可是,每間房間的大小不同,有些房間最多隻能容納一個人,比如廁所。裡面有人的時候,其他人就不能進去了。這代表一個執行緒使用某些共享記憶體時,其他執行緒必須等它結束,才能使用這一塊記憶體。 7.一個防止他人進入的簡單方法,就是門口加一把鎖。先到的人鎖上門,後到的人看到上鎖,就在門口排隊,等鎖開啟再進去。這就叫"互斥鎖"(Mutual exclusion,縮寫 Mutex),防止多個執行緒同時讀寫某一塊記憶體區域。 8.還有些房間,可以同時容納n個人,比如廚房。也就是說,如果人數大於n,多出來的人只能在外面等著。這好比某些記憶體區域,只能供給固定數目的執行緒使用。 9.這時的解決方法,就是在門口掛n把鑰匙。進去的人就取一把鑰匙,出來時再把鑰匙掛回原處。後到的人發現鑰匙架空了,就知道必須在門口排隊等著了。這種做法叫做"訊號量"(Semaphore),用來保證多個執行緒不會互相沖突。 不難看出,mutex是semaphore的一種特殊情況(n=1時)。也就是說,完全可以用後者替代前者。但是,因為mutex較為簡單,且效率高,所以在必須保證資源獨佔的情況下,還是採用這種設計。

38.簡述NSUserDefaults的使用場景和使用注意事項:

對於NSUerdefaults來說 一般可以用來儲存使用者的偏好設定 比如登陸賬號 密碼這些。 除此之外 我們還可以用它來儲存圖片, 字串 , 數字 和物件。它被儲存到專案中的Plists檔案裡面裡。儲存圖片 一般用它裡面的兩個方法 圖片儲存可以用PNG或者JPG對應的方法 先轉換成NSData 再用NSUerdefaults儲存 儲存的時候為了讓它馬上存下來要用synchronize 。它還可以用來在程式間進行反向傳值。

39.IOS中資料庫是用什麼技術實現的:

Sqlite 3

40.簡述什麼是主鍵 什麼是外來鍵:

主鍵是用來唯一確定一條記錄的唯一標記,如身份證號碼。外來鍵是用來關聯其他表,可以通過這個外來鍵唯一確定另外一張表上面的欄位。如:A表中有個欄位是B表中的主鍵,那麼這個欄位就是A的外來鍵。

41.IOS中如何實現資料模型的儲存: 42.簡述IOS的沙盒機制:

IOS中的沙盒機制(SandBox)是一種安全體系,它規定了應用程式只能在為該應用建立的資料夾內讀取檔案,不可以訪問其他地方的內容。所有的非程式碼檔案都儲存在這個地方,比如圖片、聲音、屬性列表和文字檔案等。 1.每個應用程式都在自己的沙盒內 2.不能隨意跨越自己的沙盒去訪問別的應用程式沙盒的內容 3.應用程式向外請求或接收資料都需要經過許可權認證

43.如何實現真機除錯:

Xcode7以後可以不用配置開發者證照直接進行真機測試 嘿嘿

44.如何查詢專案中的記憶體洩露:

使用Instruments來查詢程式中的記憶體洩露,以及NSZombieEnabled。

45.專案中支付環節如何實現的:

注意需要配置Apple ID 其他按照微信支付或者支付寶文件進行配置

46.如何實現專案上線到AppStore 47.簡述你在專案中遇到過哪些問題:

以前做一個專案時,專案中使用了高德地圖,當時時每點選進入一個單元格就進入地圖,後來發現點選和退出的速度加快後,程式會crash。後來找了好久,發現 每次建立地圖會佔用很大的記憶體,而你每次還沒有建立完畢就退出,就會導致崩潰,所以最後把建立地圖的那一部分程式碼轉移到了建立單元格哪裡(前一個頁面中),這樣保證每次都只有一個地圖。而不會因為地圖還沒有建立好就退出導致crash。

48.如何實現流媒體格式的視訊邊播放邊快取: 49.簡述self.name = xxx 與_name=xxx的區別:

(1)self.name  有getter 和sett er 方法     (2)self.name 可以被kvo 監聽到  (set 方法 和kvc方法)     (3)self.name  考慮了記憶體管理  是一個物件指標

前者是呼叫了setter方法,後者是普通的賦值。

50.#include與#import的區別、#import與@class的區別:

(1)#include與#import區別:#include和#import效果相同,只是後者不會引起交叉編譯,確保標頭檔案只會被匯入一次。 (2)#import和@class的區別:import會匯入類的所有資訊,包括變數和方法,而@class只是告訴編譯器,後面的名稱是類的名稱。推薦使用#import,編譯效率更高,防止相互包含的編譯錯誤。

(二) 1.IOS中是否支援垃圾回收機制:

IOS開發只支援手動記憶體管理和ARC,Mac開發支援GC垃圾回收機制,10.8之後棄用了GC,推薦使用ARC。

2.使用者自定義了一個物件,如何實現拷貝(可變和不可變拷貝)

必須實現copying和mutableCopying協議,表示返回一個不可變和可變的物件。否則程式將會出現異常。

-(id)copyWithZone:(NSZone*)zone{
Person *person = [[self Class] allocWithZone:zone];
person->age = self.age;
person->name = self.name;
return person;
}
複製程式碼
-(id)mutableCopyWithZone(NSZone*)zone;
複製程式碼

3.釋放物件的時候為什麼要呼叫[super dealloc]:

因為子類繼承父類,子類中一些物件(例項變數)也是繼承父類的,因此我們需要呼叫父類的方法,將父類所擁有的例項進行釋放。

4.簡述常見的設計模式:

單例設計、代理設計、觀察者(通知)、工廠方法。

5.記憶體管理中使用release方法好還是使用self.xxx = nil好:

使用self.xxx = nil 好,因為它會先呼叫release方法,而且將變數設定為nil,這樣就可以更安全的釋放物件,防止野指標呼叫。

6.事件響應者鏈的概念:

響應者連結串列示一系列的響應者物件。事件被交給第一響應者處理,如果第一響應者不處理,事件會沿著響應者鏈條向上傳遞,交給下一個響應者(next responder)。一般來說第一響應者是個檢視或者其子類物件,當其被觸控後事件交給它處理,如果不處理,事件就會被傳遞到它的檢視控制器(如果存在),然後是它的父檢視(superview)(如果存在),以此類推,直到頂層檢視。接下來會沿著頂層檢視(top view)到視窗(UIWindow)再到UIApplication。如果整個過程都沒有響應這個事件,該事件就會被丟棄。

7.static變數和static函式的區別:

(1)static變數表示靜態儲存變數,變數儲存在靜態儲存區。 (2)加在函式前面表示該函式是內部連線,只在本檔案中有效,別的檔案中不能應用該函式。

static 全域性變數與普通的全域性變數有什麼區別:static 全域性變數只初使化一次, 防止在其他檔案單元中被引用; static 區域性變數和普通區域性變數有什麼區別:static 區域性變數只被初始化一次, 下一次依據上一次結果值; static 函式與普通函式有什麼區別:static 函式在記憶體中只有一份,普通函式 在每個被呼叫中維持一份拷貝

8.物件導向的三大支柱 以及如何理解動態繫結(多型):

三大支柱:封裝、多型、繼承 多型: 繼承父類,實現方法,只看物件不看指標,不同的物件實現自己重寫的不同的方法。

9.frame與bounds的區別:

(1)Frame:該view是在父view座標系中的位置和大小(參照點是父檢視的座標系)當view做了transform時,該值不準確。 (2)Bounds:該view是在本身座標系的位置和大小(參照點是本身的座標系統)。

10.談談對Runloop的理解:

Run loop是執行緒相關的基礎框架的一部分。一個run loop就是一個事件處理的迴圈,用來不停的排程工作以及處理輸入事件。使用run loop的目的就是讓你的執行緒在有工作的時候忙起來,沒有工作的時候休眠。

11.SVN、Git協作開發,怎樣防止程式碼檔案衝突:

(1)防止程式碼衝突:不要同時多人修改同一個檔案。例如A、B都同時修改一個檔案,先讓A修改,然後提交到伺服器,然後B更新下來,在進行修改。 (2)伺服器上的專案檔案xcodeproj,僅讓一個人管理提交,其他人只更新。防止此檔案產生衝突。

12.斷點續傳如何實現的:

將下載的檔案分成幾個部分,通過http協議的請求頭,設定每一部分下載的偏移量,然後通過多執行緒下載每一部分,下載完成以後 再組成為最終的完整檔案。

13.堆和棧的區別 以及佇列和棧的區別:

棧區(stack)由編譯器自動分配釋放,存放 方法(函式)的引數值、區域性變數的值等、堆區(heap)一般由程式設計師分配和釋放、若不釋放,則記憶體溢位。 佇列:先進先出 棧:先進後出

14.協議、代理的理解:

實際上是兩個物件的相互呼叫 A類 B類 A中有B的物件 B.delegate=A

15.HTTP協議、TCP、UDP協議

資料請求:狀態行、請求頭、請求體 服務端響應:響應頭(狀態碼:200;404資源沒有找到;400客戶端請求語法錯誤;500伺服器錯誤;)響應體w3c school線上教程

16.IOS 6 與 IOS 7區別:

IOS 6 擬物化風格 IOS 7 扁平化風格

17.什麼是指標:

type *p; type:類資料型別。用來儲存記憶體單元的編號指標 不完全等於 地址!有型別的標識很多型別的指標,指向資料、指向方法、void 型 。不同的編譯環境,sizeof 可能不同。

18.寫一個巨集,輸入兩個引數返回其中較小的一個:

#define MIN(a,b) ((a)>(b)?(b):(a))
複製程式碼

19.排序演算法: ####選擇排序


-(void)bunbleSort:(NSMutableArray *)aData{
int count = 0;
for(int i = 0; i < [aData count]-1;i++)
{
for(int j = i+1; j < [aData count];j++)
{
if([[aData objectAtIndex:i] integerValue] < [[aDataobjectAtIndex:j]integerValue])
{
NSNumber *temp = [aData objectAtIndex:i];
[aData replaceObjectAtIndex:i withObject:[aData
objectAtIndex:j]];
[aData replaceObjectAtIndex:j withObject:temp];
count ++;}
}}
}
複製程式碼

####氣泡排序


-(void)sort2:(NSMutableArray *)resource{
//NSNumber小 -> 大
int count = [resource count];
for(int i = 0; i < count-1; i ++)
{
for(int j = 0; j < count-i-1; j ++)
{
if([[resource objectAtIndex:j] integerValue]>[[resource objectAtIndex:j+1] integerValue])
{
NSNumber *temp = [resource objectAtIndex:j];
[resource replaceObjectAtIndex:j
withObject:[resource objectAtIndex:j+1]];
[resource replaceObjectAtIndex:j+1
withObject:temp];
}
}}
}
複製程式碼

####快速排序


-(void)quickSortWithArray:(NSMutableArray *)aDataleft:(NSInteger)left right:(NSInteger)right
{
if (right > left) {NSInteger i = left;
NSInteger j = right + 1;
while (true) {
while (i+1 < [aData count] && [aData objectAtIndex:++i] <[aData objectAtIndex:left]) ;
while (j-1 > -1 && [aData objectAtIndex:--j] > [aDataobjectAtIndex:left]) ;
if (i >= j) 
{
break;
}
[self swapWithData:aData index1:i index2:j];
}
[self swapWithData:aData index1:left index2:j];

[self quickSortWithArray:aData left:left right:j-1];
[self quickSortWithArray:aData left:j+1 right:right];
}
}
-(void)swapWithData:(NSMutableArray *)aDataindex1:(NSInteger)index1 index2:(NSInteger)index2
{
NSNumber *tmp = [aData objectAtIndex:index1];
[aData replaceObjectAtIndex:index1 withObject:[aDataobjectAtIndex:index2]];
[aData replaceObjectAtIndex:index2 withObject:tmp];
}
複製程式碼

20.寫一個單連結串列,要求可以插入資料和刪除單個資料:


struct QFInfo{
int num;
struct QFInfo *next;
};
struct QFInfo *qfinfo;
//連結串列頭
void insert_AtFirst(struct QFInfo *head,struct QFInfo *insert)
{
insert->next = head->next;
head->next = insert;
}
//連結串列尾
void insert_AtEnd(struct QFInfo *head,struct QFInfo *insert)
{
struct QFInfo *temp = head->next;
while (temp->next != NULL) {
temp = temp->next;
}
insert->next = NULL;
temp->next = insert;
}
//刪除
void delete_1(struct QFInfo *head,struct QFInfo *del)
{
struct QFInfo *temp = head->next;
while (temp->next != NULL && temp->next != del)
 {
temp = temp->next;
}
if(temp->next != NULL)
{
temp->next = temp->next->next;
}
}
複製程式碼

21.下面的程式中,3次retainCount分別是什麼,為什麼:

NSMutableArray *arr = [[NSMutableArray array] retain]; 
NSString *str = [NSString stringWithFormat:@"test"];
 [str retain]; 
[arr addObject:str]; 
NSLog(@"%@%lu",str,[str retainCount]); 
[str retain]; 
[str release]; 
[str release]; 
NSLog(@"%@%lu",str,[str retainCount]);
 [arr removeObject:str];
 NSLog(@"%@%lu",str,[str retainCount]);
分別是3、2、1,因為初始化的時候retain  為1,retain的時候+1,往陣列中add的時候+1,release的時候-1,從陣列中刪除的時候-1。
複製程式碼

22.引用和指標的區別:

1 .從現象上看:指標在執行時可以改變其所指向的值,而引用一旦和某個物件繫結後就不再改變。引用訪問一個變數是直接訪問,而指標是間接訪問。 2.從記憶體分配上看:程式為指標變數分配記憶體區域,而引用不分配記憶體區域。 3.從編譯上看:程式在編譯時分別將指標和引用新增到符號表上,符號表上記錄的是變數名及變數所對應地址。指標變數在符號表上對應的地址值為指標變數的地址值,而引用在符號表上對應的地址值為引用物件的地址值。符號表生成後就不會再改,因此指標可以改變指向的物件(指標變數中的值可以改),而引用物件不能改。

23.如何將圖片新增到相簿:


UIImage *img = [UIImage imageWithNamed:@”123.ppng”];
 UIImageWriteToSavedPhotosAlbum(img, nil, nil, nil);
複製程式碼

24.寫一個獲取日期的方法,輸出格式為2016-08-08:


NSDate *date = [NSDate date];
NSDateFormatter *dateFm = [[NSDateFormatter alloc] init];
 dateFm.dateFormat = @"yyyy-MM-dd"; 
NSString *dateStr = [dateFm stringFromDate:date];
NSLog(@"dateStr:%@",dateStr);
複製程式碼

25.將一組資料永久儲存到手機裡:

NSUserDefaults、plist、資料庫、普通檔案、歸檔

26.NSarray *array = @[@“a”,@“b”,@“c”,@“a”,@“d”....],裡面有N個string元素,求出array中唯一元素,要求複雜度為N:

(分析:將重複的元素去掉拼接成一個字串)
程式碼例項:
NSArray *arr = @[@"a",@"b",@"b",@"c"];
NSString *resultStr = [arr objectAtIndex:0];
for (NSString *str in arr) 
{
if ([resultStr rangeOfString:str].location == NSNotFound) {
resultStr = [resultStr stringByAppendingString:str];
}
}
NSLog(@"%@",resultStr);
複製程式碼

27.寫一個Block使用的例子,儘可能體現出block程式設計的語法和優勢:

void(^myBlock)(NSString *msg);
myBlock = ^(NSString *str){
NSLog(@"%@",str);//line3
}
//使用block
//相當於把line3的程式碼放在這裡執行。
myBlock(@"hello!");
複製程式碼

28.nil和NULL有什麼區別:

nil是一個物件,NULL是一個值

29.什麼時候使用NSMutableArray,什麼時候使用NSArray:

當陣列在程式執行時,需要不斷變化的,使用NSMutableArray,當陣列在初始化後,便不再改變的,使用NSArray。需要指出的是,使用NSArray只表明的是該陣列在執行時不發生改變,即不能往NSAarry的陣列裡新增和刪除元素,但不表明其陣列內的元素的內容不能發生改變。NSArray是執行緒安全的,NSMutableArray不是執行緒安全的,多執行緒使用到NSMutableArray需要注意。

30.如果我們不建立記憶體池,是否有記憶體池提供給我們:

介面執行緒維護自己的記憶體池,使用者自己建立的資料執行緒,則需要建立該執行緒的記憶體池。

31.類NSObject的那些方法經常被使用:

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

32.什麼是謂詞:

謂詞是通過NSPredicate,是通過給定的邏輯條件作為約束條件,完成對資料的篩選。
predicate = [NSPredicate predicateWithFormat:@"customerID == %d",n];
a = [customers filteredArrayUsingPredicate:predicate];
複製程式碼

33.簡述記憶體分割槽情況:

1).程式碼區:存放函式二進位制程式碼 2).資料區:系統執行時申請記憶體並初始化,系統退出時由系統釋放。存放全域性變數、靜態變數、常量 3).堆區:通過malloc等函式或new等操作符動態申請得到,需程式設計師手動申請和釋放 4).棧區:函式模組內申請,函式結束時由系統自動釋放。存放區域性變數、函式引數

相關文章