Size Classes 具體使用
UIView和CALayer是什么關系?UIView顯示在屏幕上歸功于CALayer,,通過調用drawRect方法來渲染自身的內容,,調節(jié)CALayer屬性可以調整UIView的外觀, UIView繼承自UIResponder,,比起CALayer可以響應用戶事件,,Xcode6之后可以方便的通過視圖調試功能查看圖層之間的關系 UIView是iOS系統(tǒng)中界面元素的基礎,所有的界面元素都繼承自它,。它內部是由Core Animation來實現(xiàn)的,,它真正的繪圖部分,是由一個叫CALayer(Core Animation Layer)的類來管理,。UIView本身,,更像是一個CALayer的管理器,訪問它的跟繪圖和坐標有關的屬性,,如frame,,bounds等,實際上內部都是訪問它所在CALayer的相關屬性 UIView有個layer屬性,,可以返回它的主CALayer實例,,UIView有一個layerClass方法,返回主layer所使用的類,,UIView的子類,,可以通過重載這個方法,來讓UIView使用不同的CALayer來顯示,,如:
- (class) layerClass { // 使某個UIView的子類使用GL來進行繪制 return ([CAEAGLLayer class]); }
grayCover = [[CALayer alloc]init]; grayCover.backgroudColor = [[UIColor blackColor]colorWithAlphaComponent:0.2].CGColor; [self.layer addSubLayer:grayCover];
loadView的作用?loadView用來自定義view,,只要實現(xiàn)了這個方法,,其他通過xib或storyboard創(chuàng)建的view都不會被加載 看懂控制器view創(chuàng)建的這個圖就行
IBOutlet連出來的視圖屬性為什么可以被設置成weak?
IB中User Defined Runtime Attributes如何使用?User Defined Runtime Attributes是一個不被看重但功能非常強大的的特性,,它能夠通過KVC的方式配置一些你在interface builder中不能配置的屬性 當你希望在IB中作盡可能多得事情,,這個特性能夠幫助你編寫更加輕量級的viewcontroller
沙盒目錄結構是怎樣的?各自用于那些場景,?Application:存放程序源文件,,上架前經過數(shù)字簽名,上架后不可修改 Documents:常用目錄,,iCloud備份目錄,,存放數(shù)據(jù) Library tmp:存放臨時文件,,不會被備份,,而且這個文件下的數(shù)據(jù)有可能隨時被清除的可能
pushViewController和presentViewController有什么區(qū)別
請簡述UITableView的復用機制每次創(chuàng)建cell的時候通過dequeueReusableCellWithIdentifier:方法創(chuàng)建cell,,它先到緩存池中找指定標識的cell,,如果沒有就直接返回nil 如果沒有找到指定標識的cell,,那么會通過initWithStyle:reuseIdentifier:創(chuàng)建一個cell 當cell離開界面就會被放到緩存池中,以供下次復用
如何高性能的給 UIImageView 加個圓角?不好的解決方案 使用下面的方式會強制Core Animation提前渲染屏幕的離屏繪制, 而離屏繪制就會給性能帶來負面影響,,會有卡頓的現(xiàn)象出現(xiàn) self.view.layer.cornerRadius = 5; 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 *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];
使用drawRect有什么影響?drawRect方法依賴Core Graphics框架來進行自定義的繪制 缺點:它處理touch事件時每次按鈕被點擊后,,都會用setNeddsDisplay進行強制重繪,;而且不止一次,每次單點事件觸發(fā)兩次執(zhí)行,。這樣的話從性能的角度來說,,對CPU和內存來說都是欠佳的,。特別是如果在我們的界面上有多個這樣的UIButton實例,那就會很糟糕了 這個方法的調用機制也是非常特別. 當你調用 setNeedsDisplay 方法時, UIKit 將會把當前圖層標記為dirty,但還是會顯示原來的內容,直到下一次的視圖渲染周期,才會將標記為 dirty 的圖層重新建立Core Graphics上下文,然后將內存中的數(shù)據(jù)恢復出來, 再使用 CGContextRef 進行繪制
描述下SDWebImage里面給UIImageView加載圖片的邏輯SDWebImage 中為 UIImageView 提供了一個分類UIImageView WebCache.h, 這個分類中有一個最常用的接口sd_setImageWithURL:placeholderImage:,,會在真實圖片出現(xiàn)前會先顯示占位圖片,,當真實圖片被加載出來后在替換占位圖片 加載圖片的過程大致如下: 首先會在 SDWebImageCache 中尋找圖片是否有對應的緩存, 它會以url 作為數(shù)據(jù)的索引先在內存中尋找是否有對應的緩存 如果緩存未找到就會利用通過MD5處理過的key來繼續(xù)在磁盤中查詢對應的數(shù)據(jù), 如果找到了, 就會把磁盤中的數(shù)據(jù)加載到內存中,并將圖片顯示出來 如果在內存和磁盤緩存中都沒有找到,,就會向遠程服務器發(fā)送請求,,開始下載圖片 下載后的圖片會加入緩存中,并寫入磁盤中 整個獲取圖片的過程都是在子線程中執(zhí)行,,獲取到圖片后回到主線程將圖片顯示出來
設計個簡單的圖片內存緩存器
控制器的生命周期// 自定義控制器view,這個方法只有實現(xiàn)了才會執(zhí)行 - (void)loadView { self.view = [[UIView alloc] init]; self.view.backgroundColor = [UIColor orangeColor]; } // view是懶加載,,只要view加載完畢就調用這個方法 - (void)viewDidLoad { [super viewDidLoad];
NSLog(@'%s',__func__); }
// view即將顯示 - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated];
NSLog(@'%s',__func__); } // view即將開始布局子控件 - (void)viewWillLayoutSubviews { [super viewWillLayoutSubviews];
NSLog(@'%s',__func__); } // view已經完成子控件的布局 - (void)viewDidLayoutSubviews { [super viewDidLayoutSubviews];
NSLog(@'%s',__func__); } // view已經出現(xiàn) - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated];
NSLog(@'%s',__func__); } // view即將消失 - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated];
NSLog(@'%s',__func__); } // view已經消失 - (void)viewDidDisappear:(BOOL)animated { [super viewDidDisappear:animated];
NSLog(@'%s',__func__); } // 收到內存警告 - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning];
NSLog(@'%s',__func__); } // 方法已過期,,即將銷毀view - (void)viewWillUnload {
} // 方法已過期,已經銷毀view - (void)viewDidUnload {
}
你是怎么封裝一個view的/** * 純代碼初始化控件時一定會走這個方法 */ - (instancetype)initWithFrame:(CGRect)frame { if(self = [super initWithFrame:frame]) { [self setup]; }
return self; }
/** * 通過xib初始化控件時一定會走這個方法 */ - (id)initWithCoder:(NSCoder *)aDecoder { if(self = [super initWithCoder:aDecoder]) { [self setup]; }
return self; }
- (void)setup { // 初始化代碼 }
如何進行iOS6、7的適配通過判斷版本來控制,,來執(zhí)行響應的代碼 功能適配:保證同一個功能在6,、7上都能用 UI適配:保證各自的顯示風格
// iOS版本為7.0以上(包含7.0) #define iOS7 ([[UIDevice currentDevice].systemVersion doubleValue]>=7.0)
如何渲染UILabel的文字?
UIScrollView的contentSize能否在viewDidLoad中設置,?-(void)viewDidLayoutSubviews;
觸摸事件的傳遞觸摸事件的傳遞是從父控件傳遞到子控件 如果父控件不能接收觸摸事件,,那么子控件就不可能接收到觸摸事件 不能接受觸摸事件的四種情況 提示:UIImageView的userInteractionEnabled默認就是NO,,因此UIImageView以及它的子控件默認是不能接收觸摸事件的 如何找到最合適處理事件的控件: 首先,,判斷自己能否接收觸摸事件 可以通過重寫hitTest:withEvent:方法驗證 其次,判斷觸摸點是否在自己身上 對應方法pointInside:withEvent: 從后往前(先遍歷最后添加的子控件)遍歷子控件,,重復前面的兩個步驟 如果沒有符合條件的子控件,,那么就自己處理
事件響應者鏈如果當前view是控制器的view,那么就傳遞給控制器 如果控制器不存在,,則將其傳遞給它的父控件 在視圖層次結構的最頂層視圖也不能處理接收到的事件或消息,,則將事件或消息傳遞給UIWindow對象進行處理 如果UIWindow對象也不處理,,則將事件或消息傳遞給UIApplication對象 如果UIApplication也不能處理該事件或消息,則將其丟棄 補充:如何判斷上一個響應者 如果當前這個view是控制器的view,,那么控制器就是上一個響應者 如果當前這個view不是控制器的view,,那么父控件就是上一個響應者
|