最近公司項目不怎麼忙, 閒暇時間把iOS 在面試中可能會遇到的問題整理了一番, 一部分題目是本身面試遇到的,一部分題目則是網上收錄的, 方便本身鞏固複習, 也分享給你們! 知識點比較多,比較雜,這裏作了分類,下面是分類連接地址;git
面試知識點整理 - 目錄:
iOS | 面試知識整理 - OC基礎 (一)
iOS | 面試知識整理 - OC基礎 (二)
iOS | 面試知識整理 - OC基礎 (三)
iOS | 面試知識整理 - UI 相 關 (四)
iOS | 面試知識整理 - 內存管理 (五)
iOS | 面試知識整理 - 多 線 程 (六)
iOS | 面試知識整理 - 網絡相關 (七)
iOS | 面試知識整理 - 數據持久化 (八)
iOS | 面試知識整理 - Swift 基礎 (九)程序員
#include
來引入頭文件,若是須要防止重複導入須要使用#ifndef...#define...#endif
#import
來引入頭文件,能夠防止重複引入頭文件,能夠避免出現頭文件遞歸引入的現象。@class
僅用來告訴編譯器,有這樣一個類,編譯代碼時,不報錯,不會拷貝頭文件.若是須要使用該類或者內部方法須要使用 #import
導入id
能夠做爲方法的返回以及參數類型 也能夠用來定義變量instancetype
只能做爲函數或者方法的返回值@puplic面試
1.能夠在其餘類中訪問被@public修飾的成員變量
2.也能夠在本類中訪問被@public修飾的成員變量
3.能夠在子類中訪問父類中被@public修飾的成員變量
複製代碼
@private編程
1.不可能夠在其餘類中訪問被@private修飾的成員變量
2.也能夠在本類中訪問被@private修飾的成員變量
3.不能夠在子類中訪問父類中被@private修飾的成員變量
複製代碼
@protected (默認狀況下全部的實例變量都是protected)數組
1.不可能夠在其餘類中訪問被@protected修飾的成員變量
2.也能夠在本類中訪問被@protected修飾的成員變量
3.能夠在子類中訪問父類中被@protected修飾的成員變量
複製代碼
@package緩存
介於public和private之間的,若是是在其餘包中訪問就是private,在當前代碼中訪問就是public.
複製代碼
@property = ivar + getter + setter;
複製代碼
get
和set
方法聲明get和set
方法的實現atomic/nonatomic
若是不寫默認狀況爲 atomic
(系統會自動加上同步鎖,影響性能),在 iOS 開發中儘可能指定爲 nonatomic
,這樣有助於提升程序的性能readwrite(讀寫)、readooly (只讀)
retain、assign、strong、 weak、unsafe_unretained、copy
getter=、setter=
atomic
與nonatom
的主要區別就是系統自動生成的getter/setter
方法不同安全
atomic不是線程安全的ruby
weak
來解決, 好比:delegate
代理屬性, 自身已經對它進行一次強引用,沒有必要再強引用一次,此時也會使用 weak
,自定義 IBOutlet
控件屬性通常也使用 weak
;固然,也可使用 strong
,可是建議使用 weak
weak 和 assign 的不一樣點bash
weak
策略在屬性所指的對象遭到摧毀時,系統會將 weak
修飾的屬性對象的指針指 向 nil
,在 OC
給 nil
發消息是不會有什麼問題的; 若是使用 assign
策略在屬性所指 的對象遭到摧毀時,屬性對象指針還指向原來的對象,因爲對象已經被銷燬,這時候就產生了野指針,若是這時候在給此對象發送消息,很容形成程序奔潰 assigin
能夠用於修飾非 OC
對象,而 weak
必須用於 OC
對象weak
, 對於weak: 指明該對象並不負責保持delegate這個對象,delegate這個對象的銷燬由外部控制。assign
,也有weak的功效, 對於使用 assign 修飾delegate, 在對象釋放前,須要將 delegate 指針設置爲 nil,否則會產生野指針atomic,readwrite,assign
atomic,readwrite,strong
NSString、NSArray、NSDictionary 等等常用 copy
關鍵字,是由於他們有對應 的可變類型:NSMutableString、NSMutableArray、NSMutableDictionary
,爲確保 對象中的屬性值不會無心間變更,應該在設置新屬性值時拷貝一份,保護其封裝性block
也常用 copy
關鍵字,方法內部的 block
默認是 在棧區的,使用 copy
能夠把它放到堆區.block
使用 copy
仍是 strong
效果是同樣的,可是 建議寫上 copy
,由於這樣顯示告知調用者「編譯器會自動對 block
進行了 copy
操 做若想令本身所寫的對象具備拷貝功能,則需實現 NSCopying
協議。若是自定義的對象分爲可變版本與不可變版本,那麼就要同時實現 NSCopyiog 與 NSMutableCopying 協議
服務器
// 實現不可變版本拷貝
- (id)copyWithZone:(NSZone *)zone;
// 實現可變版本拷貝
- (id)mutableCopyWithZone:(NSZone *)zone;
// 重寫帶 copy 關鍵字的 setter
- (void)setName:(NSString *)name {
_name = [name copy];
}
複製代碼
方式一: 不是線程安全的,若是多線程須要加鎖
static ClassName *_instance;
+ (instancetype)sharedInstance{
@synchronized (self) {
if(!_instance) {
_instance = [self alloc]init];
}
}
return _instance;
}
複製代碼
方式二: 注意多線程問題 GCDdispatch_once 默認是線程安全的
static ClassName *_instance;
+ (instancetype)sharedInstance{
static dispatch_one_t oneToken;
dispatch_once(&onetoken,^{
_instance = [self alloc]init];
});
return _instance;
}
+ (instancetype)allocWithZone:(NSZone *) zone{
static dispatch_t onetoken;
dispatch_once(&oncetoken ^{
_instance = [super allocwithzone:zone];
})
retun _instance
}
複製代碼
好比:
NSObject *obj = [NSObject new];
[obj release]; // obj 指向的內存地址已經釋放了,
obj 若是再去訪問的話就是野指針錯誤了.
野指針錯誤形式在Xcode中一般表現爲:Thread 1:EXC_BAD_ACCESS,由於你訪問了一塊已經不屬於你的內存。
複製代碼
@property (copy, nonatomic) NSMutableArray * array
複製代碼
使用 copy 修飾,會生成不可變數組,在添加刪除數組元素時候會崩潰
@synthesize
,一個是@dynamic
。@synthesize 和@dynamic
都沒寫,那麼默認的就是@syntheszie var = _var
;@synthesize
的語義是若是你沒有手動實現 setter
方法和 getter
方法,那麼編譯器 會自動爲你加上這兩個方法@dynamic
告訴編譯器:屬性的 setter 與 getter
方法由用戶本身實現,不自動生成(固然對於 readonly 的屬性只需提供 getter 便可)setValue
仍然是調用了 setObject
方法, 若是參數 value 爲 nil,則會調用removeObject
移除這個鍵值對;setObjectForKey
是 NSMutableDictionary特有的, value 不能爲 nil,不然會崩潰setValueForKey
是KVC的,key 必須是字符串類型, setObject 的 key 能夠是任意類型[self performSelector:@selector(Delay) withObject:nil afterDelay:3.0f];
複製代碼
[NSTimer scheduledTimerWithTimeInterval:3.0f target:self selector:@selector(Delay) userInfo:nil repeats:NO];
複製代碼
[NSThread sleepForTimeInterval:3.0f];
複製代碼
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
[self Delay];
});
- (void)Delay {
NSLog(@"執行");
}
複製代碼
- (void)test_Function:(int(^)(int num)) block{}
複製代碼
(Procedure Oriented)
是一種以過程爲中心的編程思想。就是分析出解決問題所須要的步驟,而後用函數把這些步驟一步一步實現,使用的時候一個一個依次調用就能夠了。注重的是實現過程!「面向對象」是一種以對象爲中心的編程思想。
面向對象的三大特性:
繼承、封裝、多態
,從而使得面向對象編程更具備容易讓人接受,更貼近與人們的生活,比面向對象編程更加方便與快捷,必定程度上下降了程序員的工做量,使程序的可讀性也獲得了提升,代碼的效率也獲得了提升。OC的動態特性可從三方面:
cocoa touch底層技術架構 主要分爲4層:
謂詞(NSPredicate
)是OC針對數據集合的一種邏輯帥選條件,相似一個過濾器,簡單實實用代碼以下:
Person * p1 = [Person personWithName:@"alex" Age:20];
Person * p2 = [Person personWithName:@"alex1" Age:30];
Person * p3 = [Person personWithName:@"alex2" Age:10];
Person * p4 = [Person personWithName:@"alex3" Age:40];
Person * p5 = [Person personWithName:@"alex4" Age:80];
NSArray * persons = @[p1, p2, p3, p4, p5];
//定義謂詞對象,謂詞對象中包含了過濾條件
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"age < 30"];
//使用謂詞條件過濾數組中的元素,過濾以後返回查詢的結果
NSArray *array = [persons filteredArrayUsingPredicate:predicate];
複製代碼
類工廠方法就是用來快速建立對象的類方法, 他能夠直接返回一個初始化好的對象,具有如下特徵:
好比系統 UIButton 的buttonWithType 就是一個類工廠方法:
// 類工廠方法
+ (instancetype)buttonWithType:(UIButtonType)buttonType;
// 使用
+ UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom];
複製代碼
糖衣語法又叫作語法糖
或語法鹽
,是指在計算機語言中添加某種語法,這種語法對語言的功能沒有影響,但更方便程序員使用,增長程序的可讀性,減小代碼出錯機會
OC中的字面量,其實就是語法糖
NSNumber * number = @1;
NSArray * array = @[@1, @2, @3];
NSDictionary * dict = @{@"key":@"value"};
NSNumber * num1 = array[0];
NSString * value = dict[@"key"];
複製代碼
svn 和 git 都是用來對項目進行版本控制以及代碼管理的.能夠監測代碼及資源的更改變化.有利於實現高效的團隊合做;
svn 是集中式的,集中式是指只有一個遠程版本庫,git 是分佈式的,分佈式有本地和遠程版本庫,本地倉庫都保留了整個項目的完整備份;
若是存儲遠程版本庫的服務器掛了,全部人的代碼都沒法提交,甚至丟失版本庫, git則由於有本地版本庫而不會有這個問題。
因爲二者的架構不一樣,git 和 svn 的分支也是不一樣的, svn 的分支是一個完整的目錄,包含全部的實際文件,和中心倉庫是保持同步的,若是某個團隊成員建立新的分支,那麼會同步到全部的版本成員中,全部人都會收到影響. 而 git下建立的分支合併前是不會影響到任何人的.建立分支能夠在本地脫機進行任何操做.測試無誤後在合併到主分支,而後其餘成員才能夠看獲得.
OC中沒有二維數組, 能夠經過一維數組嵌套來實現二維數組;
// 字面量定義
NSArray * array = @[
@[@1,@2,@3,@4,@5],
@[@11,@12,@13,@14,@15],
@[@21,@22,@23,@24,@25],
@[@31,@32,@33,@34,@35],
@[@41,@42,@43,@44,@45],
];
// 訪問
NSLog(@"%@",array[1][1]);
複製代碼
CocoaPods 是一個 objc 的依賴管理工具,而其自己是利用 ruby 的依賴管理 gem 進行構建的
const
const常量修飾符,常用的字符串常量,通常是抽成宏,可是蘋果不推薦咱們抽成宏,推薦咱們使用const常量。
- const 做用:限制類型
- 使用const修飾基本變量, 兩種寫法效果一致 , b都是隻讀變量
const int b = 5;
int const b = 5;
- 使用const修飾指針變量的變量
第一種: const int *p = &a 和 int const *q = &a; 效果一致,*p 的值不能改,p 的指向能夠改;
第二種: int * const p = &a; 表示 p 的指向不能改,*p 的值能夠改
第三種:
const int * const p = &a; *p 值和 p 的指向都不能改
const 在*左邊, 指向可變, 值不可變
const 在*的右邊, 指向不可變, 值可變
const 在*的兩邊, 都不可變
複製代碼
宏
* 基本概念:宏是一種批量處理的稱謂。通常說來,宏是一種規則或模式,或稱語法替換 ,用於說明某一特定輸入(一般是字符串)如何根據預約義的規則轉換成對應的輸出(一般也是字符串)。這種替換在預編譯時進行,稱做宏展開。編譯器會在編譯前掃描代碼,若是遇到咱們已經定義好的宏那麼就會進行代碼替換,宏只會在內存中copy一份,而後全局替換,宏通常分爲對象宏和函數宏。 宏的弊端:若是代碼中大量的使用宏會使預編譯時間變長。
const與宏的區別?
* 編譯檢查 宏沒有編譯檢查,const有編譯檢查;
* 宏的好處 定義函數,方法 const不能夠;
* 宏的壞處 大量使用宏,會致使預編譯時間過長
複製代碼
static
* 修飾局部變量: 被static修飾局部變量,延長生命週期,跟整個應用程序有關,程序結束纔會銷燬,被 static 修飾局部變量,只會分配一次內存
* 修飾全局變量: 被static修飾全局變量,做用域會修改,也就是隻能在當前文件下使用
複製代碼
extern
聲明外部全局變量(只能用於聲明,不能用於定義)
經常使用用法(.h結合extern聯合使用)
若是在.h文件中聲明瞭extern全局變量,那麼在同一個類中的.m文件對全局變量的賦值必須是:數據類型+變量名(與聲明一致)=XXXX結構。而且在調用的時候,必須導入.h文件。代碼以下:
.h
@interface ExternModel : NSObject
extern NSString *lhString;
@end
.m
@implementation ExternModel
NSString *lhString=@"hello";
@end
調用的時候:例如:在viewController.m中調用,則能夠引入:ExternModel.h,不然沒法識別全局變量。固然也能夠經過不導入頭文件的方式進行調用(經過extern調用)。
複製代碼
常量指針本質是指針,常量修飾它,表示這個指針乃是一個指向常量的指針(變量)。
指針指向的對象是常量,那麼這個對象不能被更改。
指針常量的本質是一個常量,而用指針修飾它,那麼說明這個常量的值應該是一個指針。
指針常量的值是指針,這個值由於是常量,因此不能被賦值
指針函數
// 指針函數
int *sum(int a, int b){
int result = a + b;
int *c = &result;
return c;
}
int *p = sum(10, 20);
printf("sum:%d\n", *p);
複製代碼
函數指針
// 函數指針
int max(int a, int b){
return (a > b)?a:b;
}
int (*p)(int, int) = max;
int result = p(10, 20);
printf("result:%d\n", result);
複製代碼
#define Max(a,b) a>b?a:b
複製代碼
float a = 1;
float b = MIN(a++,1.5);
問 a= ? b = ?
答案: a = 3; b = 2
a++ 會後執行, a++在表達式出現了2次,得3, a++<1.5,返回a++,得2
// 擴展
float a = 1;
float b = [self getMix:a++ b:1.5];
- (CGFloat)getMix:(CGFloat ) a b:(CGFloat)b{
return a>b?a:b;
}
運行 a = 2; b =1;
複製代碼
其實呢做爲一個開發者,有一個學習的氛圍跟一個交流圈子特別重要,這是個人微信 你們有興趣能夠添加 邀請小夥伴們進入微信羣裏一塊兒 交流(想要進入的可加小編微信17512010526)
做者:LEON_iOS
連接:www.jianshu.com/p/51c9eb362…