高級面試題

多線程的底層實現
1> 首先搞清楚什麼是線程、什麼是多線程、多線程的使用場合
2> Mach是第一個以多線程方式處理任務的系統,所以多線程的底層實現機制是基於Mach的線程
3> GCD 和 NSOperationQueue 區別。
•NSThread:
–優勢:NSThread 比其餘兩個輕量級,使用簡單
–缺點:須要本身管理線程的生命週期、線程同步、加鎖、睡眠以及喚醒等。線程同步對數據的加鎖會有必定的系統開銷

•NSOperation:
–不須要關心線程管理,數據同步的事情,能夠把精力放在本身須要執行的操做上
–NSOperation是面向對象的

•GCD:
–Grand Central Dispatch是由蘋果開發的一個多核編程的解決方案。iOS4.0+才能使用,是替代NSThread, NSOperation的高效和強大的技術
–GCD是基於C語言的
4> 分發源 和 分發隊列 . dispatch source監聽事件(線程間
通訊)。當這些事件發生時,它自動將一個block放入一個dispatch queue的執行例程中。
5> 開發中實現多線程的方案
C語言的POSIX接口:#include <pthread.h>
OC的NSThread
C語言的GCD接口(性能最好,代碼更精簡)
OC的NSOperation和NSOperationQueue(基於GCD)
6> 爲何UI必須在主線程 [主線程又叫UI線程]
項目經理是主線程,程序員是子線程,那麼程序員完成任務後須要通知經理【不然經理不知道,那麼經理就沒法整合代碼了】
有時候能夠在子線程刷新UI,【注意:只是有時候能夠】爲了不這種狀況,咱們必須在主線程刷新UI,子線程會和主線程交流的,但何時交流是不肯定的,咱們沒法知曉具體時間
7>線程間怎麼通訊
1. GCD dispatch_async(dispatch_get_main_queue)回到主線程
2. performSelector:onThread:withObject:waitUntilDone:
   performSelectorOnMainThread:withObject:waitUntilDone:
1. NSMachPort(可選)

網絡圖片處理問題中怎麼解決一個相同的網絡地址重複請求的問題
利用字典(圖片地址爲key,下載操做爲value)
這裏其實問的是SDWebImage,關於圖片處理,SDWebImage已經幫咱們處理過了,下載以前他會先到緩存中查找,若是有就會直接拿來用,沒有就去下載



列舉cocoa中常見對幾種多線程的實現,並談談多線程安全的幾種解決辦法及多線程安全怎麼控制?
1> 只在主線程刷新訪問UI
2> 若是要防止資源搶奪,得用@synchronized進行加鎖保護
3> 若是異步操做要保證線程安全等問題, 儘可能使用GCD(有些函數默認就是安全的)
4> 注意
1. dispatch_sync(dispatch_get_mian_queue)
     ^{  
1. nslog(@「-----」)

      }   
在主線程中執行就會形成死鎖。
1. 2 的前提是1 已經執行完畢,可是1執行完畢的前提是2 執行完畢 ,由此就形成了死鎖。
備註:sync是同步的,並且他表明的是當前線程【多是主線程也多是子線程】若是是表明主線程那麼sync 會等到 後面block 執行完成才返回, sync 又再 dispatch_get_main_queue() 隊列中,它是串行隊列,sync 是後加入的,前一個是主線程,因此 sync 想執行 block 必須等待主線程執行完成,主線程等待 sync 返回,去執行後續內容。照成死鎖,sync 等待mainThread 執行完成,mianThread 等待sync 函數返回。


GCD內部怎麼實現的
1> iOS和OS X的核心是XNU內核,GCD是基於XNU內核實現的
2> GCD的API所有在libdispatch庫中
3> GCD的底層實現主要有Dispatch Queue和Dispatch Source
Dispatch Queue :管理block(操做)
Dispatch Source :處理事件(好比線程間的通訊,新線程)

你爲何要使用NSOperationQueue,實現了什麼?請描述它和GCD的區別和相似的地方
1> GCD是純C語言的API 封裝在libdispatch庫
     NSOperationQueue是基於GCD的OC版本封裝
2> GCD只支持FIFO的隊列
     NSOperationQueue能夠很方便地調整執行順序、設置最大併發數量
3> NSOperationQueue能夠在輕鬆在Operation間設置依賴關係
     GCD須要寫不少的代碼才能實現
