1.正確設置Lable圓角的姿勢
需求如圖(常用作標簽):
常規做法:
self.label.text = @"皮爾斯";
self.label.backgroundColor = [UIColor brownColor];
self.label.layer.cornerRadius = 5;
self.label.layer.borderWidth = 1;
self.label.layer.borderColor = [UIColor cyanColor].CGColor;
self.label.layer.masksToBounds = YES;
我這里用模擬器調試如圖:
標黃的地方是告訴我們這些地方引起了離屏渲染
(更新于2019年2月27日01:03:11)
離屏渲染簡單概念:GPU在當前屏幕緩沖區之外開辟一個新的緩沖區進行渲染操作,產生額外開銷,可能會造成卡頓
我們知道當FPS小于60的時候,我們肉眼會感到卡頓
FPS即每秒刷新數,即 1000 / 60 ≈ 16.7ms,即16.7ms以內刷新一次頁面就不會感到卡頓,系統生成圖像信號是靠 CPU + GPU 共同工作的,即CPU + GPU 共同工作生成圖像需要 < 16.7ms,而如果CPU或者GPU工作壓力太大,生成圖像信號大于這個時間,那么就會放棄掉這一幀,而繼續顯示之前的圖像
因為離屏渲染會增加GPU的壓力,所以我們應該盡量避免離屏渲染的發生
現在修改一下代碼
self.label.text = @"皮爾斯";
self.label.layer.backgroundColor = [UIColor brownColor].CGColor;
self.label.layer.cornerRadius = 5;
self.label.layer.borderWidth = 1;
self.label.layer.borderColor = [UIColor cyanColor].CGColor;
效果如圖:
哈哈,離屏渲染沒有了!
精髓在于我們干掉了masksToBounds這行代碼,而顏色的設置放到了layer層
以后碰到類似需求就這樣做吧,思密達!
2.數組之泛型數組
Person* p1 = [Person new];
Person* p2 = [Person new];
Person* p3 = [Person new];
NSArray* arr = @[p1,p2,p3];
for (int i = 0; i < arr.count; i++) {
arr[0];
}
如圖arr數組里存儲了3個Person實例,并進行遍歷
這樣寫固然沒有問題,但是我數組的初始化如果不是用字面量的方式,arr里元素到底存儲了那些東西,我們是需要扒代碼的,有些項目的代碼復雜度遠遠超乎你的想象,此時是非常耗時間的
OC的數組是可以存儲任何類型對象的,但是我強烈建議用泛型除非特殊需求(雖然我接過這樣的需求)
代碼改動下:
Person* p1 = [Person new];
Person* p2 = [Person new];
Person* p3 = [Person new];
NSArray<Person*>* arr = @[p1,p2,p3];
為什么建議用泛型呢?
1.在數組聲明的時候就已經明確數組里元素的數據類型了
2.用enumerateObjectsUsingBlock遍歷數組時,你會發現數組里元素類型IDE已經幫我們輸入好了(超贊的)而且《52高效》的書推薦我們用這種方式遍歷數組
3. ARC下如何打印retainCount(引用計數)
// obj目標對象
NSInteger retainCount = CFGetRetainCount((__bridge CFTypeRef)chen);
NSLog(@"Retain count is %ld", retainCount);
4.category你是否這么用過?
之前在某項目看到這樣的分類:
@interface NSString (Help)
- (BOOL)isEmpty;
@end
@implementation NSString (Help)
- (BOOL)isEmpty {
if (self == nil) {
return YES;
}
return NO;
}
@end
一個判斷字符串是否為空的分類,按照代碼邏輯當字符串對象為nil的時候,認為為空返回true
但是卻犯了一個大問題:當字符串對象為nil的時候,isEmpty方法是永遠不會執行的,邏輯上表現為一個為nil的字符串對象他不認為是空的,返回false(這樣做邏輯不就中獎了么?)
為什么會這樣呢?
當字符串對象為nil的時候即[nil isEmpty],我們向nil對象發送了一條消息,OC的機制向nil發送消息是允許的,但是方法永遠不會執行,這樣做邏輯你說會不會中獎?
5.將view 放到的圖層最上端
// 目標view假設為topView
// 1
[self.view insertSubview:topView atIndex:[self.view subviews].count];
// 2
[[topView superview] bringSubviewToFront:topView];
6.UI妹子眼中一根線的粗細到底是多少?
#define SINGLE_LINE_HEIGHT (1 / [UIScreen mainScreen].scale)
為什么要這樣呢:
scale的官方解釋:
中文:
與屏幕相關的自然比例因子。
此值反映從默認邏輯坐標空間轉換到此屏幕的設備坐標空間所需的縮放因子。 使用點測量默認邏輯坐標空間。 對于標準分辨率顯示器,比例因子為1.0,一點等于一個像素。 對于Retina顯示器,比例因子為2.0,一個點由四個像素表示。
7.這個細節你是否留意到了?
直接上圖(以某大廠出的app舉例)
這種控件現在越來越多的項目在用,但是呢,這個細膩的地方在于:
滑到“全部”這個頁面的時候,再次右滑是可以pop的,雖說看起來一樣的控件,但是我發現很多app是沒有處理這個滑動pop邏輯的
我們自己的項目中也大面積使用了這種方式,當然這種細膩的體驗我當然是要加進來的(o)/
直接上代碼(如果有更好的思路希望提出來,共同學習哈!)
假設如圖例子的UI結構是:ScrollView里添加了5個子View
// 給VC的view添加pan手勢
UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] init];
panGesture.delegate = self;
[self.view addGestureRecognizer:panGesture];
// 實現此代理
// 詢問一個手勢接收者是否應該開始解釋執行一個觸摸接收事件
#pragma mark - UIGestureRecognizerDelegate
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
{
// 這個_pageIndex就是記錄當前滑到了哪個title下
// 比如說在這里_pageIndex == 0 就是“全部”這個title下的頁面
if (_pageIndex == 0) {
CGPoint translatedPoint = [(UIPanGestureRecognizer *)gestureRecognizer translationInView:self.view];
NSLog(@"%f %f",translatedPoint.x,translatedPoint.y);
// 當在“全部”title下,且右滑的情況下,禁止scrollView滾動
self.scrollView.scrollEnabled = translatedPoint.x < 0;
}
return NO;
}
8.這個細節你是否留意到了?
直接上圖
這種相冊預覽相信大家已經見過太多了,但是請注意個小細節,圖片是由模糊漸漸變清晰的(微信圖片瀏覽器就有這個細節)
這么做好處在哪里呢?
I/O操作是比較號資源的,我們先拿小圖即縮略圖展示出來,提高展示效率,其次獲取高清圖之后再替換,既提高了效率又加強了交互體驗,一箭雙雕,nice。
如果有更好的實現方式,請留言或者聯系我
代碼的實現方式請參考我的dolin_demo
以前碰到的都忘記總結了,就想起了這些,不過后續會持續更新
如果給你帶來了一點點幫助,就點個贊吧??