如何實現視圖的變形?html
答:經過修改view的 transform 屬性便可。ios
在手勢對象基礎類UIGestureRecognizer的經常使用子類手勢類型中哪兩個手勢發生後,響應只會執行一次?面試
答:UITapGestureRecognizer,UISwipeGestureRecognizer是一次性手勢,手勢發生後,響應只會執行一次。算法
字符串經常使用方法:數據庫
NSString str = @"abc123"; NSArray arr = [str componentsSeparatedByString:@""]; //以目標字符串把原字符串分割成兩部分,存到數組中。@[@"abc", @"123"];編程
如何高性能的給 UIImageView 加個圓角?設計模式
* 很差的解決方案:使用下面的方式會`強制Core Animation提早渲染屏幕的離屏繪製, 而離屏繪製就會給性能帶來負面影響`,會有卡頓的現象出現。 self.view.layer.cornerRadius = 5.0f; self.view.layer.masksToBounds = YES;
* 正確的解決方案:使用繪圖技術
- (UIImage *)circleImage { // NO表明透明 UIGraphicsBeginImageContextWithOptions(self.size, NO, 0.0); // 得到上下文 CGContextRef ctx = UIGraphicsGetCurrentContext(); // 添加一個圓 CGRect rect = CGRectMake(0, 0, self.size.width, self.size.height); CGContextAddEllipseInRect(ctx, rect); // 裁剪 CGContextClip(ctx); // 將圖片畫上去 [self drawInRect:rect]; UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); // 關閉上下文 UIGraphicsEndImageContext(); return image;
}
* 還有一種方案:使用了貝塞爾曲線"切割"個這個圖片, 給UIImageView 添加了的圓角,其實也是經過繪圖技術來實現的。 UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
imageView.center = CGPointMake(200, 300); UIImage *anotherImage = [UIImage imageNamed:@"image"]; UIGraphicsBeginImageContextWithOptions(imageView.bounds.size, NO, 1.0);
[[UIBezierPath bezierPathWithRoundedRect:imageView.bounds
cornerRadius:50] addClip];
[anotherImage drawInRect:imageView.bounds];
imageView.image = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext();
[self.view addSubview:imageView];
複製代碼
1). 能夠經過純代碼或者xib的方式來封裝子控件 2). 創建一個跟view相關的模型,而後將模型數據傳給view,經過模型上的數據給view的子控件賦值 /**
* 純代碼初始化控件時必定會走這個方法
*/ - (instancetype)initWithFrame:(CGRect)frame { if(self = [super initWithFrame:frame]) {
[self setupUI];
} return self;
} /**
* 經過xib初始化控件時必定會走這個方法
*/ - (id)initWithCoder:(NSCoder *)aDecoder { if(self = [super initWithCoder:aDecoder]) {
[self setupUI];
} return self;
}
- (void)setupUI { // 初始化代碼 }
複製代碼
HTTP協議中 POST 方法和 GET 方法有那些區別?數組
1. GET用於向服務器請求數據,POST用於提交數據 2. GET請求,請求參數拼接形式暴露在地址欄,而POST請求參數則放在請求體裏面,所以GET請求不適合用於驗證密碼等操做 3. GET請求的URL有長度限制,POST請求不會有長度限制緩存
請簡單的介紹下APNS發送系統消息的機制安全
APNS優點:杜絕了相似安卓那種爲了接受通知不停在後臺喚醒程序保持長鏈接的行爲,由iOS系統和APNS進行長鏈接替代。 APNS的原理: 1). 應用在通知中心註冊,由iOS系統向APNS請求返回設備令牌(device Token) 2). 應用程序接收到設備令牌併發送給本身的後臺服務器 3). 服務器把要推送的內容和設備發送給APNS 4). APNS根據設備令牌找到設備,再由iOS根據APPID把推送內容展現
第一種:代理傳值
第二個控制器: @protocol WJSecondViewControllerDelegate - (void)changeText:(NSString*)text; @end @property(nonatomic,assign)iddelegate;
- (IBAction)buttonClick:(UIButton*)sender {
_str = sender.titleLabel.text;
[self.delegate changeText:sender.titleLabel.text];
[self.navigationController popViewControllerAnimated:YES];
}
第一個控制器:
- (IBAction)pushToSecond:(id)sender {
WJSecondViewController *svc = [[WJSecondViewController alloc]initWithNibName:@"WJSecondViewController" bundle:nil];
svc.delegate = self;
svc.str = self.navigationItem.title;
[self.navigationController pushViewController:svc animated:YES];
[svc release];
}
- (void)changeText:(NSString *)text{ self.navigationItem.title = text;
}
複製代碼
第二種:通知傳值
第一個控制器: //註冊監聽通知 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(limitDataForModel:) name:@"NOV" object:nil];
- (void)limitDataForModel:(NSNotification *)noti{ self.gamesInfoArray = noti.object;
}
第二個控制器: //發送通知 [[NSNotificationCenter defaultCenter] postNotificationName:@"NOV" object:gameArray];
複製代碼
第三種:單例傳值
Single是一個單例類,而且有一個字符串類型的屬性titleName
在第二個控制器:
- (IBAction)buttonClick:(UIButton*)sender {
Single *single = [Single sharedSingle];
single.titleName = sender.titleLabel.text;
[self.navigationController popViewControllerAnimated:YES];
}
第一個控制器:
- (void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
Single *single = [Single sharedSingle]; self.navigationItem.title = single.titleName;
}
複製代碼
第四種:block傳值
第二個控制器: @property (nonatomic,copy) void (^changeText_block)(NSString*);
- (IBAction)buttonClick:(UIButton*)sender {
_str = sender.titleLabel.text; self.changeText_block(sender.titleLabel.text);
[self.navigationController popViewControllerAnimated:YES];
}
第一個控制器:
- (IBAction)pushToSecond:(id)sender {
WJSecondViewController *svc = [[WJSecondViewController alloc]initWithNibName:@"WJSecondViewController" bundle:nil];
svc.str = self.navigationItem.title;
[svc setChangeText_block:^(NSString *str) {
>self.navigationItem.title = str;
}];
[self.navigationController pushViewController:svc animated:YES];
}
複製代碼
第五種:extern傳值
第二個控制器: extern NSString *btn;
- (IBAction)buttonClick:(UIButton*)sender {
btn = sender.titleLabel.text;
[self.navigationController popViewControllerAnimated:YES];
}
第一個控制器: NSString *btn = nil;
- (void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated]; self.navigationItem.title = btn;
}
複製代碼
第六種:KVO傳值
第一個控制器:
- (void)viewDidLoad {
[super viewDidLoad];
_vc =[[SecondViewController alloc]init]; //self監聽vc裏的textValue屬性 [_vc addObserver:self forKeyPath:@"textValue" options:0 context:nil];
}
第二個控制器:
- (IBAction)buttonClicked:(id)sender { self.textValue = self.textField.text;
[self.navigationController popViewControllerAnimated:YES];
}
複製代碼
公用延遲執行方法
- (void)delayMethod{ NSLog(@"delayMethodEnd");
[self performSelector:@selector(delayMethod) withObject:nil/*可傳任意類型參數*/ afterDelay:2.0];`注:此方法是一種非阻塞的執行方式,未找到取消執行的方法。 > 程序運行結束> 2015-08-31 10:56:59.361 CJDelayMethod[1080:39604] delayMethodStart2015-08-31 10:56:59.363 CJDelayMethod[1080:39604] nextMethod2015-08-31 10:57:01.364 CJDelayMethod[1080:39604] delayMethodEnd
複製代碼
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(delayMethod) userInfo:nil repeats:NO];`
注:此方法是一種非阻塞的執行方式,
取消執行方法:`- (void)invalidate;`便可
> 程序運行結束
> 2015-08-31 10:58:10.182 CJDelayMethod[1129:41106] delayMethodStart2015-08-31 10:58:10.183 CJDelayMethod[1129:41106] nextMethod2015-08-31 10:58:12.185 CJDelayMethod[1129:41106] delayMethodEnd
複製代碼
[NSThread sleepForTimeInterval:2.0]; 注:此方法是一種阻塞執行方式,建議放在子線程中執行,不然會卡住界面。但有時仍是須要阻塞執行,如進入歡迎界面須要沉睡3秒才進入主界面時。 沒有找到取消執行方式。 > 程序運行結束 > 2015-08-31 10:58:41.501 CJDelayMethod[1153:41698] delayMethodStart2015-08-31 10:58:43.507 CJDelayMethod[1153:41698] nextMethod
複製代碼
__block ViewController/*主控制器*/ *weakSelf = self; dispatch_time_t delayTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0/*延遲執行時間*/ * NSEC_PER_SEC)); dispatch_after(delayTime, dispatch_get_main_queue(), ^{ [weakSelf delayMethod]; }); 注:此方法能夠在參數中選擇執行的線程,是一種非阻塞執行方式。沒有找到取消執行方式。 > 程序運行結束 > 2015-08-31 10:59:21.652 CJDelayMethod[1181:42438] delayMethodStart2015-08-31 10:59:21.653 CJDelayMethod[1181:42438] nextMethod2015-08-31 10:59:23.653 CJDelayMethod[1181:42438] delayMethodEnd
複製代碼
完整代碼參見:
> // > // ViewController.m > // CJDelayMethod > // > // Created by 陳杰 on 8/31/15. > // Copyright (c) 2015 chenjie. All rights reserved. > // >
> # import "ViewController.h" >
> @interface ViewController () > @property (nonatomic, strong) NSTimer *timer;
> @end > @implementation ViewController* >
> *`- (void)viewDidLoad { `*
>
> *` [super viewDidLoad]; `*
>
> *` NSLog(@"delayMethodStart"); `*
>
> *` [self methodOnePerformSelector];// `* >
> *` [self methodTwoNSTimer];// `* >
> *` [self methodThreeSleep];//`* >
> *` [self methodFourGCD]; `*
>
> *` NSLog(@"nextMethod");`*
>
> *`}`*
>
> *`- (void)methodFiveAnimation{ `*
>
> *` [UIView animateWithDuration:0 delay:2.0 options:UIViewAnimationOptionAllowUserInteraction animations:^{ } completion:^(BOOL finished) { `*
>
> *` [self delayMethod]; `*
>
> *` }];`*
>
> *`}`
> `- (void)methodFourGCD{ `*
>
> *` __block ViewController`*`weakSelf = self; dispatch_time_t delayTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)); dispatch_after(delayTime, dispatch_get_main_queue(), ^{ `
>
> ` [weakSelf delayMethod]; `
>
> ` });`
>
> `}`
>
> `- (void)methodThreeSleep{ `
>
> ` [NSThread sleepForTimeInterval:2.0];`
>
> `}`
>
> `- (void)methodTwoNSTimer{`
>
> ` NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(delayMethod) userInfo:nil repeats:NO];`
>
> `}`
>
> `- (void)methodOnePerformSelector{`
>
> ` [self performSelector:@selector(delayMethod) withObject:nil/*可傳任意類型參數*/ afterDelay:2.0];`
>
> `}`
>
> `- (void)delayMethod{`
>
> ` NSLog(@"delayMethodEnd");`
>
> `}`
> `- (void)didReceiveMemoryWarning { `
>
> ` [super didReceiveMemoryWarning]; `
>
> ` // Dispose of any resources that can be recreated.` >
> `}`
>
> `@end`
複製代碼
NSPersistentStoreCoordinator , NSManaged0bjectContext 和NSManaged0bject中的那些須要在線程中建立或者傳遞
答:NSPersistentStoreCoordinator是持久化存儲協調者,主要用於協調託管對象上下文和持久化存儲區之間的關係。NSManagedObjectContext使用協調者的託管對象模型將數據保存到數據庫,或查詢數據。
您是否作過一部的網絡處理和通信方面的工做?若是有,能具體介紹一下實現策略麼?
答:使用NSOperation發送異步網絡請求,使用NSOperationQueue管理線程數目及優先級,底層是用NSURLConnetion,
你使用過Objective-C的運行時編程(Runtime Programming)麼?若是使用過,你用它作了什麼?你還能記得你所使用的相關的頭文件或者某些方法的名稱嗎?
答:Objecitve-C的重要特性是Runtime(運行時),在#import 下能看到相關的方法,用過objc_getClass()和class_copyMethodList()獲取過私有API;使用 Method method1 = class_getInstanceMethod(cls, sel1); Method method2 = class_getInstanceMethod(cls, sel2); method_exchangeImplementations(method1, method2); 代碼交換兩個方法,在寫unit test時使用到。
Core開頭的系列的內容。是否使用過CoreAnimation和CoreGraphics。UI框架和CA,CG框架的聯繫是什麼?分別用CA和CG作過些什麼動畫或者圖像上的內容。(有須要的話還能夠涉及Quartz的一些內容)
答:UI框架的底層有CoreAnimation,CoreAnimation的底層有CoreGraphics。
UIKit Core Animation Core Graphics Graphics Hardware 使用CA作過menu菜單的展開收起(太遜了)
是否使用過CoreText或者CoreImage等?若是使用過,請談談你使用CoreText或者CoreImage的體驗。
答:CoreText能夠解決複雜文字內容排版問題。CoreImage能夠處理圖片,爲其添加各類效果。體驗是很強大,挺複雜的。
自動釋放池是什麼,如何工做
答:當您向一個對象發送一個autorelease消息時,Cocoa就會將該對象的一個引用放入到最新的自動釋放.它仍然是個OC的對象,所以自動釋放池定義的做用域內的其它對象能夠向它發送消息。當程序執行到做用域結束的位置時,自動釋放池就會被釋放,池中的全部對象也就被釋放。
NSNotification和KVO的區別和用法是什麼?何時應該使用通知,何時應該使用KVO,它們的實現上有什麼區別嗎?若是用protocol和delegate(或者delegate的Array)來實現相似的功能可能嗎?若是可能,會有什麼潛在的問題?若是不能,爲何?(雖然protocol和delegate這種東西面試已經面爛了…)
答:NSNotification是通知模式在iOS的實現,KVO的全稱是鍵值觀察(Key-value observing),其是基於KVC(key-value coding)的,KVC是一個經過屬性名訪問屬性變量的機制。例如將Module層的變化,通知到多個Controller對象時,可使用NSNotification;若是是隻須要觀察某個對象的某個屬性,可使用KVO。 對於委託模式,在設計模式中是對象適配器模式,其是delegate是指向某個對象的,這是一對一的關係,而在通知模式中,每每是一對多的關係。委託模式,從技術上能夠如今改變delegate指向的對象,但不建議這樣作,會讓人迷惑,若是一個delegate對象不斷改變,指向不一樣的對象。
你用過NSOperationQueue麼?若是用過或者瞭解的話,你爲何要使用NSOperationQueue,實現了什麼?請描述它和G.C.D的區別和相似的地方(提示:能夠從二者的實現機制和適用範圍來描述)。
答:使用NSOperationQueue用來管理子類化的NSOperation對象,控制其線程併發數目。GCD和NSOperation均可以實現對線程的管理,區別是 NSOperation和NSOperationQueue是多線程的面向對象抽象。項目中使用NSOperation的優勢是NSOperation是對線程的高度抽象,在項目中使用它,會使項目的程序結構更好,子類化NSOperation的設計思路,是具備面向對象的優勢(複用、封裝),使得實現是多線程支持,而接口簡單,建議在複雜項目中使用。 項目中使用GCD的優勢是GCD自己很是簡單、易用,對於不復雜的多線程操做,會節省代碼量,而Block參數的使用,會是代碼更爲易讀,建議在簡單項目中使用。
既然提到G.C.D,那麼問一下在使用G.C.D以及block時要注意些什麼?它們兩是一回事兒麼?block在ARC中和傳統的MRC中的行爲和用法有沒有什麼區別,須要注意些什麼?
答:使用block是要注意,若將block作函數參數時,須要把它放到最後,GCD是Grand Central Dispatch,是一個對線程開源類庫,而Block是閉包,是可以讀取其餘函數內部變量的函數。
對於Objective-C,你認爲它最大的優勢和最大的不足是什麼?對於不足之處,如今有沒有可用的方法繞過這些不足來實現需求。若是能夠的話,你有沒有考慮或者實踐太重新實現OC的一些功能,若是有,具體會如何作?
> 答:最大的優勢是它的運行時特性,不足是沒有命名空間,對於命名衝突,可使用長命名法或特殊前綴解決,若是是引入的第三方庫之間的命名衝突,可使用link命令及flag解決衝突。
複製代碼
> 答:抽象和封裝,方便使用。首先是對問題有充分的瞭解,好比構建一個文件解壓壓縮框架,從使用者的角度出發,只需關注發送給框架一個解壓請求,框架完成複雜文件的解壓操做,而且在適當的時候通知給是哦難過者,如解壓完成、解壓出錯等。在框架內部去構建對象的關係,經過抽象讓其更爲健壯、便於更改。其次是API的說明文檔。
複製代碼
AFNetworking 底層原理分析
AFNetworking主要是對NSURLSession和NSURLConnection(iOS9.0廢棄)的封裝,其中主要有如下類: 1). AFHTTPRequestOperationManager:內部封裝的是 NSURLConnection, 負責發送網絡請求, 使用最多的一個類。(3.0廢棄) 2). AFHTTPSessionManager:內部封裝是 NSURLSession, 負責發送網絡請求,使用最多的一個類。 3). AFNetworkReachabilityManager:實時監測網絡狀態的工具類。當前的網絡環境發生改變以後,這個工具類就能夠檢測到。 4). AFSecurityPolicy:網絡安全的工具類, 主要是針對 HTTPS 服務。 5). AFURLRequestSerialization:序列化工具類,基類。上傳的數據轉換成JSON格式 (AFJSONRequestSerializer).使用很少。 6). AFURLResponseSerialization:反序列化工具類;基類.使用比較多: 7). AFJSONResponseSerializer; JSON解析器,默認的解析器. 8). AFHTTPResponseSerializer; 萬能解析器; JSON和XML以外的數據類型,直接返回二進 制數據.對服務器返回的數據不作任何處理. 9). AFXMLParserResponseSerializer; XML解析器;
描述下SDWebImage裏面給UIImageView加載圖片的邏輯
SDWebImage 中爲 UIImageView 提供了一個分類UIImageView+WebCache.h, 這個分類中有一個最經常使用的接口sd_setImageWithURL:placeholderImage:,會在真實圖片出現前會先顯示佔位圖片,當真實圖片被加載出來後再替換佔位圖片。 加載圖片的過程大體以下: 1.首先會在 SDWebImageCache 中尋找圖片是否有對應的緩存, 它會以url 做爲數據的索引先在內存中尋找是否有對應的緩存 2.若是緩存未找到就會利用經過MD5處理過的key來繼續在磁盤中查詢對應的數據, 若是找到了, 就會把磁盤中的數據加載到內存中,並將圖片顯示出來 3.若是在內存和磁盤緩存中都沒有找到,就會向遠程服務器發送請求,開始下載圖片 4.下載後的圖片會加入緩存中,並寫入磁盤中 5.整個獲取圖片的過程都是在子線程中執行,獲取到圖片後回到主線程將圖片顯示出來 SDWebImage原理: 調用類別的方法: 1. 從內存(字典)中找圖片(當這個圖片在本次使用程序的過程當中已經被加載過),找到直接使用。 2. 從沙盒中找(當這個圖片在以前使用程序的過程當中被加載過),找到使用,緩存到內存中。 3. 從網絡上獲取,使用,緩存到內存,緩存到沙盒。
友盟統計接口統計的全部功能
APP啓動速度,APP停留頁面時間等
1.不用中間變量,用兩種方法交換A和B的值
// 1.中間變量 void swap(int a, int b) { int temp = a; a = b; b = temp; } // 2.加法 void swap(int a, int b) { a = a + b; b = a - b; a = a - b; } // 3.異或(相同爲0,不一樣爲1\. 能夠理解爲不進位加法) void swap(int a, int b) { a = a ^ b; b = a ^ b; a = a ^ b; }
複製代碼
2.求最大公約數
/** 1.直接遍歷法 */ int maxCommonDivisor(int a, int b) { int max = 0; for (int i = 1; i <=b; i++) { if (a % i == 0 && b % i == 0) { max = I; } } return max; } /** 2.展轉相除法 */ int maxCommonDivisor(int a, int b) { int r; while(a % b > 0) { r = a % b; a = b; b = r; } return b; } // 擴展:最小公倍數 = (a * b)/最大公約數
複製代碼
3.模擬棧操做
/** * 棧是一種數據結構,特色:先進後出 * 練習:使用全局變量模擬棧的操做 */ #include #include #include //保護全局變量:在全局變量前加static後,這個全局變量就只能在本文件中使用 static int data[1024];//棧最多能保存1024個數據 static int count = 0;//目前已經放了多少個數(至關於棧頂位置) //數據入棧 push void push(int x){ assert(!full());//防止數組越界 data[count++] = x; } //數據出棧 pop int pop(){ assert(!empty()); return data[--count]; } //查看棧頂元素 top int top(){ assert(!empty()); return data[count-1]; } //查詢棧滿 full bool full() { if(count >= 1024) { return 1; } return 0; } //查詢棧空 empty bool empty() { if(count <= 0) { return 1; } return 0; } int main(){ //入棧 for (int i = 1; i <= 10; i++) { push(i); } //出棧 while(!empty()){ printf("%d ", top()); //棧頂元素 pop(); //出棧 } printf("\n"); return 0; }
複製代碼
4.排序算法
選擇排序、冒泡排序、插入排序三種排序算法能夠總結爲以下:
* 都將數組分爲已排序部分和未排序部分。 1\. 選擇排序將已排序部分定義在左端,而後選擇未排序部分的最小元素和未排序部分的第一個元素交換。 2\. 冒泡排序將已排序部分定義在右端,在遍歷未排序部分的過程執行交換,將最大元素交換到最右端。 3\. 插入排序將已排序部分定義在左端,將未排序部分元的第一個元素插入到已排序部分合適的位置。
複製代碼
* 選擇排序 /** * 【選擇排序】:最值出如今起始端 * * 第1趟:在n個數中找到最小(大)數與第一個數交換位置 * 第2趟:在剩下n-1個數中找到最小(大)數與第二個數交換位置 * 重複這樣的操做...依次與第三個、第四個...數交換位置 * 第n-1趟,最終可實現數據的升序(降序)排列。 * / void selectSort(int arr, int length) { for (int i = 0; i < length - 1; i++) { //趟數 for (int j = i + 1; j < length; j++) { //比較次數 if (arr[i] > arr[j]) { int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } } } } * 冒泡排序 / * 【冒泡排序】:相鄰元素兩兩比較,比較完一趟,最值出如今末尾 * 第1趟:依次比較相鄰的兩個數,不斷交換(小數放前,大數放後)逐個推動,最值最後出如今第n個元素位置 * 第2趟:依次比較相鄰的兩個數,不斷交換(小數放前,大數放後)逐個推動,最值最後出如今第n-1個元素位置 * …… …… * 第n-1趟:依次比較相鄰的兩個數,不斷交換(小數放前,大數放後)逐個推動,最值最後出如今第2個元素位置 */ void bublleSort(int *arr, int length) { for(int i = 0; i < length - 1; i++) { //趟數 for(int j = 0; j < length - i - 1; j++) { //比較次數 if(arr[j] > arr[j+1]) { int temp = arr[j]; arr[j] = arr[j+1]; arr[j+1] = temp; } } } }
參考: 8大排序算法圖文講解 經常使用算法OC實現
5.折半查找(二分查找)
/** * 折半查找:優化查找時間(不用遍歷所有數據) * * 折半查找的原理: * 1> 數組必須是有序的 * 2> 必須已知min和max(知道範圍) * 3> 動態計算mid的值,取出mid對應的值進行比較 * 4> 若是mid對應的值大於要查找的值,那麼max要變小爲mid-1 * 5> 若是mid對應的值小於要查找的值,那麼min要變大爲mid+1 * */ // 已知一個有序數組, 和一個key, 要求從數組中找到key對應的索引位置 int findKey(int *arr, int length, int key) { int min = 0, max = length - 1, mid; while (min <= max) { mid = (min + max) / 2; //計算中間值 if (key > arr[mid]) { min = mid + 1; } else if (key < arr[mid]) { max = mid - 1; } else { return mid; } } return -1; }
複製代碼
參考:請Review下面的代碼,並根據iOS的編碼規範作出正確的修改
1.在 Objective-C 中,enum 建議使用NS_ENUM和NS_OPTIONS宏來定義枚舉類型。
//定義一個枚舉(比較嚴密) typedef NS_ENUM(NSInteger, BRUserGender) {
BRUserGenderUnknown, // 未知 BRUserGenderMale, // 男性 BRUserGenderFemale, // 女性 BRUserGenderNeuter // 無性 }; @interface BRUser : NSObject @property (nonatomic, readonly, copy) NSString *name; @property (nonatomic, readonly, assign) NSUInteger age; @property (nonatomic, readonly, assign) BRUserGender gender;
- (instancetype)initWithName:(NSString *)name age:(NSUInteger)age gender:(BRUserGender)gender; @end //說明: //既然該類中已經有一個「初始化方法」 ,用於設置 name、age 和 gender 的初始值: 那麼在設計對應 @property 時就應該儘可能使用不可變的對象:其三個屬性都應該設爲「只讀」。用初始化方法設置好屬性值以後,就不能再改變了。 //屬性的參數應該按照下面的順序排列: (原子性,讀寫,內存管理)
複製代碼
2.避免使用C語言中的基本數據類型,建議使用 Foundation 數據類型,對應關係以下:
int -> NSInteger unsigned -> NSUInteger float -> CGFloat 動畫時間 -> NSTimeInterval
HomeKit,是蘋果2014年發佈的智能家居平臺。
什麼是 OpenGL、Quartz 2D?
Quatarz 2d 是Apple提供的基本圖形工具庫。只是適用於2D圖形的繪製。 OpenGL,是一個跨平臺的圖形開發庫。適用於2D和3D圖形的繪製。
ffmpeg框架:
ffmpeg 是音視頻處理工具,既有音視頻編碼解碼功能,又能夠做爲播放器使用。
談談 UITableView 的優化
1). 正確的複用cell; 2). 設計統一規格的Cell; 3). 提早計算並緩存好高度(佈局),由於heightForRowAtIndexPath:是調用最頻繁的方法; 4). 異步繪製,遇到複雜界面,遇到性能瓶頸時,可能就是突破口; 5). 滑動時按需加載,這個在大量圖片展現,網絡加載的時候很管用! 6). 減小子視圖的層級關係; 7). 儘可能使全部的視圖不透明化以及作切圓操做; 8). 不要動態的add 或者 remove 子控件。最好在初始化時就添加完,而後經過hidden來控制是否顯示; 9). 使用調試工具分析問題。
如何實行cell的動態的行高
若是但願每條數據顯示自身的行高,必須設置兩個屬性,1.預估行高,2.自定義行高。 設置預估行高 tableView.estimatedRowHeight = 200。 設置定義行高 tableView.estimatedRowHeight = UITableViewAutomaticDimension。 若是要讓自定義行高有效,必須讓容器視圖有一個自下而上的約束。
說說你對 block 的理解
棧上的自動複製到堆上,block 的屬性修飾符是 copy,循環引用的原理和解決方案。 block的循環引用;block的代碼實現;爲何會形成循環引用;block是如何強引用self的; 參考:Block 代碼塊中用到了self引用問題,致使循環引用
什麼是野指針、空指針?
野指針:不知道指向了哪裏的指針叫野指針。即指針指向不肯定,指針存的地址是一個垃圾值,未初始化。 空指針:不指向任何位置的指針叫空指針。即指針沒有指向,指針存的地址是一個空地址,NULL。
什麼是 OOA / OOD / OOP ?
OOA(Object Oriented Analysis) --面向對象分析 OOD(Object Oriented Design) --面向對象設計 OOP(Object Oriented Programming)--面向對象編程
多線程是什麼
多線程是個複雜的概念,按字面意思是同步完成多項任務,提升了資源的使用效率,從硬件、操做系統、應用軟件不一樣的角度去看,多線程被賦予不一樣的內涵,對於硬件,如今市面上多數的CPU都是多核的,多核的CPU運算多線程更爲出色;從操做系統角度,是多任務,如今用的主流操做系統都是多任務的,能夠一邊聽歌、一邊寫博客;對於應用來講,多線程可讓應用有更快的迴應,能夠在網絡下載時,同時響應用戶的觸摸操做。在iOS應用中,對多線程最初的理解,就是併發,它的含義是原來先作燒水,再摘菜,再炒菜的工做,會變成燒水的同時去摘菜,最後去炒菜。
iOS 中的多線程
> iOS中的多線程,是Cocoa框架下的多線程,經過Cocoa的封裝,可讓咱們更爲方便的使用線程,作過C++的同窗可能會對線程有更多的理解,好比線程的創立,信號量、共享變量有認識,Cocoa框架下會方便不少,它對線程作了封裝,有些封裝,可讓咱們建立的對象,自己便擁有線程,也就是線程的對象化抽象,從而減小咱們的工程,提供程序的健壯性。
>
> GCD是(Grand Central Dispatch)的縮寫 ,從系統級別提供的一個易用地多線程類庫,具備運行時的特色,能充分利用多核心硬件。GCD的API接口爲C語言的函數,函數參數中多數有Block,關於Block的使用參看這裏,爲咱們提供強大的「接口」,對於GCD的使用參見本文
>
> NSOperation與Queue
>
> NSOperation是一個抽象類,它封裝了線程的細節實現,咱們能夠經過子類化該對象,加上NSQueue來同面向對象的思惟,管理多線程程序。具體可參看這裏:一個基於NSOperation的多線程網絡訪問的項目。
>
> NSThread
>
> NSThread是一個控制線程執行的對象,它不如NSOperation抽象,經過它咱們能夠方便的獲得一個線程,並控制它。但NSThread的線程之間的併發控制,是須要咱們本身來控制的,能夠經過NSCondition實現。
>
> 參看 iOS多線程編程之NSThread的使用
>
> 其餘多線程
>
> 在Cocoa的框架下,通知、Timer和異步函數等都有使用多線程,(待補充).
複製代碼
> 項目中使用NSOperation的優勢是NSOperation是對線程的高度抽象,在項目中使用它,會使項目的程序結構更好,子類化NSOperation的設計思路,是具備面向對象的優勢(複用、封裝),使得實現是多線程支持,而接口簡單,建議在複雜項目中使用。
>
> 項目中使用GCD的優勢是GCD自己很是簡單、易用,對於不復雜的多線程操做,會節省代碼量,而Block參數的使用,會是代碼更爲易讀,建議在簡單項目中使用。
複製代碼
> * KVO就是cocoa框架實現的觀察者模式,通常同KVC搭配使用,經過KVO能夠監測一個值的變化,好比View的高度變化。是一對多的關係,一個值的變化會通知全部的觀察者。
> * NSNotification是通知,也是一對多的使用場景。在某些狀況下,KVO和NSNotification是同樣的,都是狀態變化以後告知對方。NSNotification的特色,就是須要被觀察者先主動發出通知,而後觀察者註冊監聽後再來進行響應,比KVO多了發送通知的一步,可是其優勢是監聽不侷限於屬性的變化,還能夠對多種多樣的狀態變化進行監聽,監聽範圍廣,使用也更靈活。
>
> * delegate 是代理,就是我不想作的事情交給別人作。好比狗須要吃飯,就經過delegate通知主人,主人就會給他作飯、盛飯、倒水,這些操做,這些狗都不須要關心,只須要調用delegate(代理人)就能夠了,由其餘類完成所須要的操做。因此delegate是一對一關係。
>
> * block是delegate的另外一種形式,是函數式編程的一種形式。使用場景跟delegate同樣,相比delegate更靈活,並且代理的實現更直觀。
>
> * KVO通常的使用場景是數據,需求是數據變化,好比股票價格變化,咱們通常使用KVO(觀察者模式)。delegate通常的使用場景是行爲,需求是須要別人幫我作一件事情,好比買賣股票,咱們通常使用delegate。
> Notification通常是進行全局通知,好比利好消息一出,通知你們去買入。delegate是強關聯,就是委託和代理雙方互相知道,你委託別人買股票你就須要知道經紀人,經紀人也不要知道本身的顧客。Notification是弱關聯,利好消息發出,你不須要知道是誰發的也能夠作出相應的反應,同理發消息的人也不須要知道接收的人也能夠正常發出消息。
複製代碼
* GCD方法,經過向主線程隊列發送一個block塊,使block裏的方法能夠在主線程中執行。 dispatch_async(dispatch_get_main_queue(), ^{ //須要執行的方法 });
* NSOperation 方法 NSOperationQueue *mainQueue = [NSOperationQueue mainQueue]; //主隊列 NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{ //須要執行的方法 }];
[mainQueue addOperation:operation];
* NSThread 方法
[self performSelector:@selector(method) onThread:[NSThread mainThread] withObject:nil waitUntilDone:YES modes:nil];
[self performSelectorOnMainThread:@selector(method) withObject:nil waitUntilDone:YES];
[[NSThread mainThread] performSelector:@selector(method) withObject:nil];
* RunLoop方法
[[NSRunLoop mainRunLoop] performSelector:@selector(method) withObject:nil];
複製代碼
如何讓計時器調用一個類方法
- 計時器只能調用實例方法,可是能夠在這個實例方法裏面調用靜態方法。
- 使用計時器須要注意,計時器必定要加入RunLoop中,而且選好model才能運行。scheduledTimerWithTimeInterval方法建立一個計時器並加入到RunLoop中因此能夠直接使用。
- 若是計時器的repeats選擇YES說明這個計時器會重複執行,必定要在合適的時機調用計時器的invalid。不能在dealloc中調用,由於一旦設置爲repeats 爲yes,計時器會強持有self,致使dealloc永遠不會被調用,這個類就永遠沒法被釋放。好比能夠在viewDidDisappear中調用,這樣當類須要被回收的時候就能夠正常進入dealloc中了。
[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timerMethod) userInfo:nil repeats:YES];
-(void)timerMethod
{ //調用類方法 [[self class] staticMethod];
}
-(void)invalid
{
[timer invalid];
timer = nil;
}
複製代碼
如何重寫類方法
一、在子類中實現一個同基類名字同樣的靜態方法
二、在調用的時候不要使用類名調用,而是使用[self class]的方式調用。原理,用類名調用是早綁定,在編譯期綁定,用[self class]是晚綁定,在運行時決定調用哪一個方法。
NSTimer建立後,會在哪一個線程運行
用scheduledTimerWithTimeInterval建立的,在哪一個線程建立就會被加入哪一個線程的RunLoop中就運行在哪一個線程
本身建立的Timer,加入到哪一個線程的RunLoop中就運行在哪一個線程。
id和NSObject*的區別
typedef struct objc_object *id
複製代碼
id能夠理解爲指向對象的指針。全部oc的對象 id均可以指向,編譯器不會作類型檢查,id調用任何存在的方法都不會在編譯階段報錯,固然若是這個id指向的對象沒有這個方法,該崩潰仍是會崩潰的。
NSObject *指向的必須是NSObject的子類,調用的也只能是NSObjec裏面的方法不然就要作強制類型轉換。
不是全部的OC對象都是NSObject的子類,還有一些繼承自NSProxy。NSObject *可指向的類型是id的子集。
static關鍵字的做用
回答一:
1.在函數體內定義的static他的做用域爲該函數體,該變量在內存中只被分配一次,所以,其值在下次調用時仍維持上次的值不變; 2.在模塊內的static全局變量能夠被模塊內全部函數訪問,可是不能被模塊外的其餘函數訪問; 3.在模塊內的staic全局變量能夠被這一模塊內的其餘函數調用,這個函數的使用範圍被限制在這個模塊內; 4.在類中的static成員變量屬於整個類所擁有,對類的全部對象只有一份拷貝,也就是說只要是該類的對象,那麼該對象的中被static修飾的成員變量都指向同一塊地址。
回答二:
修飾局部變量: 1.延長局部變量的生命週期,程序結束纔會銷燬。 2.局部變量只會生成一分內存,只會初始化一次。 3.改變局部變量的做用域。 修飾全局變量: 1.只能在本文件中訪問,修改全局變量的做用域,生命週期不會改 2.避免重複定義全局變量
在OC中static關鍵字使用誤區
1.使用static修飾實例變量是不被容許的 2.使用static修飾了方法,也是錯誤的
優勢:
一、簡潔的語法 二、更強的類型安全 三、函數式編程的支持 Swift 語言自己提供了對函數式編程的支持。 Objc 自己是不支持的,可是能夠經過引入 ReactiveCocoa 這個庫來支持函數式編程。 四、編寫 OS X 下的自動化腳本
缺點
一、App體積變大 使用Swift 後, App 體積大概增長 5-8 M 左右,對體積大小敏感的慎用。 體積變大的緣由是由於 Swift 還在變化,因此 Apple 沒有在 iOS 系統裏放入 Swift 的運行庫,反而是每一個 App 裏都要包含其對應的 Swift 運行庫。 二、Xcode 支持不夠好 若是你是使用 Xcode常常卡住或者崩潰想必你是確定碰到過了,這個是目前使用 Swift 最讓人頭疼的事情,即便是到如今XCode 9, 有時候也會遇到這種問題,因此要看你的承受力了…… 三、第三方庫的支持不夠多 目前確實 Swift 編寫的第三方庫確實很少,但能夠經過橋接的方式來使用 Objc 的三方庫,基本上沒有太大問題。如今已經改善不少了… 四、語言版本更新帶來的編譯問題 語言自己還在發展,因此每次版本更新後都會出現編譯不過的狀況(至少到目前爲止仍是),可是自從 4.0 版本發佈後,改動沒有 beta 時候那麼大了,並且根據 Xcode 提示基本就能夠解決語法變更致使的編譯問題了。
#小編這裏推薦一個羣:691040931 裏面有大量的書籍和麪試資料,不少的iOS開發者都在裏面交流技術
本文轉載於 blog.csdn.net/wujakf/arti…