4> NSOperationQueue支持KVO,能夠監測operation是否正在執行(isExecuted)、是否結束(isFinished),是否取消(isCanceld)
建一個Person類:
@interface Person : NSObject
@property (copy, nonatomic) NSString *name;
@property(assign, nonatomic) int;
在控制器中: age;
Person *p = [[Person alloc]init];
p.name = @"jack";
p.age = 18;
// 註冊KVO
[p addObserver:self forKeyPath:@「name" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
p.name = @"rose";
self.person = p;
p的name屬性發生變化就會調用這個方法
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    NSLog(@"%@",change);
}
補充
// 註冊KVO
(void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context;
//解除KVO
• (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath;
值得注意的是:不要忘記解除註冊,不然會致使資源泄露。

5> GCD的執行速度比NSOperationQueue快

任務之間不太互相依賴:GCD
任務之間有依賴\或者要監放任務的執行狀況:NSOperationQueue

在使用GCD以及block時要注意些什麼?它們兩是一回事兒麼?block在ARC中和傳統的MRC中的行爲和用法有沒有什麼區別,須要注意些什麼?
block 底層: 結構體指針
block 原理 :沒有__block修飾的變量是值傳遞(閉包)
                   有__block修飾的變量地址傳遞  【有__block 修飾的變量咱們才能在block內部修改它   做用 : 1  逆傳值    從控制器A 跳轉到 控制器B,而A須要B裏邊的東西,這個時候就用到逆傳值了
1. 保存代碼
2. 回調
Block的使用注意:
block的內存管理
防止循環retian
      爲何會循環retain(在block塊裏使用self,會對self有個強指針)
      通常用copy修飾block來將block從棧中移到堆中,若是用copy,則self會對block有一個強指針,而在block中又使用了self,那麼block會對self有一個強指針。
MRC:__block
ARC:__weak\__unsafe_unretained
1. 對Block無論是retain、copy、release都不會改變引用計數retainCount,retainCount始終是1
在異步線程中下載不少圖片,若是失敗了,該如何處理?請結合RunLoop來談談解決方案.(提示:在異步線程中啓動一個RunLoop從新發送網絡請求,下載圖片)
1>   從新下載圖片(屢次下載)
2>下載完畢,利用RunLoop的輸入源回到主線程刷新UIImageView(performSelectorOnMainThread)
關於RunLoop
RunLoop從字面上看是運行循環的意思,準確的說是線程中的循環。
有些線程執行的任務是一條直線,起點到終點——-如簡單HelloWorld,運行打印完,它的生命週期便結束了

而另外一些線程要乾的活則是一個圓,不斷循環,直到經過某種方式將它終止。—操做系統,一直運行直到你關機,圓型的線程就是經過run loop不停的循環實現的。

首先循環體的開始須要檢測是否有須要處理的事件,若是有則去處理,若是沒有則進入睡眠以節省CPU時間。 因此重點即是這個須要處理的事件,在RunLoop中,須要處理的事件分兩類,一種是輸入源,一種是定時器,
定時器
好理解就是那些須要定時執行的操做
輸 入源分三類:
performSelector源
基於端口(Mach port)的源
自定義的源。
RunLoop有一個觀察者Observer的概念,能夠往RunLoop中加入本身的 觀察者以便監控着RunLoop的運行過程
 另外RunLoop中還有一個運行模式的概念,每個運行循環必然運行在某個模式下,而模式的存在是爲了過濾事件源和觀察者的,只有那些和當前 RunLoop運行模式一致的事件源和觀察者纔會被激活。


在一個線程中咱們須要作的事情並不單一,如須要處理定時鐘事件,須要處理用戶的觸控事件,須要接受網絡遠端發過來的數據,將這些須要作的事情通通注 冊到事件源中,每一次循環的開始便去檢查這些事件源是否有須要處理的數據,有的話則去處理。 
拿具體的應用舉個例子,NSURLConnection網絡數據請求,默認是異步的方式,其實現原理就是建立以後將其做爲事件源加入到當前的 RunLoop,而等待網絡響應以及網絡數據接受的過程則在一個新建立的獨立的線程中完成,當這個線程處理到某個階段的時候好比獲得對方的響應或者接受完 了網絡數據以後便通知以前的線程去執行其相關的delegate方法。

每個線程都有其對應的RunLoop,可是默認非主線程的RunLoop是沒有運行的,須要爲RunLoop添加至少一個事件源,而後去run它。通常狀況下咱們是沒有必要去啓用線程的RunLoop的,除非你在一個單獨的線程中須要長久的檢測某個事件。
Run loop同時也負責autorelease pool的建立和釋放
在使用手動的內存管理方式的項目中,會常常用到不少自動釋放的對象,若是這些對象不可以被即時釋放掉,會形成內存佔用量急劇增大。Run loop就爲咱們作了這樣的工做,每當一個運行循環結束的時候,它都會釋放一次autorelease pool,同時pool中的全部自動釋放類型變量都會被釋放掉。


Run loop的優勢
一個run loop就是一個事件處理循環,用來不停的監聽和處理輸入事件並將其分配到對應的目標上進行處理。若是僅僅是想實現這個功能,你可能會想一個簡單的while循環不就能夠實現了嗎,用得着費老大勁來作個那麼複雜的機制?顯然,蘋果的架構設計師不是吃乾飯的,你想到的他們早就想過了。
首先,NSRunLoop是一種更加高明的消息處理模式,他就高明在對消息處理過程進行了更好的抽象和封裝,這樣才能使得你不用處理一些很瑣碎很低層次的具體消息的處理,在NSRunLoop中每個消息就被打包在input source或者是timer source(見後文)中了。
其次,也是很重要的一點,使用run loop可使你的線程在有工做的時候工做,沒有工做的時候休眠,這能夠大大節省系統資源。

Run loop相關知識點

Run loop接收輸入事件來自兩種不一樣的來源:輸入源(input source)和定時源(timer source)。兩種源都使用程序的某一特定的處理例程來處理到達的事件。圖-1顯示了run loop的概念結構以及各類源。






 Socket的實現原理及Socket之間是如何通訊的
Socket用於網絡中進程通信
 通常基於TCP/IP,UDP,常連接,時時保持通信(取決於協議)
TCP/IP 【端對端: 一個對一個】比較安全,不會出現丟包現象,只要發了就必定會收到
UDP     【廣播式協議: 一對多】容易出現丟包現象,只管發,無論你收沒收到
長鏈接與短鏈接  
長鏈接 指在一個TCP鏈接上能夠連續發送多個數據包,在TCP鏈接保持期間,若是沒有數據包發送,須要雙方發檢測包以維持此鏈接,通常須要本身作在線維持。 
長鏈接操做過程: 
  鏈接→數據傳輸→保持鏈接(心跳)→數據傳輸→保持鏈接(心跳)→……→關閉鏈接; 
短鏈接 是指通訊雙方有數據交互時,就創建一個TCP鏈接,數據發送完成後,則斷開此TCP鏈接,通常銀行都使用短鏈接。
短鏈接操做步驟是: 
  鏈接→數據傳輸→關閉鏈接;  
何時用長鏈接,短鏈接?
長鏈接多用於操做頻繁,點對點的通信,並且鏈接數不能太多狀況
每一個TCP鏈接都須要三步握手,這須要時間,若是每一個操做都是先鏈接,再操做的話那麼處理速度會下降不少,
因此每一個操做完後都不斷開,下次次處理時直接發送數據包就OK了,不用創建TCP鏈接。

通常銀行都使用短鏈接。

例如:數據庫的鏈接用長鏈接, 
若是用短鏈接頻繁的通訊會形成socket錯誤,並且頻繁的socket 建立也是對資源的浪費。
 http協議的實現 
HTTP的概念: 全稱是Hypertext Transfer Protocol,超文本傳輸協議
(1)規定客戶端和服務器之間的數據傳輸格式
(2)讓客戶端和服務器能有效地進行數據溝通

爲何選擇使用HTTP:
(1)簡單快速  由於HTTP協議簡單,因此HTTP服務器的程序規模小,於是通訊速度很快
(2)靈活  HTTP容許傳輸任意類型的數據
(3)HTTP 0.9和1.0使用非持續鏈接  限制每次鏈接只處理一個請求,服務器對客戶端的請求作出響應後,立刻斷開鏈接,這種方式能夠節省傳輸時間
HTTP的通訊過程
(1)請求:客戶端向服務器索要數據


請求行:包含了請求方法、請求資源路徑、HTTP協議版本
GET /MJServer/resources/images/1.jpg HTTP/1.1


請求頭:包含了對客戶端的環境描述、客戶端請求的主機地址等信息
1.  192.168.1.105:8080 // 客戶端想訪問的服務器主機地址
2. er-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9) Firefox/30.0// 客戶端的類型,客戶端的軟件環境
Accept: text/html, */*// 客戶端所能接收的數據類型
Accept-Language: zh-cn // 客戶端的語言環境
Accept-Encoding: gzip // 客戶端支持的數據壓縮格式
請求體:客戶端發給服務器的具體數據,好比文件數據

(2)響應:服務器返回客戶端相應的數據
狀態行:包含了HTTP協議版本、狀態碼、狀態英文名稱
1. TP/1.1 200 OK
響應頭:包含了對服務器的描述、對返回數據的描述
1. rver: Apache-Coyote/1.1 // 服務器的類型
Content-Type: image/jpeg // 返回數據的類型
1. t-Length: 56811 // 返回數據的長度
2. e: Mon, 23 Jun 2014 12:54:52 GMT // 響應的時間
實體內容:服務器返回給客戶端的具體數據,好比文件數據       

 iOS中發送HTTP請求的方案
在iOS中,常見的發送HTTP請求(GET和POST)的解決方案有
(1)蘋果原生(自帶)
NSURLConnection:用法簡單,最古老最經典最直接的一種方案
NSURLSession:iOS 7新出的技術,功能比NSURLConnection更增強大
CFNetwork:NSURL*的底層,純C語言
(2)第三方框架
ASIHttpRequest:外號「HTTP終結者」,功能極其強大,惋惜早已中止更新
AFNetworking:簡單易用,提供了基本夠用的經常使用功能
ASI和AFN架構對比

說明:AFN基於NSURL,ASI基於CFHTTP,ASI的性能更好一些。



怎麼保證多人開發進行內存泄露的檢查
使用Analyze進行代碼的靜態分析(檢測有無潛在的內存泄露)
經過profile –> leak檢查在程序運行過程當中有無內存泄露     
使用ARC

2.非自動內存管理狀況下怎麼作單例模式.
建立單例設計模式的基本步驟 ·
>聲明一個單例對象的靜態實例,並初始化爲nil。 
• satic Person * Person= nil;
>建立一個類的類工廠方法裏面加鎖實現【能夠用NSLock/ NSCondiction/@synchronized 這裏咱們直接用dispatch_once由於裏面自動加鎖並且只調用一次】
類方法: +(instance)sharePerson;
>重寫allocWithZone:方法和copyWithZone:方法,確保用戶在直接分配和初始化對象時,不會產 生另外一個對象。 
>重寫release、autorelease、retain、retainCount方法, 以此確保單例的狀態。 
具體以下:
#import <foundation foundation.h="">
@interface Singleton : NSObject
+(instancetype) shareInstance ;
@end

#import "Singleton.h"
@implementation Singleton
• atic Singleton* _instance = nil;
+(instancetype) shareInstance
{
    static dispatch_once_t onceToken ;
    dispatch_once(&onceToken, ^{
        _instance = [[super allocWithZone:NULL] init] ;
    }) ;
    return _instance ;
}
+(id) allocWithZone:(struct _NSZone *)zone
{
    return [Singleton shareInstance] ;
}
-(id) copyWithZone:(struct _NSZone *)zone
{
    return [Singleton shareInstance] ;
}
@end

#import <foundation foundation.h="">
#import "Singleton.h"

• t main(int argc, const char * argv[]) {
    @autoreleasepool {

• ngleton* obj1 = [Singleton shareInstance] ;
• Log(@"obj1 = %@.", obj1) ;
• ngleton* obj2 = [Singleton shareInstance] ;
• Log(@"obj2 = %@.", obj2) ;

• ngleton* obj3 = [[Singleton alloc] init] ;
• Log(@"obj3 = %@.", obj3) ;

• ngleton* obj4 = [[Singleton alloc] init] ;
• Log(@"obj4 = %@.", [obj4 copy]) ;
    }
    return 0;
}</foundation>
輸出結果是同樣的,即獲取的對象是同樣的


3.對於類方法(靜態方法)默認是autorelease的。全部類方法都會這樣嗎?
1> 系統自帶的絕大數類方法返回的對象,都是通過autorelease的

4.block在ARC中和MRC中的用法有什麼區別,須要注意什麼
1>無論是ARC和MRC,block都應該用copy操做來持有
2>應注意避免循環引用
ARC: __weak、__unscafe_unretained
MRC:__block

5.什麼狀況下會發生內存泄漏和內存溢出?
1> 內存泄露:該釋放的沒有釋放內存泄露會最終會致使內存溢出!
2>內存溢出:當程序在申請內存時,沒有足夠的內存空間供其使用,出現out of memory;好比申請了一個int,但給它存了long才能存下的數,那就是內存溢出。

6.[NSArray arrayWithobject:<id>] 這個方法添加對象後,須要對這個數組作釋放操做嗎?
    不須要 這個對象被放到自動釋放池中 

7.Json數據的解析,和解析數據的時候有內存泄露嗎?有的話 如何解決        
JSON解析的方案
蘋果原生  NSJSONSerialization (無需導入包,IOS5支持,低版本IOS不支持)
1. NSError *error;
2. //加載一個NSURL對象
3. NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@" http://m.weather.com.cn/data/101180601.html"]];
4. //將請求的url數據放到NSData對象中
5. NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
6. //IOS5自帶解析類NSJSONSerialization從response中解析出數據放到字典中
7. NSDictionary *weatherDic = [NSJSONSerialization JSONObjectWithData:response options:NSJSONReadingMutableLeaves error:&error];


第三方【TouchJson、 SBJson 、JSONKit】
TouchJson (需導入包:#import 「TouchJson/JSON/CJSONDeserializer.h")

1. //獲取API接口
2. NSURL *url = [NSURL URLWithString:@" http://m.weather.com.cn/data/101010100.html"];
3. //定義一個NSError對象,用於捕獲錯誤信息
4. NSError *error;          NSString *jsonString = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:&error];
5. //將解析獲得的內容存放字典中,編碼格式爲UTF8,防止取值的時候發生亂碼
6. NSDictionary *rootDic = [[CJSONDeserializer deserializer] deserialize:[jsonString dataUsingEncoding:NSUTF8StringEncoding] error:&error];
7. //由於返回的Json文件有兩層,去第二層內容放到字典中去
8. NSDictionary *weatherInfo = [rootDic objectForKey:@"weatherinfo"];
9. NSLog(@"weatherInfo--->%@",weatherInfo);
10. //取值打印
11. txtView.text = [NSString stringWithFormat:@"今天是 %@  %@  %@  的天氣情況是:%@  %@ ",[weatherInfo objectForKey:@"date_y"],[weatherInfo objectForKey:@"week"],[weatherInfo objectForKey:@"city"], [weatherInfo objectForKey:@"weather1"], [weatherInfo objectForKey:@"temp1"]];
    14          
SBJson  (需導入包:#import "SBJson/SBJson.h")
1. NSURL *url = [NSURL URLWithString:@" http://m.weather.com.cn/data/101180701.html"];
2. NSError *error = nil;
3. NSString *jsonString = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:&error];
4. SBJsonParser *parser = [[SBJsonParser alloc] init];
    5          
1. NSDictionary *rootDic = [parser objectWithString:jsonString error:&error];
2. NSDictionary *weatherInfo = [rootDic objectForKey:@"weatherinfo"];
3. txtView.text = [NSString stringWithFormat:@"今天是 %@  %@  %@  的天氣情況是:%@  %@ ",[weatherInfo objectForKey:@"date_y"],[weatherInfo objectForKey:@"week"],[weatherInfo objectForKey:@"city"], [weatherInfo objectForKey:@"weather1"], [weatherInfo objectForKey:@"temp1"]];
4. }
JSONKit 不支持ARC(需導入包:#import 「JSONKit/JSONKit.h")
1. //若是json是「單層」的,即value都是字符串、數字,可使用objectFromJSONString
2. NSString *json1 = @"{\"a\":123, \"b\":\"abc\"}";
1. Dictionary *data1 = [json1 objectFromJSONString];

    //若是json有嵌套,即value裏有array、object,若是再使用objectFromJSONString,程序可能會報錯(測試結果代表:使用由網絡或獲得的php/json_encode生成的json時會報錯,但使用NSString定義的json字符串時,解析成功),最好使用objectFromJSONStringWithParseOptions:  
1. String *json2 = @"{\"a\":123, \"b\":\"abc\", \"c\":[456, \"hello\"], \"d\":{\"name\":\"張三\", \"age\":\"32\"}}";

1. Dictionary *data2 = [json2 objectFromJSONStringWithParseOptions:JKParseOptionLooseUnicode];
    // 記住釋放用來保存解析後數據的數組
1. son2 release];

1. 自動釋放池底層怎麼實現
自動釋放池以棧的形式實現:當你建立一個新的自動釋放池時,它將被添加到棧頂。當一個對象收到發送autorelease消息時,它被添加到當前線程的處於棧頂的自動釋放池中,當自動釋放池被回收時,它們從棧中被刪除, 而且會給池子裏面全部的對象都會作一次release操做.
自動釋放池何時會進行回收:在那個大括號執行完畢就會釋放回收


KVO內部實現原理
KVO是基於runtime機制實現的
當某個類的對象第一次被觀察時, 系統就會在運行期動態地建立該類的一個派生類【就是子類】,在這個派生類中重寫基類中任何被觀察屬性的 setter 方法。 
 NSKVONotifying_Person)◊派生類在被重寫的 setter 方法實現真正的通知機制(Person


上圖中的NSKVONotifitying_Person就是動態建立的派生類


是否能夠把比較耗時的操做放在NSNotificationCenter中
若是在異步線程發的通知,那麼能夠執行比較耗時的操做;
若是在主線程發的通知,那麼就不能夠執行比較耗時的操做

3.Foundation對象與Core Foundation對象有什麼區別
1> Foundation對象是OC的,Core Foundation對象是C對象
2> Foundation對象和Core Foundation對象是能夠互相轉換的,數據類型之間的轉換
ARC:__bridge_retained、__bridge_transfer
非ARC: __bridge

4.不用中間變量,用兩種方法交換A和B的值
A = A + B
• = A - B
• = A - B
或者
A = A^B;
B = A^B;
A = A^B;

6.什麼是動態,舉例說明
1> 在程序運行過程才執行的操做
2>動態綁定    
3>runtime

7.runtime實現的機制是什麼,怎麼用,通常用於幹嗎. 你還能記得你所使用的相關的頭文件或者某些方法的名稱嗎? 
做用
獲取類裏面的全部成員變量【歸檔】
爲類動態添加成員變量,
動態改變類的方法實現,
爲類動態添加新的方法等 
須要導入<objc/message.h><objc/runtime.h>
runtime,運行時機制,它是一套C語言庫
• OC代碼,最終都是轉成了runtime庫的東西,好比類轉成告終構體等數據類型,方法轉成函數,平時調方法都是轉成了objc_msgSend函數(因此說OC有個消息發送機制)[p setName:]; --- > objc_msgSend(p, selector(setName:),);
• 拿到全部成員變量,進行歸檔。Class_copyIvarList([Person class], &count)
• swizzel;  imageWithName,裏面判斷若是是iOS7,在name圖片名後拼接「_os7」,而後image = [UIImage  ImageName:name];不是iOS7,直接image = [UIImage  ImageName:name];返回image便可;可是若是沒有用分類方法處理圖片,要麼一個一個換成ImageWithName,要麼swizzle將ImageName方法的實現換成IamgeWithName;表面上調用ImageNamed, 實際上用的ImageWithName。
2.爲了不數組不能存nil.給可變數組(Foundation)弄個分類
也能夠若是是字符串再添加,避免數組越界;換objectAtIndex;
總結:


CoreText 【就是富文本—用NSAttributedString這個類來作富文本】
隨意修改文本的樣式
圖文混排(純C語言)
國外:Niumb
Core Image(濾鏡處理)
• 能調節圖片的各類屬性(飽和度, 色溫, 色差等) 美圖秀秀用到這個

9.NSNotification和KVO的區別和用法是什麼?
何時應該使用通知,何時應該使用KVO,它們的實現上有什麼區別嗎?若是用protocol和delegate(或者delegate的Array)來實現相似的功能可能嗎?若是可能,會有什麼潛在的問題?若是不能,爲何?(雖然protocol和delegate這種東西面試已經面爛了…)
通知比較靈活(1個通知能被多個對象接收, 1個對象能接收多個通知), 

代理比較規範,可是代碼多(默認是1對1)可是也能有多個代理,就是讓代理都遵照同一份協議

KVO性能很差(底層會動態產生新的類),只能監聽某個對象屬性的改變, 不推薦使用(1個對象的屬性能被多個對象監聽,  1個對象能監聽多個對象的其餘屬性)

更詳細參考:
http://blog.csdn.net/dqjyong/article/details/7685933

談談你對KVC 與 KVO 理解
KVC,便是指 NSKeyValueCoding,一個非正式的 Protocol,提供一種機制來間接訪問對象的屬性。KVO 就是基於 KVC 實現的關鍵技術之一。

KVC 運用的技術
• C運用了一個isa- swizzling技術。isa-swizzling就是類型混合指針機制。KVC主要經過isa- swizzling,來實現其內部查找定位的。
isa指針,如其名稱所指,(就是is a kind of的意思),指向維護分發表的對象的類。該分發表實際上包含了指向實現類中的方法的指針,和其它數據。
KVC實例:
一個對象擁有某些屬性。好比說,一個 Person 對象有一個 name 和一個 address 屬性。以 KVC 說法,Person 對象分別有一個 value 對應他的 name 和 address 的 key。 key 只是一個字符串,它對應的值能夠是任意類型的對象。從最基礎的層次上看,KVC 有兩個方法:一個是設置 key 的值,另外一個是獲取 key 的值。以下面的例子
void changeName(Person *p, NSString *newName)
{

    // using the KVC accessor (getter) method
    NSString *originalName = [p valueForKey:@"name"];

    // using the KVC  accessor (setter) method.
    [p setValue:newName forKey:@"name"];

    NSLog(@"Changed %@'s name to: %@", originalName, newName);

}
如今,若是 Person 有另一個 key 配偶(spouse),spouse 的 key 值是另外一個 Person 對象,用 KVC 能夠這樣寫:


void logMarriage(Person *p)
{

    // just using the accessor again, same as example above
    NSString *personsName = [p valueForKey:@"name"];

    // this line is different, because it is using
    // a "key path" instead of a normal "key"
    NSString *spousesName = [p valueForKeyPath:@" spouse.name"];

    NSLog(@"%@ is happily married to %@", personsName, spousesName);

}
key 與 key path 要區分開來,key 能夠從一個對象中獲取值,而 key path 能夠將多個 key 用點號 「.」 分割鏈接起來,好比:
[p valueForKeyPath:@" spouse.name"];
至關於這樣……
[[p valueForKey:@"spouse"] valueForKey:@"name"];

Key-Value Observing (KVO) 創建在 KVC 之上,它可以觀察一個對象的 KVC key path 值的變化。
優勢 
當 有屬性改變,KVO會提供自動的消息通知。這樣的架構有不少好處。首先,開發人員不須要本身去實現這樣的方案:每次屬性改變了就發送消息通知。這是KVO機制提供的最大的優勢。由於這個方案已經被明肯定義,得到框架級支持,能夠方便地採用。開發人員不須要添加任何代碼,不須要設計本身的觀察者模型,直接能夠在工程裏使用。其次,KVO的架構很是的強大,能夠很容易的支持多個觀察者觀察同一個屬性,以及相關的值。
使用方法
1. 註冊,指定被觀察者的屬性
2. 實現回調方法
3. 移除觀察
注意
只有符合KVC標準的對象才能使用kvo
KVO實例:
假設一個場景,股票的價格顯示在當前屏幕上,當股票價格更改的時候,實時顯示更新其價格。
1.定義DataModel,

1. @interface StockData : NSObject {
2.     NSString * stockName;
3. float price;
4. }
5. @end
6. @implementation StockData
7. @end

2.定義此model爲Controller的屬性,實例化它,監聽它的屬性,並顯示在當前的View裏邊
[cpp] view plaincopy

• - (void)viewDidLoad
• {
• [super viewDidLoad];
    4      
1. stockForKVO = [[StockData alloc] init];
2. [stockForKVO setValue:@"searph" forKey:@"stockName"];
3. [stockForKVO setValue:@"10.0" forKey:@"price"];
4. [stockForKVO addObserver:self forKeyPath:@"price" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:NULL];
    9      
1. myLabel = [[UILabel alloc]initWithFrame:CGRectMake(100, 100, 100, 30 )];
2. myLabel.textColor = [UIColor redColor];
3. myLabel.text = [stockForKVO valueForKey:@"price"];
4. [self.view addSubview:myLabel];
    14         
•         UIButton * b = [UIButton buttonWithType:UIButtonTypeRoundedRect];
• b.frame = CGRectMake(0, 0, 100, 30);
• [b addTarget:self action:@selector(buttonAction) forControlEvents:UIControlEventTouchUpInside];
• [self.view addSubview:b];
    19      
1. }

3.當點擊button的時候,調用buttonAction方法,修改對象的屬性

[cpp] view plaincopy

1. -(void) buttonAction
2. {
3. [stockForKVO setValue:@"20.0" forKey:@"price"];
4. }

1. 實現回調方法
[cpp] view plaincopy

1. -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
2. {
3. if([keyPath isEqualToString:@"price"])
4. {
5. myLabel.text = [stockForKVO valueForKey:@"price"];
6. }
7. }

5.增長觀察與取消觀察是成對出現的,因此須要在最後的時候,移除觀察者

• - (void)dealloc
• {
• [super dealloc];
• [stockForKVO removeObserver:self forKeyPath:@"price"];
• [stockForKVO release];
• }

KVB:Key Value Binding  鍵值綁定【補充內容】
KVB實現的兩個基本方法
• 爲對象添加觀察者OBserver  --  addObserver:forKeyPath:options:context:
• )觀察者OBserver收到信息的處理函數 -- observerValueForKeyPath:ofObject:change:context:

KVO和KVB最明顯的使用場景就是在一些界面實現變化很強的敵方。例如股票走向、售票餘數等,可及時更改參數變化狀況。





CAAnimation的層級結構

若是使用CAAnimation
建立CAAnimation對象
設置CAAnimation對象的屬性
添加CAAnimation對象到CALayer上,CALayer就會自動執行這個動畫

UIButton與UITableView的層級結構
層級結構  label  UIImage  NSObjcet->UIResponder->UIView->UIControl->UIButton
內部的子控件結構    cell 分割線  UIView->UIScrollView>UITableView
  設置scroll view的contensize能在Viewdidload裏設置麼,爲何
1. ,可能不太安全。子控制器的frame在viewDidLoad和ViewWillAppear時可能不同,若是scrollView的contentSize = 375 是基於子控制器的View(等於),當子控制器變小時,contentSize就變小了。




按鈕或者其它UIView控件的事件傳遞的具體過程

UIResponder有一個nextResponder屬性,經過該屬性能夠組成一個響應者鏈,事件或消息在其路徑上進行傳遞
若是UIResponder沒有處理傳給它的事件,會將未處理的消息轉發給本身的nextResponder




控制器View的生命週期及相關函數是什麼?你在開發中是如何用的?
• 1.首先判斷控制器是否有視圖,若是沒有就調用loadView方法建立:經過storyboard或者代碼;
• 2.隨後調用viewDidLoad,能夠進行下一步的初始化操做;只會被調用一次;
• 3.在視圖顯示以前調用viewWillAppear;該函數能夠屢次調用;
• 4.視圖viewDidAppear

• 3.在視圖顯示以前調用viewWillDisappear;該函數能夠屢次調用;
如須要);
• 5.在佈局變化先後,調用viewWill/DidLayoutSubviews處理相關信息;
6.viewWillDisappear ViewDidDisappear   
8.父子關係  
1.控制器 子控制器調用navigationController 會看一下當前控制器是否在一個導航控制器裏面,在就把這個導航控制器拿過來,沒有就看一下父控制器是否在導航控制器裏,再拿來
2.旋轉屏幕默認只有window的rootViewController纔會旋轉,只有具有父子關係,子控制器纔會觸發旋轉方法。
1. NSRunLoop的實現機制,及在多線程中如何使用

NSRunLoop是IOS消息機制的處理模式
>做用:控制NSRunLoop裏面線程的執行和休眠,
>NSRunLoop 就是一直在循環檢測,從線程start到線程end,檢測inputsource(如點擊,雙擊等操做)異步事件,檢測timesource同步事件,檢測到輸入源會執行處理函數,首先會產生通知,core function向線程添加runloop observers來監聽事件,意在監聽事件發生時來作處理。
>3.runloopmode是一個集合,包括監聽:事件源,定時器,以及需通知的runloop observers

1.  只有在爲你的程序建立次線程的時候,才須要運行run loop。對於程序的主線程而言,run loop是關鍵部分。Cocoa提供了運行主線程run loop的代碼同時也會自動運行run loop。IOS程序UIApplication中的run方法在程序正常啓動的時候就會啓動run loop。若是你使用xcode提供的模板建立的程序,那你永遠不須要本身去啓動run loop
2.  在多線程中,你須要判斷是否須要run loop。若是須要run loop,那麼你要負責配置run loop並啓動。你不須要在任何狀況下都去啓動run loop。好比,你使用線程去處理一個預先定義好的耗時極長的任務時,你就能夠毋需啓動run loop。Run loop只在你要和線程有交互時才須要


3簡單說一下APP的啓動過程,從main文件開始提及
    程序啓動分爲兩類:1.有storyboard 2.沒有storyboard
有storyboard狀況下:
1.main函數
2.UIApplicationMain
• 建立UIApplication對象
• 建立UIApplication的delegate對象
3.根據Info.plist得到最主要storyboard的文件名,加載最主要的storyboard(有storyboard)
• 建立UIWindow
• 建立和設置UIWindow的rootViewController
• 顯示窗口

沒有storyboard狀況下:
1.main函數
2.UIApplicationMain
• 建立UIApplication對象
• 建立UIApplication的delegate對象
3.delegate對象開始處理(監聽)系統事件(沒有storyboard)
• 程序啓動完畢的時候, 就會調用代理的application:didFinishLaunchingWithOptions:方法
• 在application:didFinishLaunchingWithOptions:中建立UIWindow
• 建立和設置UIWindow的rootViewController
• 顯示窗口

4把程序本身關掉和程序進入後臺,遠程推送的區別
1. 關掉後不執行任何代碼, 不能處理事件
2. 應用程序進入後臺狀態不久後轉入掛起狀態。在這種狀態下,應用程序不執行任何代碼,並有可能在任意時候從內存中刪除。只有當用戶再次運行此應用,應用纔會從掛起狀態喚醒,代碼得以繼續執行
3.或者進入後臺時開啓多任務狀態,保留在內存中,這樣就能夠執行系統容許的動做
4.遠程推送是由遠程服務器上的程序發送到APNS,再由APNS把消息推送至設備上的程序,當應用程序收到推送的消息會自動調用特定的方法執行事先寫好的代碼
5(void)application:(UIApplication*)application   didReceiveRemoteNotification:(NSDictionary*)userInfo 

{// alert   // 前臺
 
if (application.applicationState == UIApplicationStateActive) { 

        UILocalNotification *notification=[[UILocalNotification alloc] init]; 
        
if(notification!=nil){ 
NSDate*date=[NSDate dateWithTimeIntervalSinceNow:10]; 


         notification.fireDate=date ; 
          
notification.timeZone=[NSTimeZone defaultTimeZone];
           
notification.alertBody= [[userInfo objectForKey:@"aps"] objectForKey:@"alert"]; 

notification.soundName= UILocalNotificationDefaultSoundName;  

notification.userInfo = userInfo;

[[UIApplicationsharedApplication] scheduleLocalNotification:notification]; 
[self playSound]; 



5本地通知和遠程推送通知對基本概念和用法?





鍵盤呼出時的通知

  // 註冊通知
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textChange) name:UITextViewTextDidChangeNotification object:textView];
       // 監聽鍵盤的彈出的隱藏
    // 監聽鍵盤彈出和退下
    [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
    [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
-(void)keyboardWillShow:(NSNotification *)noti
{
    // 取出鍵盤彈出的時間
    CGFloat duration = [noti.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];

    // 取出鍵盤高度
    CGRect keyBoardRect = [noti.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
    CGFloat keyBoardHeight = keyBoardRect.size.height;

1. IView animateWithDuration:duration delay:0.0 options:7 << 16 animations:^{
        self.toolBar.transform = CGAffineTransformMakeTranslation(0, -keyBoardHeight);

    } completion:^(BOOL finished) {

    }];

}

-(void)keyboardWillHide:(NSNotification *)noti
{
    // 取出鍵盤隱藏的時間
    CGFloat duration = [noti.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
    // 清空transform
    [UIView animateWithDuration:duration animations:^{
        self.toolBar.transform = CGAffineTransformIdentity;
    }];

1. IView animateWithDuration:duration delay:0.0 options:7 << 16 animations:^{
         self.toolBar.transform = CGAffineTransformIdentity;

    } completion:^(BOOL finished) {

    }];

}

copy、retain、assign、strong、weak怎樣用,如何區別,原子性和非原子性的區別
 聲明property的語法爲:@property (參數1,參數2) 類型 名字;

其中參數主要分爲三類:

讀寫屬性: (readwrite/readonly)
setter語意:(assign/retain/copy)
原子性: (atomicity/nonatomic)

各參數意義以下:

readwrite: 產生setter\getter方法
readonly: 只產生簡單的getter,沒有setter。
assign: 默認類型,setter方法直接賦值,而不進行retain操做  通常基本數據類型用該屬性聲明,好比,int, BOOL。
retain: setter方法對參數進行release舊值,再retain新值。 該屬性與 strong 一致;只是可讀性更強一些。
copy: setter方法進行Copy操做,與retain同樣        與 strong 的區別是聲明變量是拷貝對象的持有者。
nonatomic: 禁止多線程,變量保護,提升性能
weak:該屬性與 strong 一致;只是可讀性更強一些。

若是使用多線程,有時會出現兩個線程互相等待對方致使鎖死的狀況(在沒有(nonatomic)的狀況下,即默認(atomic),會防止這種線程互斥出現,可是會消耗必定的資源。因此若是不是多線程的程序,打上(nonatomic)便可

十、block寫一個方法,該方法能夠快速查找到離某個視圖最近的父視圖
十二、代理爲何要用weak
防止循環引用
在MRC的時候是用assign來修飾,在ARC以後用
unsafe_unretained,做用是跟weak相似的。主要是爲了防止循環引用。好比A引用了B,B引用了C,C又引用了A,這樣循環引用以後,若是用strong強引用來修飾,這個代理就永遠釋放不掉了。
1四、pickerView的使用
和tableView差很少  記得遵照協議和代理
//數據源的代理方法
-(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView//返回顯示的列數  
-(NSInteger) pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component //返回當前列顯示的行數 
//代理方法
-(NSString*)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
//返回當前行的內容,此處是將數組中數值添加到滾動的那個顯示欄上
1五、極光推送(JPUSH)的使用流程及原理

1. ush iOS Push 包括 2 個部分,APNs 推送(代理),與 JPush 應用內消息。
紅色部分是 APNs 推送,JPush 代理開發者的應用(須要基於開發者提供的應用證書),向蘋果 APNs 服務器推送。由 APNs Server 推送到 iOS 設備上。
藍色部分是 JPush 應用內推送部分,即 App 啓動時,內嵌的 JPush SDK 會開啓長鏈接到 JPush Server,從而 JPush Server 能夠推送消息到 App 裏。
應用內消息
應用內消息:JPush iOS SDK 提供的應用內消息功能,在 App 在前臺時可以收到推送下來的消息。App 可以使用此功能來作消息下發動做。
此消息不通過 APNs 服務器,徹底由 JPush 提供功能支持。



JPush APNs 有神魔用
iOS 平臺上,只有 APNs 這個官方的推送通道,是能夠隨時送達的。通常開發者都是本身部署應用服務器向 APNs Server 推送。
JPush APNs 作推送代理,其意義又在哪裏呢?JPush APNs 相比直接向 APNs 推送有什麼好處呢?
    •    減小開發及維護成本:
    ◦    應用開發者不須要去開發維護本身的推送服務器與 APNs 對接。
    ◦    集成了 JPush iOS SDK 後沒必要本身維護更新 device token。
    ◦    經過 JPush 的 Web Portal 直接推送,也能夠調用JPush的 HTTP 協議 API 來完成,開發工做量大大減小。
    •    減小運營成本:
    ◦    極光推送支持一次推送,同時向 Android, iOS, WinPhone 三個平臺。支持統一的 API 與推送界面。
    ◦    極光推送提供標籤、別名綁定機制,以及提供了很是細分的用戶分羣方式,運營起來很是簡單、直觀。
    •    提供應用內推送:
    ◦    除了使得 APNs 推送更簡單,也另外提供應用內消息推送。這在相似於聊天的場景裏頗有必要。




1六、MJExtion如何使用,若是寫的model裏有這個屬性,後臺數據沒有,程序會不會崩
MJExtension很強大,幾乎支持現有全部的模型、字典、json數據轉換,並且效率很是高
MJExtension很是好用可是容易被忽略的功能:無論你的模型屬性有幾百個,只須要加一句宏MJCodingImplementation,就能實現歸檔解檔,不用再編寫噁心的encodeWithCoder:和initWithCoder:了
經過plist來建立一個模型
1.( filename 文件名(僅限於mainBundle中的文件)
(instancetype)objectWithFilename:(NSString *)filename;
2.(file 文件全路徑)
+(instancetype)objectWithFile:(NSString *)file;
經過字典數組來建立一個模型數組
(NSMutableArray *)objectArrayWithKeyValuesArray:(id)keyValuesArray;


1九、如何改變代碼塊兒裏的值  

2二、深拷貝和淺拷貝的區別,如何實現深拷貝
淺拷貝    只是對指針的拷貝,拷貝後兩個指針指向同一個內存空間
深拷貝    不但對指針進行拷貝,並且對指針指向的內容進行拷貝,經深拷貝後的指針是指向兩個不一樣地址的指針
2四、經常使用的第三方框架,他們解決了哪些問題
       1.AFNetworking
       2.MBProgressHUD
       3.MJExtension
       4.MJRefresh
       5.SDWebImage
       6.UMSocial_sdk<友盟分享>

2五、ios開發傳值方式有哪些
       1.設置委託
        2.extern   @interface以前定義extern NSString *strZhi;
        3.對象的property屬性傳值
          4.方法的參數傳值
          5.靜態方法傳值
          6.用給 指向 指針的指針 賦值 的方式傳值
          7.NSNotification (觀察者模式)
          8.單例
1. 3 NSUserDefaults
 .h
#define myAvgcost @"myavgcost"
.m
[[NSUserDefaults standardUserDefaults] setObject:p_Avgcost_arr forKey:myAvgcost];//寫道磁盤
傳到另外一個類
NSArry *myAvgcost_arr=[[NSUserDefaults standardUserDefaults] arrayForKey:myAvgcost];
          10.delegate
              主要是要把共享的數據設置爲XXDelegate的一個成員變量;
              而後在須要的地方經過以下方法得到一個XXDelegate的對象,以下:
              XXDelegate*app = (XXDelegate *) [[UIApplicationsharedApplication] delegate];
              每次獲取delegate並非建立一個新app,每一個app只有一個delegate。



2六、ios怎麼作到性能優化


30、介紹一下MVC以及動態方法和靜態方法的區別
 1.靜態的方法在整個應用程序其間存儲在內存中,速度快,但佔用內存. 
  2.動態的方法在先聲明類實例才能調用類中的方法
   3.通常使用頻繁的方法用靜態方法,用的少的方法用動態的。靜態的速度快,佔內存。動態的速度相對慢些,但調用完後,當即釋放類,能夠節省內存,
4.靜態方法主要的問題就是數據同步的問題。若是你的靜態方法的類中不保存私有變量那麼什麼問題都不會有的。最好是包要操做的數據所有以參數的方式傳到方法中去
1. 靜態方法是類方法,調用時不須要建立類實例。
2. 靜態方法是靜態綁定到子類,不是被繼承
7.從面向對象的角度來看: 
靜態方法面向的是類的操做,而實力方法面向的是對象.
8.靜態方法修改的是類的狀態,而對象修改的是各個對象的狀態,這點也是它們重要的區別

9.類的實例化調用是在類的生命週期中存在,當類沒有了之後,對應的實例也就沒有了,對應的方法也就沒有了,靜態類否則,只要你引用了那個靜態類的命名空間,他就會一直存在,直到你退出系統。

3一、談談MVC在CocoaTouch中的實現

 M-Model(模型)是應用系統中與視圖對應部分的數據;
V-View(視圖)是應用系統中用戶看到並與之交互的界面;
C-Controller(控制器)在應用系統中起到控制器做用,用來接受用戶事件、顯示數據、與視圖進行交互等。

3二、有兩個字符串@「hello」,@「world」你有幾種方法將它倆拼接在一塊兒

//方法1.
1. ring = [NSString initWithFormat:@"%@,%@", string1, string2 ];
//方法2.
1. ring = [string1 stringByAppendingString:string2];
2. 方法3 .
string = [string stringByAppendingFormat:@"%@,%@",string1, string2];
//截取字符串
• (NSString *)substringFromIndex:(NSUInteger)from;
• (NSString *)substringToIndex:(NSUInteger)to;
• (NSString *)substringWithRange:(NSRange)range;
3三、一個列表有足夠多得顯示區域,滑動了一下,如何判斷是向上滑動仍是向下滑動。
偏移量
• (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
    oldY = scrollView.contentOffset.y;
}

• (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
   if( scrollView.contentOffset.y > oldY) {
  向下
}else{
向上

3四、有這樣一段json數據{「title」:「null」},轉成字典以後將title對應的value賦值在一個label.text上,會出現什麼問題


3五、請簡單描述一下ios中的KVO實現方式

3六、如何判斷一個字典中是否含有某個key
       1.for in   2.遍歷器  3.dictionary.allkeys  containt 
3七、屬性readwrite,readonly,assign,copy,nonatomic各是什麼做用?在哪些狀況下用

3八、OC建立線程的方法是什麼?若是在主線程中執行代碼,方法是什麼?若是想演示執行代碼,方法又是什麼

3九、#import,# include@class有什麼區別?

40、OC中書寫一個單例模式,使用GCD書寫單例

4一、說明weak與_weak的做用及經常使用在何時


4六、通知跟代理的區別分別寫一個通知及代理





//自我發揮
1.是否有本身的設備
2.作過什麼項目
3.參與整個項目開發的有多少人,除了跟本身的團隊溝通,有跟後臺溝經過麼
相關文章
相關標籤/搜索