1,NSObject中description屬性的意義,它可以重寫嗎?
答案:
每當 NSLog(@"")函數中出現 %@ 時,都會調用description函數,所以通過重寫 description 函數可以很好輸出的制定特殊的格式。
打印自定義對象會輸出對象的名稱和地址,這時候自定義description方法
+description方法決定了類對象的輸出結果,即類本身
-description方法決定了實例對象的輸出結果,即類創建的對象
2,寫一個Objective-C實現單例模式的簡單例子(注意多線程訪問的問題)
簡述@synchronized(self){}的作用
答案:
單例設計模式:節約內存開銷,保證整個應用程序只使用一份資源(大家訪問的數據都是一致的),工具類設計成單例模式
思路:
聲明一個單件對象的靜態實例,并初始化為nil。
創建一個類的類工廠方法,當且僅當這個類的實例為nil時生成一個該類的實例
實現NScopying協議, 覆蓋allocWithZone:方法,確保用戶在直接分配和初始化對象時,不會產生另一個對象。
覆蓋release、autorelease、retain、retainCount方法, 以此確保單例的狀態。
在多線程的環境中,注意使用@synchronized關鍵字或GCD,確保靜態實例被正確的創建和初始化(防止多線程搶奪資源)
代碼:
// 用來保存唯一的單例對象
static id _instace;
(id)allocWithZone:(struct _NSZone *)zone
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instace = [super allocWithZone:zone];
});
return _instace;
}(instancetype)sharedDataTool
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instace = [[self alloc] init];
});
return _instace;
}
(id)copyWithZone:(NSZone *)zone
{
return _instace;
}(oneway void)release { }
(id)retain { return self; }
(NSUInteger)retainCount { return 1;}
(id)autorelease { return self;}
為了保證線程的安全(避免多線程搶奪同一份資源),用@synchronized來加鎖,或者用GCD
3,為NSString擴展一個方法,方法能判斷字符串是否是Url地址(即判斷字符串是否以“http://”),返回BOOL值類型
答案:
- (BOOL)isUrl:(NSString *)string {
if([string hasPrefix:@"http://"]){
return YES;
}else{
return NO;
}
}
4,protocol的定義,實例
答案:
@protocol HKViewControllerDelegate <NSObject>
@optional
@required
@end
@interface HKViewController : UIViewController
@property (nonatomic, weak) id<HKViewControllerDelegate> delegate;
@end
實例:最常用的UITableView
5,定義一個Block并寫一個應用例子,如果對變量加上__block的表示,有什么意義。
答案:
block用來保存一段代碼。是指向結構體的指針,編譯器會把block存放的代碼生成對應的函數,通過指針能訪問函數。
定義:
__block:防止循環retain,用在非ARC
block在ARC用strong,在MRC用copy
block的使用場景:
1.把block保存到對象中去,等到恰當的時機再使用(外部調用),可以用來傳值。
2.把block當成方法的參數使用,外部不調用,外部只是實現,函數內部調用
3.block作為返回值
鏈式編程思想:把要操作的值當成block的參數,block的返回值是方法調用者本身
6,這段代碼有問題嗎?
for (int i = 0; i < someLargeNumber; i++)
{
NSString *string =@"Abc";
string = [string lowercaseString];
string = [string stringByAppendingString:@"xyz"];
NSLog(@"%@", string);
}
答案:
問題出在每執行一次循環,就會有一個string加到當前NSRunloop中的自動釋放池中,只有當自動釋放池被release的時候,自動釋放池中的標示了autorelease的這些數據所占用的內存空間才能被釋放掉。假設,當someLargeNumber大到一定程度時,內存空間將被耗盡而沒有被釋放掉,所以就出現了內存溢出的現象。
目前的解決方法就是在循環里面加個自動釋放池
for (int i = 0; i < someLargeNumber; i++)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSString *string =@"Abc";
string = [string lowercaseString];
string = [string stringByAppendingString:@"xyz"];
NSLog(@"%@", string);
[pool release];
}
7,self.name = "object"和name = "object"有何不同?
答案:
區別是前者會調用setName方法,后者只是賦值。
- (void)setName:(NSString*)newName
{
[newName retain];
[name relase];
name=newName;
}
8,category和inheritance的區別?
答案:
category 可以在不獲悉,不改變原來代碼的情況下往里面添加新的方法,只能添加,不能刪除修改。并且如果類別和原來類中的方法產生名稱沖突,則類別將覆蓋原來的方法,因為類別具有更高的優先級。
category的好處(1)將類的實現分散到多個不同文件或多個不同框架中。(2)創建對私有方法的前向引用。 (3)向對象添加非正式協議。
inheritance可以增加,修改或者刪除方法,并且可以增加屬性。
9,代理的作用?
答案:
代理的目的是改變或傳遞控制鏈。允許一個類在某些特定時刻通知到其他類,而不需要獲取到那些類的指針。可以減少框架復雜度。另外一點,代理可以理解為java中的回調監聽機制的一種類似。
10,消息推送(本地推送,遠程推送)?
答案:
遠程通知的幾種展現形式:橫幅,提醒,鎖屏,app數字圖標(在設置里面設置,還可以播放音效)。安卓不能開關(垃圾!)
程序在前臺,推送給不呈現;點擊通知,打開app
長連接的作用:時間校準,系統升級,傳輸速度快
deviceToken = 手機的UDID + APP的BundleID
遠程推送(APNs):設備聯網之后把UDID和app的BundleID發給蘋果的服務器,蘋果的服務器加密之后返回給一個deviceToken。設備把deviceToken發給應用程序的服務器,服務器把用戶的信息和deviceToken存儲到數據庫。別的用戶給之前的用戶發送消息的時候,先在數據庫中查找用戶的deviceToken,然后把deviceToken和消息體發送到蘋果的服務器,然后推動給用戶。
11,多態,動態類型和動態綁定。
答案:
不同對象以自己的方式響應相同的消息的能力叫做多態。
向下轉型之前一定要先做向上轉型,正確的做法是:
Person p = new Man(); //先將Man的實例向上轉型成Person的實例(向上轉型)
Man man = (Man)p; //將被轉型來的p實例進行強制轉換成Man的實例man(向下轉型)
動態綁定
在objective-c中,
一個對象是否調用指定的方法不是由編譯器決定而是由運行時決定,這被稱作是方法的動態綁定。在objective-c里,對象不調用方法,而是接收消息,消息表達式為:[reciver message];運行時系統首先確定接收者的類型(動態類型識別),然后根據消息名在類的方法列表里選擇相依的方法執行,所以在源代碼里消息也稱為選擇器(selector)
消息函數的作用:
– 首先通過第一個參數的receiver,找到它的isa指針,然后在isa指向的Class對象中使用第二個參數selector查找方法;
– 如果沒有找到,就使用當前Class 對象中的新的isa 指針 到上一級的父類的Class 對象中查找;
– 當找到方法后,再依據receiver的中的self 指針找到當前 的對象,調用當前對象的具體實現的方法(IMP),然后傳遞參數,調用實現方法。
– 假如一直找到NSObject的Class 對象,也沒有找到你調用的方法,就會報告不能識別發送消息的錯誤。
動態加載:運行時加載新類
在運行時創建一個新類,只需要3步:
1、為 class pair分配存儲空間 ,使用 objc_allocateClassPair函數
2、增加需要的方法使用class_addMethod函數,增加實 例變量用class_addIvar
3 、用objc_registerClassPair函數注冊這個類,以便它能被別人使用。
注意:使用這些函數請引#import <objc/runtime.h>
12,事件傳遞鏈和響應者鏈
事件傳遞鏈:
用戶的觸摸事件首先會由系統截獲,進行包裝處理等。
然后遞歸遍歷所有的view,先看子控件能不能接收事件,在看點在不在子控件上面。
然后進行碰觸測試(hitTest),直到找到可以處理事件的view。
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event; // recursively calls -pointInside:withEvent:. point is in the receiver's coordinate system
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event; // default returns YES if point is in bounds
大致的過程application –> window –> root view –>……–>lowest view
響應者鏈:
1,事件響應者鏈是有多個響應者對象組成的鏈條(響應者對象是能處理事件的對象)
2,利用響應者鏈條,可以讓多個響應者對象處理同一個事件,
3,怎么利用鏈條向上傳遞,要尋找上一個響應者
>>如果當前的view是控制器的view,控制器就是上一個響應者
>>如果當前的view不是控制器的view,這個view的父view就是上一個響應者
當有view能夠處理觸摸事件后,開始響應事件。
系統會調用view的以下方法:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;
可以多對象共同響應事件。只需要在以上方法重載中調用super的方法。
大致的過程initial view –> super view –> …..–> view controller –> window –> Application
需要特別注意的一點是,傳遞鏈中時沒有controller的,因為controller本身不具有大小的概念。但是響應鏈中是有controller的,因為controller繼承自UIResponder。
13,方法和選擇器有何不同?
答案:
selector是一個方法的名字,method是一個組合體,包含了名字和實現。
14,懶加載(延時加載)
答案:
(1)不必將創建對象的代碼全部寫在viewDidLoad方法中,代碼的可讀性更強
(2)每個控件的getter方法中分別負責各自的實例化處理,代碼彼此之間的獨立性強,松耦合
(3)只有當真正需要資源時,再去加載,節省了內存資源。
(4)在內存警告的時候將懶加載的對象置為nil,當再次用到的時候又可以懶加載了
15,Cocoa中有虛基類的概念么?怎么簡潔的實現?
答案:
虛基類主要解決在多重繼承時,基類可能被多次繼承,虛基類主要提供一個基類給派生類。
例如:A是基類,B和C都繼承了A類,而此時D又繼承了B和C,那么D豈不是繼承了兩次A嗎?為了避免重復多次繼承,就應該聲明B和C虛擬繼承A,確保A被繼承一次。
16,timer的間隔周期準嗎?為什么?怎樣實現一個精準的timer?
答案:
計時器不準確的原因是,計時器只有在 runLoop 的一次循環中被檢查,所以如果在上次循環中做了什么耗時的操作,那么計時器就被延后執行了。
正確的方法應該是新開一個線程,然后在新開的線程里設定一個 timer,并執行。
__block TestViewController *blockSelf = self;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
blockSelf->_timer=[NSTimer scheduledTimerWithTimeInterval:1.0
target:blockSelf
selector:@selector(caculateLeftTimeForTomorrow)
userInfo:nil
repeats:YES] ;
[[NSRunLoop currentRunLoop] addTimer:blockSelf->_timer forMode:NSDefaultRunLoopMode];
[[NSRunLoop currentRunLoop] run];
});
17,id和instancetype
答案:
id可以指向任何類型的指針 或 指向任何未知類型的指針。
instancetype只能作為返回值,不能像id那樣作為參數
18,[pool release]和[pool drain]有什么區別?
答案:
在GC機制下,release相當于空操作,所以用[pool drain]。
19,數據持久化
答案:
數據持久化,實際上就是將數據存放到網絡或者硬盤上,這里是存儲到本地的硬盤上,應用程序的本地硬盤是沙盒,沙盒實際上就是一個文件夾,它下面有4個文件夾。分別是Documents,Library,APP包和tmp文件夾。
Documents里面主要是存儲用戶長期使用的文件,itunes會自動備份,保存在這里會被蘋果拒絕應用
Library里面又有Caches和Preferences文件夾,
Caches里面存放的是臨時的文件,緩存。程序員管理。
Preferences里面存放的是偏好設置。iTunes會備份,系統管理
tmp里面也是臨時的文件,系統管理。iTunes不備份
plist:能不能用plist存儲看看能不能使用writeToFile方法,不能存儲自定義對象
偏好設置:不用關心文件名,鍵值對存儲。單例。iOS7之前默認不會和硬盤同步
NSKeyedArchiver:自定義對象歸檔,要遵守NSCoding協議,實現協議方法
encodeWithCoder告訴什么對象需要歸檔
initWithCoder。解檔,解析文件的時候調用
調用父類的[super init],只要父類也遵守了<NSCoding>協議,就要調用[super initWithCoder]方法;解檔之后要給成員變量賦值!!
補充:調用init方法就會調用initWithFrame方法
20,在iphone上有兩件事情要做,請問是在一個線程里按順序做效率高還是兩個線程里做效率高?為什么?
答案:
任務復雜就在一個線程順序執行,因為要是在兩個線程并發,線程切換需要時間
線程的創建需要512k的棧內存空間,主線程需要1M
21,obj-c的優缺點
objc優點: 1)Cateogies 2) Posing 3) 動態識別 4) 指標計算 5)彈性訊息傳遞 6) 不是一個過度復雜的 C 衍生語言 7) Objective-C 與 C++ 可混合編程
缺點: 1) 不支援命名空間 2) 不支持運算符重載 3) 不支持多重繼承 4) 使用動態運行時類型,所有的方法都是函數調用,所以很多編譯時優化方法都用不到。(如內聯函數等),性能低劣。
最大的優點是它的運行時特性,不足是沒有命名空間,對于命名沖突,可以使用長命名法或特殊前綴解決,如果是引入的第三方庫之間的命名沖突,可以使用link命令及flag解決沖突。
22,UIView和CALayer
答案:
1.首先UIView可以響應用戶的觸摸事件,Layer不可以.
2.View中frame getter方法,bounds和center,UIView并沒有做什么工作;它只是簡單的各自調用它底層的CALayer的frame,bounds和position方法。
3.UIView主要是對顯示內容的管理而 CALayer 主要側重顯示內容的繪制。
4.在做 iOS 動畫的時候,修改非 RootLayer的屬性(譬如位置、背景色等)會默認產生隱式動畫,而修改UIView則不會。
每個 UIView 內部都有一個 CALayer 在背后提供內容的繪制和顯示,并且 UIView 的尺寸樣式都由內部的 Layer 所提供。兩者都有樹狀層級結構,layer 內部有 SubLayers,View 內部有 SubViews.但是 Layer 比 View 多了個AnchorPoint
在 View顯示的時候,UIView 做為 Layer 的 CALayerDelegate,View 的顯示內容由內部的 CALayer 的 display
5.CALayer是定義在CoreGraphic框架中的,設置顏色和圖像屬性的時候要轉換成CGColor和CGImage屬性
6.如果兩個UIView是父子關系,那么它們內部的CALayer也是父子關系。
7.兩者最明顯的區別是 View可以接受并處理事件,而 Layer 不可以;圖層不能直接渲染到屏幕上。
23,寫框架的時候注意點。
答案:
1,留的接口夠不夠用,調用是不是簡單
2,留的參數是不是夠用
3,是否能根據類名,方法名猜出功能
4,是否依賴別人的框架
24,什么是NSManagedObject模型?什么是NSManagedobjectContext?
答案:NSManagedObject是NSObject的子類 ,也是coredata的重要組成部分,它是一個通用的類,實現了core data 模型層所需的基本功能,用戶可通過子類化NSManagedObject,建立自己的數據模型。
答案:NSManagedobjectContext對象負責應用和數據庫之間的交互。
1> CoreData是對SQLite數據庫的封裝
2> CoreData中的NSManagedObjectContext在多線程中不安全
3> 如果想要多線程訪問CoreData的話,最好的方法是一個線程一個NSManagedObjectContext
4> 每個NSManagedObjectContext對象實例都可以使用同一個NSPersistentStoreCoordinator實例,這是因為NSManagedObjectContext會在便用NSPersistentStoreCoordinator前上鎖
25,簡單介紹下NSURLConnection類及+ sendSynchronousRequest:returningResponse:error:與– initWithRequest:delegate:兩個方法的區別?
答案: NSURLConnection主要用于網絡訪問,其中+ sendSynchronousRequest:returningResponse:error:是同步訪問數據,即當前線程會阻塞,并等待request的返回的response,而– initWithRequest:delegate:使用的是異步加載,當其完成網絡訪問后,會通過delegate回到主線程,并其委托的對象。
26,Objective C中的selector 是什么?
答案:可以理解@selector()就是取方法的編號,他的行為基本可以等同C語言的中函數指針,只不過C語言中,可以把函數名直接賦給一個函數指針,而 Objective-C的類不能直接應用函數指針,這樣只能做一個@selector語法來取.它的結果是一個SEL類型。這個類型本質是類方法的編號 (函數地址)。
27,SQLite數據庫
答案:
iOS中數據存儲的方式:
1>Plist(只能數組,字典)
2>Preference(偏好設置/NSUserDefault)
3>NSCoding(NSKeyedArchiver)
4>SQLite3
5>Core Data
SQL:結構化查詢語言
數據庫不分大小寫,語句以“;”結尾。
DDL:數據定義語句create table/drop table
DML:數據操作語言insert update delete
DQL:數據查詢語言select
SQLite數據庫無類型
數據庫中的字符串用單引號
count(*)代表記錄
ORDER BY + 字段 DESC/ASC
limit可控制查詢條數
約束:NOT NULL UNIQUE,可以一起用
主鍵約束:自增長,唯一,不為空
利用外鍵約束可以建立表和表之間的聯系:一張表的某個字段,引用領一張表的主鍵
表鏈接:需要聯合多張表才能查到想要查詢的數據
28,使用block實現委托模式,其優點是回調的block代碼塊定義在委托對象函數內部,使代碼更為緊湊;
適配對象不再需要實現具體某個protocol,代碼更為簡潔。
GCD和block:在指定的隊列里提交一個異步執行的block,不阻塞當前線程
通過queue來控制block執行的線程。
GCD:異步并發:開啟多個線程異步執行
異步串行:開一一個線程順序執行
異步主線程:不開啟線程串行執行
同步任務在主隊列會卡死主線程(因為同步任務要立即執行,但是還要等待當前函數執行完畢,所以互相等待,卡死)
異步任務在主隊列不會卡死,會讓當前函數執行之后再執行任務
dispatch_apply用于遍歷數組,無序執行,可以用這個函數,快速迭代
NSOperationQueue進行掛起或者取消不會立刻終結當前任務
自定義NSOperation要自定義main方法,加入main方法中有耗時操作,建議在每個耗時操作之間加入方法判斷是不是被取消了
29,謂詞(NSPredicate)
答案:OC中的謂詞操作是針對于數組類型的,他就好比數據庫中的查詢操作,數據源就是數組,這樣的好處是我們不需要編寫很多代碼就可以去操作數組,同時也起到過濾的作用,我們可以編寫簡單的謂詞語句,就可以從數組中過濾出我們想要的數據。
30,UI框架的底層有CoreAnimation,CoreAnimation的底層有CoreGraphics。
31,目標 - 動作(Target - Action)
答案:允許一個控件對象(例如按鍵或滑動條) 向另外一個對象發送一條消息(即動作),以之作為對某個用戶事件(例如一個點擊事件)的響應。接收到消息的對象則可以對消息進行響應,并針對業務要求做出處理。
32,優化UITableView的性能(比如含有正在加載的網絡圖片不會卡)
答案:
- 使用不透明視圖。
- 不要重復創建不必要的table cell(注意設置identifier回收)
- 不要把控件放到contentView中,最佳的解決辦法還是繼承UITableViewCell,并在其drawRect:中自行繪制
- 在實現drawRect:的時候,它的rect參數就是需要繪制的區域,這個區域之外的不需要進行繪制。
- 避免在主線程更新UI,加載網絡圖片用SDWebImage
33,NSInteger和int
答案:NSInteger會根據系統是32位還是64位來決定是本身是int還是Long。
34,沙盒的目錄結構
答案:
Documents:保存應用運行時生成的需要持久化的數據,iTunes會自動備份該目錄。蘋果建議將程序中建立的或在程序中瀏覽到的文件數據保存在該目錄下,iTunes備份和恢復的時候會包括此目錄
Library:存儲程序的默認設置和其他狀態信息,iTunes會自動備份該目錄。
Libaray/Caches:存放緩存文件,iTunes不會備份此目錄,此目錄下文件不會在應用退出刪除。一般存放體積比較大,不是特別重要的資源
Libaray/Preferences:保存應用的所有偏好設置,ios的Settings(設置)應用會在該目錄中查找應用的設置信息,iTunes會自動備份該目錄。
tmp:保存應用運行時所需的臨時數據,使用完畢后再將相應的文件從該目錄刪除。應用沒有運行時,系統也有可能會清除該目錄下的文件,iTunes不會同步該目錄。iphone重啟時,該目錄下的文件會丟失。
35,+load和+initialize方法的區別
答案:
load是只要類所在文件被引用就會被調用,而initialize是在類或者其子類的第一個方法被調用前調用。所以如果類沒有被引用進項目,就不會有load調用;但即使類文件被引用進來,但是沒有使用,那么initialize也不會被調用。
load方法在Main方法執行之前執行
36, Posing,顧名思義,意思是“冒充”,它跟categories類似,但本質上不一樣,Posing存在的目的在于子類可以冒充父類,使得后續的代碼無需把父類修改為子類,就可以很方便的讓父類表現成子類的行為,從而實現非常方便的冒充。(不推薦使用的語言特征)
37,什么是runtime?
1> runtime是一套底層的C語言API(包含很多強大實用的C語言數據類型、C語言函數)
2> 實際上,平時我們編寫的OC代碼,底層都是基于runtime實現的
- 也就是說,平時我們編寫的OC代碼,最終都是轉成了底層的runtime代碼(C語言代碼)
runtime有啥用?
1> 能動態產生一個類、一個成員變量、一個方法
2> 能動態修改一個類、一個成員變量、一個方法
3> 能動態刪除一個類、一個成員變量、一個方法
常見的函數、頭文件
import <objc/runtime.h> : 成員變量、類、方法
Ivar * class_copyIvarList : 獲得某個類內部的所有成員變量
Method * class_copyMethodList : 獲得某個類內部的所有方法
Method class_getInstanceMethod : 獲得某個實例方法(對象方法,減號-開頭)
Method class_getClassMethod : 獲得某個類方法(加號+開頭)
method_exchangeImplementations : 交換2個方法的具體實現
消息機制原理:對象根據方法編號SEL去映射表查找對應的方法實現
import <objc/message.h>
Build Setting -> 搜索msg -> 設置屬性為No
objc_msgSend(....)
OC在編譯階段,可以調用任何函數,即使函數沒有實現也可以調用
C語言調用未實現的函數就會報錯
任何方法的調用,本質上都是發送消息
動態添加方法:
可以用performSelector動態添加方法
resolveInstanceMethod調用:當調用了沒有實現的方法沒有實現就會調用resolveInstanceMethod
分類添加屬性:
讓屬性和對象產生關聯:
- (void)setName:(NSString *)name {
// 添加屬性,跟對象
// 給某個對象產生關聯,添加屬性
// object:給哪個對象添加屬性
// key:屬性名,根據key去獲取關聯的對象 ,void * == id
// value:關聯的值
// policy:策越
objc_setAssociatedObject(self, @"name", name, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
解決KVC報錯
- (void)setValue:(id)value forUndefinedKey:(NSString *)key
{
if ([key isEqualToString:@"id"]) {
_ID = [value integerValue];
}
// key:沒有找到key
// value:沒有找到key對應的值
NSLog(@"%@ %@",key,value);
}
39,靜態庫和動態庫在使用上的區別
靜態庫:鏈接時,靜態庫會被完整地復制到可執行文件中,被多次使用就有多份冗余拷貝
動態庫:鏈接時不復制,程序運行時由系統動態加載到內存,供程序調用,系統只加載一次,多個程序共用,節省內存
注意:項目中如果使用了自制的動態庫,不能被上傳到AppStore
.a 和 .framework 的使用區別
.a 本身是一個二進制文件,需要配上 .h 和 其它資源文件 才能使用
.framework 本身已經包含了 .h 和 其它資源文件,可以直接使用
40,APP上架
41,UIButton和UITableView的設計模式
42,system樣式的UIButton不能設置image屬性,所以要把樣式改成custom;屬性名不能用new開頭;initWith注意With的W大寫
43,CocoaPods
答案:CocoaPods基于ruby對gem(gem是一種文件組織的包,一般的ruby的很多插件都有由這種各種的包提供)的依賴管理
44,在OC中調用JavaScript代碼
使用UIWebView的stringByEvaluatingJavaScriptFromString方法即可
45,正則表達式
拼接字符串規則
創建正則表達式對象,將規則放到正則表達式對象中
將傳進來的字符串進行遍歷,看看匹配哪些規則(表情,@,話題,URL)
46,圖片加載的兩種方法
方式一:有緩存(圖片所占用的內存會一直停留在程序中)
- (UIImage *)imageNamed:(NSString *)name;
name是圖片的文件名
方式二:無緩存(圖片所占用的內存會在一些特定操作后被清除)
NSString *path = [[NSBundle mainBundle] pathForResource];
- (UIImage *)imageWithContentsOfFile:(NSString *)path
- (id)initWithContentsOfFile:(NSString *)path;
path是圖片的全路徑
47,view的封裝
如果一個view內部的子控件比較多,一般會考慮自定義一個view,把它內部子控件的創建屏蔽起來,不讓外界關心
外界可以傳入對應的模型數據給view,view拿到模型數據后給內部的子控件設置對應的數據
48,進程間的通信方式:
無名管道( pipe ):管道是一種半雙工的通信方式,數據只能單向流動,而且只能在具有親緣關系的進程間使用。進程的親緣關系通常是指父子進程關系。
高級管道(popen):將另一個程序當做一個新的進程在當前程序進程中啟動,則它算是當前程序的子進程,這種方式我們成為高級管道方式。
有名管道 (named pipe) : 有名管道也是半雙工的通信方式,但是它允許無親緣關系進程間的通信。
消息隊列( message queue ) : 消息隊列是由消息的鏈表,存放在內核中并由消息隊列標識符標識。消息隊列克服了信號傳遞信息少、管道只能承載無格式字節流以及緩沖區大小受限等缺點。
信號量( semophore ) : 信號量是一個計數器,可以用來控制多個進程對共享資源的訪問。它常作為一種鎖機制,防止某進程正在訪問共享資源時,其他進程也訪問該資源。因此,主要作為進程間以及同一進程內不同線程之間的同步手段。
信號 ( sinal ) : 信號是一種比較復雜的通信方式,用于通知接收進程某個事件已經發生。
共享內存( shared memory ) :共享內存就是映射一段能被其他進程所訪問的內存,這段共享內存由一個進程創建,但多個進程都可以訪問。共享內存是最快的 IPC 方式,它是針對其他進程間通信方式運行效率低而專門設計的。它往往與其他通信機制,如信號兩,配合使用,來實現進程間的同步和通信。
套接字( socket ) : 套解口也是一種進程間通信機制,與其他通信機制不同的是,它可用于不同機器間的進程通信。
49,pch的作用
首先定義一個宏看看是不是OC文件,防止編譯錯誤
優點:
1,放一些公用的宏
2,公用的頭文件
3,自定義Log
缺點:
項目大時候編譯的慢
50,用KVC設置模型屬性
1,依次遍歷字典,取出key:name,去模型中找setter方法賦值
2,找_name方法進行賦值_name = name;
3,找name屬性直接進行賦值
全都找不到就會報錯
51,UIApplication
lication是應用程序的象征
應用程序創建的第一個對象就是UIApplication對象
applicationIconBadgeNumber紅點點
狀態欄是不是在聯網狀態,打電話,打開網頁。打電話發短信之所以要用application操作,是設計到應用級別的跳轉,所以用應用的唯一標識。
代理方法:啟動-->獲取焦點(可以用戶交互)
UIApplicationMain作用:
創建UIApplication對象,創建UIApplication的代理,并且設置代理遵守UIApplicationDelegate協議,開啟主運行循環,接收處理事件
通過info.plist加載Main.storyBoard(沒有不加載)
52,UIWindow
直接設置窗口的根控制器會增加旋轉功能,直接添加控制器的view不會做旋轉功能
makeKeyAndVisible:當前窗口成為應用程序的主窗口,并且顯示
狀態欄和鍵盤都是窗口,彈框不是窗口。
后創建的窗口放在最上層
UIWindowLevelAlert > UIWindowLevelStatusBar > UIWindowLevelNormal 真實類型是CGFloat
要想讓控制器顯示在最上面,就添加到UIWindow上面
53,-(void)loadView的作用
1,自定義控制器的view
2,第一次使用控制器的view時候調用
3,如果沒有自定義view,就不能獲取控制器的view
4,不用調用[super loadView];
5,重寫了這個方法,就不會加載storyboard描述的view了
注意:加載控制器的view,先調loadView方法,然后是viewDidLoad方法
54,默認控制器的顏色:幾乎透明,clearColor,后面的view不能交互,但是能看到
<= 0.01透明 >0.01幾乎透明
55,pop控制器的時候要把動畫執行完畢才銷毀,一個導航控制器只有一個導航條,導航條的標題由棧頂控制器決定。什么什么item都是蘋果封裝的模型
[button sizeToFit];控件的尺寸有圖片決定(僅僅設置尺寸,不能設置位置)
56,控制器的生命周期
viewDidLoad>>viewWillAppear>>viewWillLayoutSubviews>>viewDidLayoutSubviews>>
viewDidAppear
跳轉的時候先調用第二個控制器的viewDidLoad>>viewWillLayoutSubviews>>viewDidLayoutSubviews
然后第一個控制器viewWillDisAppear>>viewDidDisAppear
didReceiveMemeryWarning調用之后調用viewDidUnload
57,block(相當于小弟)快捷方式:inline
保存一段代碼,用到的時候再去調用,一般不需要返回值,需要傳遞什么值,就把什么作為參數
適用場合:逆傳傳值,處理網絡的時候用block封裝代碼:先把更新UI的代碼放在block中,等到網絡加載完成后調用
A->B B要傳值給A,在B中定義block屬性,適當的位置調用,block的實現放在A中
58,UITabBarButton沒有圖片,badge顯示在tabBarButton的左上角,有圖片才顯示在圖片的右上角
59,tableView數據固定死就用靜態單元格,靜態單元格只能在storyBoard中用,Xib不能用。使用靜態單元格的時候不用寫tableView的數據源方法
60,任何控制器都能用modal展示出來,push的下一個界面和上一個界面有聯系,modal沒有聯系
modal出什么控制器,什么控制器就有權利dismiss
61,調用一個控制器的alloc init方法,會先加載VC的view的view.xib。沒有則會加載viewController.xib。也沒有則不會加載xib
62,只有繼承了UIResponder的對象才能接受并處理事件,view的拖拽要設置multiple touch
觸摸事件發生后,事件交給UIApplication處理,application取出最上層的事件交給keyWindow,主窗口尋找最合適的視圖去處理,父控件的alpha值小于0.01,會讓子控件看不見
hitTest方法:事件傳遞的時候調用,為了尋找最合適的view,傳入的參數point是方法調用者的坐標系
子控件超出父控件之外不能接受事件。解決辦法:轉換坐標系到超出的子控件,判斷點擊的點是不是在超出的子控件上面,如果是,交給子控件處理,不在,調用super的hitTest方法
63,runloop(事件驅動)
作用:保持程序一直運行,處理觸摸事件(輸入源/定時源),定時事件,selector事件,節省CPU資源,不用的時候休眠
NSRunloop CFRunLoopRef。每條線程都有與之對應的RunLoop,讓子線程永遠活著就可以開啟RunLoop。用字典來存儲,key是當前線程
一個RunLoop包含多個模式,一個模式包含Source/Timer/Observer,不同的模式對應不同的事件
runloop要想成功運行有兩個條件:模式里面有東西,調用run方法
Observer監聽Runloop的狀態改變,用處:在UI點擊之前做一些事情。點擊按鈕先調afterWaiting
runLoop有時間限制,但是系統給的時間很大
CF的內存管理:
凡是帶有create,copy,retain創建的對象都要進行一次release操作:CFRelease()
通過調用[NSRunloop currentRunLoop];就可以創建runloop對象
一條線程對應一個runloop:源碼寫道:調用[NSRunloop currentRunLoop]就傳給一個pthread對象,然后返回一個runloop對象,通過字典的形式一一對應
和runloop相關的5個類:CFRunloopRef,CFRunloopModeRef,CFRunloopSourceRef,CFRunloopTimerRef,CFRunloopObserverRef
source0:基于非port的(比如按鈕點擊)
source1:基于port的,操作系統內核或者其他線程發過來的消息,source1接收到事件是發給source0的
應用
1,滾動操作的時候延遲顯示圖片
2,常駐線程,用來監控用戶的行為,聯網狀態
3,自動釋放池在runloop休眠之前(before waiting)會清理一次,創建常駐線程開啟runloop的代碼最好用@autoreleasepool包住
kCFRunLoopEntry; // 創建一個自動釋放池
kCFRunLoopBeforeWaiting; // 銷毀自動釋放池,創建一個新的自動釋放池
kCFRunLoopExit; // 銷毀自動釋放池
面試題:
1,什么是runloop:
是運行循環,內部是執行一個高級的do-while循環,這個循環中這行各種timer,source,observe任務,沒有任務就會休眠,休眠之前會釋放一下自動釋放池
一個線程對應一個runloop,主線程的runloop默認開啟,子線程的runloop要手動開啟,開啟runloop要設置模式,模式里面要有任務,沒有任務就會直接退出runloop
64,NSTimer不準
NSTimer有兩種創建方式,schedule...自動加到主線程的默認模式下的runloop,模式改變(tracking模式)的時候不準。第二種[NSTimer timer...]加到主運行循環中,加上模式標簽commonModes
65,父子控制器
兩個控制器的view是父子關系,兩個控制器也應該是父子關系
66,static的作用
修飾局部變量會讓局部變量只創建一次,內存只有一份(修改之后保存新的值),不會改變局部變量的作用域
用extern關鍵字可以訪問全局變量,普通的全局變量不安全,會被改掉
用static修飾的全局變量作用域變成當前文件,不是全世界了
67,copy
調用multiCopy一定會產生可變字符串,產生新地址(深拷貝)
只有copy不可變對象(比如NSString)才會產生不可變字符串,不產生新地址(淺拷貝)
要想拷貝自定義對象,就要遵守<NSCopying>協議,實現copyWithZone方法
@property聲明字符串用copy:將傳進來的屬性copy一份賦值給對象的屬性,傳進來的屬性改變,對象的屬性不改變
例子:@property(nonatomic, copy) NSMultiString *name;
錯誤!真實類型是NSString。要用strong屬性聲明
68,const和宏
const修飾的變量是常量,定義的宏會在內存中出現多次,但是const保證全局只有一次內存(蘋果的通知的常量用的都是const)
static const修飾的全局變量變成全局常量,并且只能在本文件訪問
在項目中定義常量,定義Const.h和Const.m文件.m用來聲明常量.h用來引用常量。為了裝逼,可以把extern換成UIKIT_EXTERN。
面試題:
//p1不能修改(不能修改指針指向的值),但是p1可以修改(可以修改p1的指向)
const int p1; == int const p1;
正確:p1 = # 錯誤:p1 = 30;
//p2不能修改(不能修改指針p2的指向),但是p2可以修改(可以修改p2指針指向的值)
int * const p2;
錯誤:p2 = # 正確p2 = 30;
//不希望外部改name的值,所以用const修飾
UIKIT_EXTERN NSString * const name;
數組指針面試題:
數組的地址就是首元素的地址
指針p的加減法運算
指針p + N
p里面存儲的地址值 + N * 指針所指向類型的占用字節數
指針p - N
p里面存儲的地址值 - N * 指針所指向類型的占用字節數
數組名
存儲的是數組首元素的地址
等價于:一個指向數組首元素的指針
數組名 + 1 的跨度:數組首元素的占用字節數
其他結論
&num + 1的跨度:num的占用字節數
舉例:
// int numbers[2][2][2] = {
// {
// {10, 20},
// {30, 40},
// },
// {
// {50, 60},
// {70, 80}
// }
// };
//
// numbers[0][0] == &numbers[0][0][0],相當于是一個指向numbers[0][0][0]的指針
// numbers[1] == &numbers[1][0],相當于是一個指向numbers[1][0]的指針
// numbers == &numbers[0],相當于是一個指向numbers[0]的指針
// &numbers == 相當于是一個指向numbers的指針
69,在Objective-C中,對象的類是isa指針決定的。isa指針指向對象所屬的類。
這就引出了元類的定義:元類是類對象的類,類對象是元類的實例。
簡單說就是:
我們以前調用 "+" 開頭的類方法實際是在調用元類的對象方法
當你給對象發送消息時,消息是在尋找這個對象的類的方法列表。
當你給類發消息時,消息是在尋找這個類的元類的方法列表。
根元類的元類則就是它自己。也就是說基類的元類的isa指針指向他自己。
70,分析內存分配:Xcode->Product->Profile->Allocations/Leaks
內存包括實際內存和虛擬內存
/*
imageNamed和imageWithContentOfFile
imageNamed:加載圖片
1.當對象銷毀,圖片對象不會隨著一起銷毀
2.加載的圖片占據的內存較大:9.48
3.相同的圖片只會加載一份到內存中,如果同時使用,使用同一個對象即可
imageWithContentOfFile:加載圖片
1.當對象銷毀的時候,圖形對象會隨著一起銷毀
2.加載的圖片,占據的內存較小:6.25
3.相同的圖片會多次加載到內存中,如果同時使用圖片,使用的是不同的對象
總結:
imageName:如果一些圖片在多個界面都會使用,并且圖片較小,使用頻率高.(圖標/小的背景圖)
imageWithContentOfFile:只在一個地方使用,并且圖片較大,使用頻率不高.(版本新特性/相冊)
*/
71,分析內存泄露Xcode->Product->Analyze
1,靜態內存分析:不運行程序,直接對代碼進行分析。沒有真正分配內存,根據代碼的上下文情況分析是不是有內存泄露,不一定準確。為什么不準確?在方法中聲明的變量在外面釋放會被檢測到內存泄露
運用場景:在ARC用CF框架
2,動態內存分析:讓程序跑起來,用到可能泄露的代碼
72,在iOS中,有2個框架可以訪問用戶的通訊錄
AddressBookUI.framework
提供了聯系人列表界面、聯系人詳情界面、添加聯系人界面等
一般用于選擇聯系人
AddressBook.framework
純C語言的API,僅僅是獲得聯系人數據
沒有提供UI界面展示,需要自己搭建聯系人展示界面
里面的數據類型大部分基于Core Foundation框架,使用起來極其蛋疼
從iOS6開始,需要得到用戶的授權才能訪問通訊錄,因此在使用之前,需要檢查用戶是否已經授權
73,屏幕適配
1>.為什么蘋果推出SizeClasses
iPhone3gs-4s : frame直接寫死
iPad : autoresizing—>根據父控件frame發生改變,子控件跟著一起改變
iPhone5-iPhone5s : autolayout —>自動布局
iPhone6和iPhone6p : size Classes—>發現屏幕變的太多樣化,界面大統一
2> sizeclass
僅僅是對屏幕進行了分類, 真正排布UI元素還得使用autolayout
不再有橫豎屏的概念, 只有屏幕尺寸的概念
不再有具體尺寸的概念, 只有抽象尺寸的概念
把寬度和高度各分為3種情況
- Compact : 緊湊(小)
- Any : 任意
- Regular : 寬松(大)
和UIButton類比
練習
練習1:UIButton手機橫屏的時候顯示,豎屏的時候不顯示
練習2:橫屏的時候在左上角,豎屏的時候,在右下角
練習3:iPad當中也顯示在中間
練習4:圖片的顯示 : 一般情況下顯示一張圖片,iPad顯示特有的圖片
練習5:Label的顯示
練習6:約束沖突
- 符號代表
- : Compact
- : Any
- : Regular
- 繼承性
w:Compact h:Compact 繼承 (w:Any h:Compact , w:Compact h:Any , w:Any h:Any)
w:Regular h:Compact 繼承 (w:Any h:Compact , w:Regular h:Any , w:Any h:Any)
w:Compact h:Regular 繼承 (w:Any h:Regular , w:Compact h:Any , w:Any h:Any)
w:Regular h:Regular 繼承 (w:Any h:Regular , w:Regular h:Any , w:Any h:Any) - 設備對應屏幕
iPhone4S,iPhone5/5s,iPhone6
豎屏:(w:Compact h:Regular)
橫屏:(w:Compact h:Compact)
iPhone6 Plus
豎屏:(w:Compact h:Regular)
橫屏:(w:Regular h:Compact)
iPad
豎屏:(w:Regular h:Regular)
橫屏:(w:Regular h:Regular)
Apple Watch(猜測)
豎屏:(w:Compact h:Compact)
橫屏:(w:Compact h:Compact) - sizeclass和autolayout的作用
sizeclass:僅僅是對屏幕進行了分類
autolayout:對屏幕中各種元素進行約束(位置\尺寸)
74,靜態庫和動態庫
frameWork可以是動態的,也可以是靜態的
系統的frameWork是動態庫,默認制作出來的frameWork都是動態庫
靜態庫:鏈接的時候靜態庫會被復制到可執行文件中,產生冗余
動態庫:系統只加載一次,多個程序可以共用。使用自制的動態庫,不能上傳到AppStore
可以把MRC編譯成靜態庫
模擬器:
4s-5用的都是i386架構
5s-6Plus用的都是x86_64架構
真機:
3GS-4s armv7架構
5/5c armv7s架構,只要支持armv7,就支持armv7s
5s-6Plus arm64架構
debug版本包含很多符號信息
75,把NSURLConnection放到主線程默認會開啟子線程處理。嘗試放在子線程發送請求會不好用,因為子線程的runloop默認不啟動
76,用NSURLSession實現斷點下載,記錄data文件,把上次下載的tmp文件保存到caches里面,開始的時候再放到tmp文件夾里面
用NSURLConnection實現斷點下載:設置http的請求頭,設置Range的區間
77,如何快速上手公司的舊項目
搜索文字,搜索圖片
把圖片保存,關聯控制器記錄下來
搜索AppDelegate/int main
return;注釋
78,
當把一個對象添加到集合中的時候會把對象的引用計數+1
當集合被銷毀的時候,會對集合里面所有的對象引用計數—1
對象從集合中移除之后,會把對象引用計數-1
以add開頭的方法,后面的對象的引用計數會+1
79設計模式
1 工廠模式
- 客戶向工廠提出需求,不關注如何制造手機;工廠制造手機,對制造工藝進行封裝
- 簡單工廠是具體的類
- 工廠管理者將簡單工廠的工廠類進行了一次抽象,根據不同的需求創建不同的具體工廠
- 直接對NSNumber/NSValue進行實例化不能創建出來對象,有實現具體工廠
80,線程的狀態
當一個線程剛剛創建的時候處于就緒狀態,調用start方法的時候放到內存中的可調度線程池中,當CPU輪詢到這個線程的時候就會處于運行狀態,處理別的線程的時候處于就緒狀態。當睡眠或者等待同步鎖的時候就處于阻塞狀態,這時候會從可調度線程池中移除,但是不會在內存中銷毀,等到阻塞狀態結束之后后就會重新放回可調度線程池中。等到線程死亡的時候就會從可調度線程池中移除,并且從內存中銷毀
81,MD5和base64區別
MD5是一種不可逆的摘要算法,無論多少二進制數據,在MD5算法一定的情況下,都會變成一個定長的數據,并且是根據內容不同而唯一。
而Base64是一種編碼方式,主要用于將二進制數據轉換為文本數據,方便使用HTTP協議等,是可逆的。
83,AFNetWorking的底層實現
基于NSURLSession的和NSURLConnection的封裝,但是現在3.0版本已經放棄對NSURLConnection的支持了。
發送基本的HTTP請求用到的是AFHTTPSessionManager,調用+manager方法進行初始化,初始化包括指定sessionConfiguration為默認的configuration,NSOperationQueue的初始化并且設置最大并發數為1,指定session的代理為當前控制器。GET請求方法封裝了dataTast和downloadTask,并且將task啟動(因為通過原生的方式創建默認不啟動,要手動啟動,就是resume方法)。在文件上傳的時候將文件的二進制文件拼接到參數中就行,內部幫我們設置好了mimeType,下載的時候內部遵守了協議,實現了三個代理方法,將下載的進度以block的方式返回回來,同時將完成結果返回回來
監控聯網狀態的類使用常駐線程來一直監控用戶的聯網狀態
84,操作系統的五大管理功能:
(1)作業管理:包括任務、界面管理、人機交互、圖形界面、語音控制和虛擬現實等;
(2)文件管理:又稱為信息管理;
(3)存儲管理:實質是對存儲“空間”的管理,主要指對主存的管理;
(4)設備管理:實質是對硬件設備的管理,其中包括對輸入輸出設備的分配、啟動、完成和回收;
(5)進程管理:實質上是對處理機執行“時間”的管理,即如何將CPU真正合理地分配給每個任務。
五大類型操作系統各自的特點分別是:
(1) 批處理操作系統的特點有:a. 用戶脫機使用計算機。用戶提交作業之后直到獲得結果之前就不再和計算機打交道。作業提交的方式可以是直接交給計算中心的管理操作員,也可以是通過遠程通訊線路提交。提交的作業由系統外存收容成為后備作業。
b.成批處理。操作員把用戶提交的作業分批進行處理。每批中的作業將由操作系統或監督程序負責作業間自動調度執行。
c.多道程序運行。按多道程序設計的調度原則,從一批后備作業中選取多道作業調入內存并組織它們運行,成為多道批處理。
(2) 分時操作系統的特點有:a. 交互性:首先, 用戶可以在程序動態運行情況下對其加以控制。其次,用戶上機提交作業方便。第三,分時系統還為用戶之間進行合作提供方便。
b. 多用戶同時性:多個用戶同時在自己的終端上上機,共享CPU和其他資源,充分發揮系統的效率。
c.獨立性:客觀效果上用戶彼此間感覺不到有別人也在使用該臺計算機,如同自己獨占計算機一樣。
(3) 實時操作系統的特點有:a. 實時時鐘管理(定時處理和延時處理)。
b. 連續的人-機對話,這對實時控制往往是必須的。
c.要求采取過載保護措施。例如對于短期過載,把輸入任務按一定的策略在緩沖區排隊,等待調度; 對于持續性過載,可能要拒絕某些任務的輸入; 在實時控制系統中,則及時處理某些任務,放棄某些任務或降低對某些任務的服務頻率。
d.高度可靠性和安全性需采取冗余措施。雙機系統前后臺工作,包括必要的保密措施等。
(4) 網絡操作系統的特點有:a. 計算機網絡是一個互連的計算機系統的群體。
b. 這些計算機是自治的,每臺計算機有自己的操作系統,各自獨立工作,它們在網絡協議控制下協同工作。
c.系統互連要通過通信設施(硬件、軟件)來實現。
d.系統通過通信設施執行信息交換、資源共享、互操作和協作處理,實現多種應用要求。
(5) 分布式操作系統的特點有:a.計算機網絡的開發都遵循協議,而對于各種分布式系統并沒有制定標準的協議。當然,計算機網絡也可認為是一種分布式系統。
b.分布式系統要求一個統一的操作系統,實現系統操作的統一性。
c.分布式操作系統對用戶是透明的。但對計算機網絡,若一個計算機上的用戶希望使用另一臺計算機上的資源,則必須明確指明是哪臺計算機。
d.分布式系統的基礎是網絡。分布式系統已不僅是一個物理上的松散耦合系統,同時還是一個邏輯上緊密耦合的系統。
e.分布式系統還處在研究階段。而計算機網絡已經在各個領域得到廣泛的應用
85, 橋接轉換
在MRC的情況下,直接進行強制類型轉換就行,不用考慮對象的所有權
在ARC的情況下會報錯,加上__bridge橋接轉換,但是不會轉讓對象的所有權。__bridge_transfer:CF對象的所有權交給OC對象,由ARC釋放內存。__bridge_retained:OC對象的所有權交給CF對象管理。需要手動CFRelease()一下
唐巧:
__bridge只做類型轉換,不增加引用計數,CF對象不用的時候需要調用CFRelease。
__bridge_retained:類型轉換后,引用計數加1,需要調用CFRelease。
__bridge_transfer:類型轉換后,將對象的引用計數交給ARC管理,不用調用CFRelease。
86,nil,Nil,NULL,NSNull
Nil:空類
nil:空對象,已經從內存中消失了,再次retain或者添加到數組/字典中會崩潰
NSNull:對象的值為空,但是再次retain或者添加到數組/字典中不會導致程序崩潰
NULL:來自C語言,代表空指針
87,iOS中導航設計模式的種類
平鋪導航:UITabBarController
標簽導航:UINavigationController
樹形導航:UIPageViewController
88,iOS單元測試框架
OCUnit和XCTest都是官方的測試框架,OCUnit過時已經被XCTest取代。
GHUnit和OCMock都是第三方的測試框架
89,模態視圖的專用屬性
A.UIModalPresentationFullScreen,全屏狀態,是默認呈現樣式,iPhone只能全屏呈現。
B.UIModalPresentationPageSheet,它的寬度是固定的768點,在iPad豎屏情況下則全屏顯示。
C.UIModalPresentationFormSheet,它的是固定的540*620點,
無論是橫屏還是豎屏情況下呈現尺寸都不會變化。
D.UIModalPresentationCurrentContext,它與父視圖控制器有相同的呈現方式。
90,UIPopoverController控制器的常用方法和屬性(ABCD)
A. presentPopoverFromBarButtonItem:permittedArrowDirections:animated: 呈現Popover視圖方法;
B.dismissPopoverAnimated:關閉Popover視圖方法;
C.popoverVisible,判斷Popover視圖是否可見;
D.popoverArrawDirection,判斷Popover視圖箭頭的方向;
91,NSURL的構造函數有?(CD)
A. + requestWithURL:
B - initWithURL:
C + URLWithString:
D - initWithString:
92,MRR是MRC的官方名字;
MRC是手動引用計數;
ARC是自動引用計數;
GC是垃圾回收(在開發OS X中使用);
93,
NSXML框架中核心的是NSXMLParser和它的委托協議NSXMLParserDelegate,NSXMLParserDelegate常用的方法有哪些?(ABCDE)
A. parserDidStartDocument
B. parser:foundCharacters
C. parser:didStartElement:namespaceURI:qualifiedName:attributes
D. parser:didEndElement:namespaceURI:qulificedName
E. parserDidEndDocument
95,軟件的缺陷生命周期:
1,new:缺陷被測試發現(臥槽!)
2,Open:測試提交給開發(媽蛋!)
3,Update:開發人員修復了但是沒有給測試人員(小樣!)
4,Fix:自測通過,提交給測試人員(得意臉)
5,Close:測試的確修復(牛逼!)
6,Reopen:沒通過,重新改(損色)
96,NSHashTable對引用的對象是weak指針
97,枚舉定義1<<3
什么時候要用到這種方式呢? 那就是一個枚舉變量可能要代表多個枚舉值的時候. 其實給一個枚舉變量賦予多個枚舉值的時候,原理只是把各個枚舉值加起來罷了. 當加起來以后,就獲取了一個新的值,那么為了保證這個值的唯一性,這個時候就體現了位運算的重要作用. 位運算可以確保枚舉值組合的唯一性. 因為位運算的計算方式是將二進制轉換成十進制,也就是說,枚舉值里面存取的是 計算后的十進制值. 打個比方: 通過上面的位運算方式設定好枚舉以后,打印出來的枚舉值分別是: 1 2 4 8 16 這5個數字,無論你如何組合在一起,也不會產生兩個同樣的數字.
98,iOS9關鍵字
_Nullable:屬性可以為空
_Nonnull:屬性可以為空(只能修飾對象)
泛型一般用來修飾集合中元素的類型。通過泛型取出來的對象可以直接當指定的泛型類型使用
_covariant:協變性:
99,UIViewController完整生命周期
-[ViewController initWithNibName:bundle:];
-[ViewController init];
-[ViewController loadView];
-[ViewController viewDidLoad];
-[ViewController viewWillDisappear:];
-[ViewController viewWillAppear:];
-[ViewController viewDidAppear:];
-[ViewController viewDidDisappear:];
100,self = [super init];
容錯處理,先初始化父類,再傳給子類,假如父類初始化失敗就會返回nil。子類擁有父類的實例和方法。
103.KVO的底層實現
調用對象的setter方法才會被KVO監聽到,直接進行賦值操作不能監聽到。p.age可以,p->age不可以
修改當前對象的isa指針指向生成的派生類,派生類在前面加上NSKVONotifying_
KVO是怎么進行通知的:
1>> KVO是對NSObject對象的一個分類,任何一個對象都可以調用KVO
* 首先保存被觀察對象為當前分類的成員屬性,因為在分類中,只能用運行時保存,實際上就是設置和屬性的關聯 ,然后傳入策略(copy, retain等),導入<objc/message.h>框架
* 然后同樣是通過運行時修改被觀察對象的isa指針的指向
2>>在派生類中做事情
* 在生成的派生類中先調用super調用父類的setter方法
* 然后通過運行時拿到被觀察的對象
* 調用對象的observeValueForKeyPath方法告知外界
104.objectForKey與valueForKey的區別
從 NSDictionary 取值的時候有兩個方法,objectForKey: 和 valueForKey:
一般的key可以是任意的字符和字母的組合。但是使用valueForKey方法,如果key是以 @ 開頭,系統會去掉 key 里的 @ 然后用剩下部分作為 key 執行 [super valueForKey:],這樣就會報valueForUndefinedKey錯誤
建議NSDictionary用objectForKey
105.xcode6和xcode5的區別
1.xcode6沒有frameworks,會導入常見的frameworks
2.xcode6多了launchScreen.xib
3.沒有設置啟動界面,默認的可見范圍是320*480
4.xcode5有pch文件
106.info.plist的作用
1.是一個字典,存放一些配置的鍵值對
2.Bundle name <-> 應用程序的名稱
3.Bundle identifier <-> 應用的唯一標示符,推送的時候通過唯一標示符找到對應的應用
4.Bundle version string short <-> 上傳新的版本要設置比之前的版本號高
5.通過[NSBundle mainBundle].infoDictionary
107.pch的作用,新增的pch文件需要告訴編譯器提前編譯,指定pch的路徑
1.存放一些公用的宏
2.存放一些公用的頭文件
3.自定義Log,NSLog比較消耗資源,在調試的時候使用,發布的時候需要注釋
HKLog(...) NSLog(VA_ARGS)...表示是可變參數
4.和C或者C++混編的時候要注意對pch文件進行處理,#ifdef OBJC #endif,否則會報錯
108.NSURLConnection和Runloop的關系
NSURLConnection請求發出去要等待服務器給它發送的數據。在當前線程的runloop中等待網絡返回的數據。
所以放在子線程中不好使,因為子線程的runloop是默認不啟動的
109.xib和storyboard對版本控制工具不友好:
他們含有xcode的版本信息和操作系統的信息,多人操作的時候即使不修改,只要打開就會修改其內容
110.弱引用持有對象,但是不增加引用計數
111.散列函數的設計和特點
1.直接定制法:設計線性函數。特點:簡單,均勻,但是要事先知道關鍵字的分布情況
2.數字分析法:關鍵字的位數比較大,去數字的一部分
3.平方取中法:不知道關鍵字的分布,關鍵字比較小
4.折疊法:將關鍵字折疊分組,然后相加。特點:不用知道關鍵字的分布,關鍵字的位數比較多
5.除留余數法(HOT):選擇的被除數最好小于表的長度(最好接近)的質數或者不包括20以下質因子的合數。
112.沖突的解決辦法
1.開放定址法:一旦發現了沖突,就去尋找下一個空的散列地址
2.再散列函數法:用一個新的散列函數去計算
3.鏈地址法:在產生沖突的位置創建一個單鏈表
4.公共溢出區法:設置一個公共溢出區,用來存放出現沖突的地址。
113.NSInvocation
NSInvocation方法包裝了一次方法調用(方法調用者,方法名,方法參數,方法返回值)
方法簽名:包括了方法名稱,參數,返回值,對方法的描述
114.NSTimer和CADisplayLink
NSTimer需要設置一個時間間隔,當時間間隔和屏幕的刷新頻率不一樣的時候就會出現時間的堆積,出現卡頓的現象。
CADisplayLink的selector執行的時間間隔就是屏幕的刷新頻率,所以不會卡。
115.進程的特點:
1.獨立性。
2.動態性:程序是靜態的指令集合,進程是活動的指令集合,是動態消亡的
3.并發性:CPU不斷的調度進程。
Core Animation是在后臺執行的,不會阻塞主線程,只能作用在CALayer上面,不能作用在UIView上面
CAAnimation遵守CAMediaTiming協議,有三個子類CAAnimationGroup(動畫組),CAPropertyAnimation(屬性動畫),CATransition(轉場動畫)
CAPropertyAnimation有兩個子類:CABasicAnimation(基礎動畫)和CAKeyFrameAnimation(關鍵幀動畫)
* CABasicAnimation只能從一個數值(fromValue)變到另一個數值(toValue),而CAKeyframeAnimation會使 用一個NSArray保存這些數值
* CABasicAnimation可看做是只有2個關鍵幀的CAKeyframeAnimation
轉場動畫:
CATransition:轉場代碼必須得要和轉場動畫在同一個方法當中.
UIView也可以做轉場動畫
117.UIView動畫與核心動畫的區別?
1.核心動畫只作用在layer.
2.核心動畫修改的值都是假像.它的真實位置沒有發生變化.
什么時候用UIView動畫什么時候用核心動畫?
當需要與用戶進行交互時用UIView,不需要與用戶進行交互時兩個都可以.
什么情況用核心動畫最多?
1.轉場動畫.
2.幀動畫.(屬性動畫的一種,另外一個是基礎動畫,可以看做是有兩個關鍵幀的幀動畫)
3.動畫組.
118,weak和assign
weak:用__weak修飾,不會讓引用計數加一,如果指向的對象被銷毀,指針自動置為nil
assign:用__unsafe_unretained修飾,不會讓引用計數加一,如果指向的對象被銷毀,不自動將指針置為nil,會報壞內存訪問錯誤
119.react native
面向組件開發,類都能生成組件,插入到頁面中
FlexBox:彈性盒模型
120.Masonry的底層實現
用到鏈式編程
首先創造約束制造者MASConstrainMaker,并且綁定當前的view,生成了一個保存了所有約束的數組
執行傳入的block(設置約束)
約束制造者給view安裝約束
* 清空之前所有的約束
* 遍歷約束數組,一個一個安裝(安裝就用系統的NSLayoutConstrain)
121,RAC被稱為函數響應式編程(FRP)框架
[RACSubscriber
sendNext]: 執行nextBlock
[RACReplaySubject
sendNext]:
- 1.保存發送的值
- 2.遍歷自己所有訂閱者,發送數據
122,排序總結
排序方法 平均情況 最好情況 最壞情況 輔助空間 穩定性
冒泡排序 O(n^2) O(n) O(n^2) O(1) 穩定
選擇排序 O(n^2) O(n^2) O(n^2) O(1) 不穩定
- 比較次數:O(n^2) 移動次數:O(n)
插入排序 O(n^2) O(n) O(n^2) O(1) 穩定
希爾排序 O(nlog(n))~O(n^2) O(n^1.3) O(n^2) O(1) 不穩定
堆排序 O(nlog(n)) O(nlog(n)) O(nlog(n)) O(1) 不穩定
歸并排序 O(nlog(n)) O(nlog(n)) O(nlog(n)) O(n) 穩定
快速排序 O(nlog(n)) O(n*log(n)) O(n^2) O(log(n)) 不穩定
外排序:歸并排序
堆排序中建堆過程的時間復雜度是O(n),重建堆的時間復雜度為nlogn
關鍵字比較次數同記錄初始排列有關的是:冒泡,直接插入,快速,歸并
- Prim算法的時間復雜度 鄰接表存儲時,是 O(n+e) 圖的時候 是O(n^2)
124.中綴后綴的轉換
中->后:棧用來進出運算的符號,數字直接輸出
后->中:棧用來進出數字,符號用來將棧中的數字計算輸出
深度優先搜索和謙虛二叉遍歷都類似圖的深度遍歷,都借助棧的數據結構;
廣度優先相關的借助了隊列的數據結構,類似圖的層序遍歷
126.js閉包
可以讀取函數內部的變量,
讓這些變量的值始終保持在內存中。
127.objc和JS相互調用
OC調用JS:在webViewDidFinishLoad方法中執行js語句
JS中調用OC:
> 當加載一個網頁之后,假如網頁中想調用OC的方法,要在js的方法中改變locations的url指向,然后在shouldStartLoadWithRequest代理方法中獲取訪問的URL地址,通過解析協議頭調用早已經實現好了的方法。
> 通過導入JavaScriptCore.framework通過KVC獲取JSContext上下文,通過上下文執行block,block中就是想
調用的方法,這個block的名字就是網頁中js調用的方法的名字,而且可以通過上下文獲取到傳進來的參數數組,遍歷數組就能取出來相傳進來的參數。
128,B-樹
B-樹的階數m決定了節點的分支數(m/2的上整,m),但是有兩個例外,一個是葉節點,另外一個是根節點,根節點允許有兩個分支。
129.雙向鏈表節點p的右邊插入節點s
s->left = p; s->right = p->right; p->right->left = s; p->right = s;
雙鏈表的插入兩種方法:
將下面的next換成rlink,pre 換成llink即可
一、首先處理新插入節點p的后繼、前驅,然后再處理后繼的前驅、
p->next = q; //p的后繼
p->pre = q->pre;//p的前驅
q->pre = p; //(q)的前驅
p->pre->next = p;///新節點的前驅( p->pre)的后繼
二、前兩步都一樣:
p->next = q; //p的后繼
p->pre = q->pre;//p的前驅
q->pre->next = p; //這一步要在前面,
q->pre = p;
130.精簡排序
插入排序:每次插入的時候,想要插入的元素只和前面的元素比較一次。
歸并排序:兩兩歸并,只比較一次。
131.一個有向圖能被拓撲排序的充要條件就是它是一個有向無環圖。
入隊時,將元素壓入s1。
出隊時,判斷s2是否為空,如不為空,則直接彈出頂元素;如為空,則將s1的元素逐個“倒入”s2,把最后一個元素彈出并出隊。
這個思路,避免了反復“倒”棧,僅在需要時才“倒”一次
132貪心算法
單源最短路徑中的Dijkstra算法
最小生成樹的Prim算法
最小生成樹的Kruskal算法