iOS面試題整理筆記

OC語法篇

面向?qū)ο?/h3>

1. 一個(gè)NSObject對(duì)象占用多少內(nèi)存?

系統(tǒng)分配了16個(gè)字節(jié)給NSobject對(duì)象(通過malloc_size函數(shù)獲得)灶挟,但NSobject對(duì)象內(nèi)部只是用了8個(gè)字節(jié)的空間(64bit環(huán)境下,可以通過class_getInstanceSize函數(shù)獲得)

2. 對(duì)象的isa指針指向哪里亚斋?

instance對(duì)象的isa指針指向class對(duì)象扎酷;class對(duì)象的isa指針指向meta-class對(duì)象;meta-class對(duì)象的isa指針指向基類的meta-class對(duì)象

3. OC的類信息存放在哪里?

對(duì)象方法酪捡、屬性、成員變量纳账、協(xié)議信息逛薇,存放在class對(duì)象中;類方法存放在meta-class對(duì)象中疏虫;成員變量的具體值永罚,存放在instance對(duì)象中啤呼。
OC對(duì)象分為三種對(duì)象
instance對(duì)象:實(shí)例對(duì)象(包含isa指針、成員變量)
class對(duì)象:類對(duì)象(包含isa指針呢袱、superclass官扣、屬性、對(duì)象方法羞福、協(xié)議惕蹄、成員變量···)
meta-class對(duì)象:元類對(duì)象(包含isa指針、superclass治专、類方法)

4. isa焊唬、superclass總結(jié)

instance的isa指向class
class的isa指向meta-class
meta-class的isa指向基類的meta-class

class的superclass指向父類的class
如果沒有父類,superclass指針為nil
meta-class的superclass指向父類的meta-class
基類的meta-class的superclass指向基類的class

instance調(diào)用對(duì)象方法的軌跡
isa找到class看靠,方法不存在赶促,就通過superclass找父類

class調(diào)用類方法的軌跡
isa找meta-class,方法不存在挟炬,就通過superclass找父類

KVO and KVC

1. iOS用什么方式實(shí)現(xiàn)對(duì)一個(gè)對(duì)象的KVO鸥滨?(KVO的本質(zhì)是什么?)

利用RuntimeAPI動(dòng)態(tài)生成一個(gè)子類谤祖,并且讓instance對(duì)象的isa指向這個(gè)全新的子類
當(dāng)修改instance對(duì)象的屬性時(shí)婿滓,會(huì)調(diào)用Foundation的_NSSetXXXValueAndNotify函數(shù)
willChangeValueForKey:
父類原來的setter
didChangeValueForKey:
內(nèi)部會(huì)觸發(fā)監(jiān)聽器(Oberser)的監(jiān)聽方法( observeValueForKeyPath:ofObject:change:context:)

2. 如何手動(dòng)觸發(fā)KVO?

手動(dòng)調(diào)用willChangeValueForKey:和didChangeValueForKey:

3. 通過KVC修改屬性會(huì)觸發(fā)KVO么粥喜?

會(huì)觸發(fā)KVO

4. KVC的賦值和取值過程是怎樣的凸主?原理是什么?

KVC的全稱是Key-Value Coding额湘,俗稱“鍵值編碼”卿吐,可以通過一個(gè)key來訪問某個(gè)屬性
常見的API有
- (void)setValue:(id)value forKeyPath:(NSString *)keyPath;
- (void)setValue:(id)value forKey:(NSString *)key;
- (id)valueForKeyPath:(NSString *)keyPath;
- (id)valueForKey:(NSString *)key;
賦值過程:
按照setKey:、_setKey順序查找方法锋华,找到了方法傳遞參數(shù)嗡官,調(diào)用方法;若沒找到毯焕,查看accessInstanceVariablesDirectly方法的返回值衍腥,若為NO則調(diào)用setValue:forUndefinedKey:并拋出異常NSUnknownKeyException,若返回YES則按照_key纳猫、_isKey婆咸、key、isKey順序查找成員變量芜辕,找到直接賦值尚骄,找不到則調(diào)用setValue:forUndefinedKey:并拋出異常NSUnknownKeyException
取值過程
按照getKey:、key物遇、_isKey乖仇、key順序查找方法憾儒,找到了方法询兴,調(diào)用方法乃沙;若沒找到,查看accessInstanceVariablesDirectly方法的返回值诗舰,若為NO則調(diào)用valueForUndefinedKey:并拋出異常NSUnknownKeyException警儒,若返回YES則按照_key、_isKey眶根、key蜀铲、isKey順序查找成員變量,找到直接取值属百,找不到則調(diào)用valueForUndefinedKey:并拋出異常NSUnknownKeyException

Category

1. Category的使用場合是什么记劝?
2. Category的實(shí)現(xiàn)原理

Category編譯之后的底層結(jié)構(gòu)是struct category_t,里面存儲(chǔ)著分類的對(duì)象方法族扰、類方法厌丑、屬性、協(xié)議信息
在程序運(yùn)行的時(shí)候渔呵,runtime會(huì)將Category的數(shù)據(jù)怒竿,合并到類信息中(類對(duì)象、元類對(duì)象中)

3. Category和Class Extension的區(qū)別是什么扩氢?

Class Extension在編譯的時(shí)候耕驰,它的數(shù)據(jù)就已經(jīng)包含在類信息中
Category是在運(yùn)行時(shí),才會(huì)將數(shù)據(jù)合并到類信息中

4. Category中有l(wèi)oad方法嗎录豺?load方法是什么時(shí)候調(diào)用的朦肘?load 方法能繼承嗎?

有l(wèi)oad方法
load方法在runtime加載類双饥、分類的時(shí)候調(diào)用
load方法可以繼承厚骗,但是一般情況下不會(huì)主動(dòng)去調(diào)用load方法,都是讓系統(tǒng)自動(dòng)調(diào)用

5. load兢哭、initialize方法的區(qū)別什么领舰?它們?cè)赾ategory中的調(diào)用的順序?以及出現(xiàn)繼承時(shí)他們之間的調(diào)用過程迟螺?

+load方法會(huì)在runtime加載類冲秽、分類時(shí)調(diào)用
每個(gè)類、分類的+load矩父,在程序運(yùn)行過程中只調(diào)用一次
調(diào)用順序:先調(diào)用類的+load锉桑,按照編譯先后順序調(diào)用(先編譯,先調(diào)用)窍株,調(diào)用子類的+load之前會(huì)先調(diào)用父類的+load民轴;再調(diào)用分類的+load攻柠,按照編譯先后順序調(diào)用(先編譯,先調(diào)用)

+initialize方法會(huì)在類第一次接收到消息時(shí)調(diào)用后裸,調(diào)用順序:先調(diào)用父類的+initialize瑰钮,再調(diào)用子類的+initialize,(先初始化父類微驶,再初始化子類浪谴,每個(gè)類只會(huì)初始化1次)
+initialize和+load的很大區(qū)別是,+initialize是通過objc_msgSend進(jìn)行調(diào)用的因苹,所以有以下特點(diǎn):如果子類沒有實(shí)現(xiàn)+initialize苟耻,會(huì)調(diào)用父類的+initialize(所以父類的+initialize可能會(huì)被調(diào)用多次);如果分類實(shí)現(xiàn)了+initialize扶檐,就覆蓋類本身的+initialize調(diào)用

6. Category能否添加成員變量凶杖?如果可以,如何給Category添加成員變量款筑?

不能直接給Category添加成員變量智蝠,但是可以間接實(shí)現(xiàn)Category有成員變量的效果
添加關(guān)聯(lián)對(duì)象:void objc_setAssociatedObject(id object, const void * key,
id value, objc_AssociationPolicy policy)
獲得關(guān)聯(lián)對(duì)象:id objc_getAssociatedObject(id object, const void * key)
移除所有的關(guān)聯(lián)對(duì)象:void objc_removeAssociatedObjects(id object)

block

1. block的原理是怎樣的?本質(zhì)是什么醋虏?

block本質(zhì)上也是一個(gè)OC對(duì)象寻咒,它內(nèi)部也有個(gè)isa指針,封裝了函數(shù)調(diào)用以及調(diào)用環(huán)境的OC對(duì)象

block有3種類型颈嚼,可以通過調(diào)用class方法或者isa指針查看具體類型毛秘,最終都是繼承自NSBlock類型
         __NSGlobalBlock__(_NSConcreteGlobalBlock):存儲(chǔ)在數(shù)據(jù)區(qū),沒有訪問auto變量
         __NSStackBlock__(_NSConcreteStackBlock):存儲(chǔ)在棧區(qū),訪問auto變量
         __NSMallocBlock__(_NSConcreteMallocBlock):存儲(chǔ)在堆區(qū),__NSStackBlock__調(diào)用了copy
2. __block的作用是什么阻课?有什么使用注意點(diǎn)叫挟?

__block可以用于解決block內(nèi)部無法修改auto變量值的問題
__block不能修飾全局變量、靜態(tài)變量(static)
編譯器會(huì)將__block變量包裝成一個(gè)對(duì)象

3. block的屬性修飾詞為什么是copy限煞?使用block有哪些使用注意抹恳?

block一旦沒有進(jìn)行copy操作,就不會(huì)在堆上
使用注意:循環(huán)引用問題
__weak typeof(self)weakSelf = self;
__unsafe _unretained id weakSelf = self;
__block id weakSelf = self;

Runtime

1. 講一下 OC 的消息機(jī)制

OC中的方法調(diào)用其實(shí)都是轉(zhuǎn)成了objc_msgSend函數(shù)的調(diào)用署驻,給receiver(方法調(diào)用者)發(fā)送了一條消息(selector方法名)
objc_msgSend底層有3大階段
消息發(fā)送(當(dāng)前類奋献、父類中查找)、動(dòng)態(tài)方法解析旺上、消息轉(zhuǎn)發(fā)

2. 什么是Runtime瓶蚂?平時(shí)項(xiàng)目中有用過么?

OC是一門動(dòng)態(tài)性比較強(qiáng)的編程語言宣吱,允許很多操作推遲到程序運(yùn)行時(shí)再進(jìn)行
OC的動(dòng)態(tài)性就是由Runtime來支撐和實(shí)現(xiàn)的窃这,Runtime是一套C語言的API,封裝了很多動(dòng)態(tài)性相關(guān)的函數(shù)
平時(shí)編寫的OC代碼征候,底層都是轉(zhuǎn)換成了Runtime API進(jìn)行調(diào)用

具體應(yīng)用
利用關(guān)聯(lián)對(duì)象(AssociatedObject)給分類添加屬性杭攻;遍歷類的所有成員變量(修改textfield的占位文字顏色祟敛、字典轉(zhuǎn)模型、自動(dòng)歸檔解檔)兆解; 交換方法實(shí)現(xiàn)(交換系統(tǒng)的方法)馆铁;利用消息轉(zhuǎn)發(fā)機(jī)制解決方法找不到的異常問題

RunLoop

1. 講講 RunLoop,項(xiàng)目中有用到嗎痪宰?

運(yùn)行循環(huán)叼架,在程序運(yùn)行過程中循環(huán)做一些事情
應(yīng)用范疇:定時(shí)器(Timer)畔裕、PerformSelector衣撬;GCD Async Main Queue;事件響應(yīng)扮饶、手勢(shì)識(shí)別具练、界面刷新;網(wǎng)絡(luò)請(qǐng)求甜无;AutoreleasePool
RunLoop的基本作用:保持程序的持續(xù)運(yùn)行扛点;處理App中的各種事件(比如觸摸事件、定時(shí)器事件等)岂丘;節(jié)省CPU資源陵究,提高程序性能:該做事時(shí)做事,該休息時(shí)休息

2. runloop內(nèi)部實(shí)現(xiàn)邏輯奥帘?
3. runloop和線程的關(guān)系铜邮?

每條線程都有唯一的一個(gè)與之對(duì)應(yīng)的RunLoop對(duì)象
RunLoop保存在一個(gè)全局的Dictionary里,線程作為key寨蹋,RunLoop作為value
線程剛創(chuàng)建時(shí)并沒有RunLoop對(duì)象松蒜,RunLoop會(huì)在第一次獲取它時(shí)創(chuàng)建
RunLoop會(huì)在線程結(jié)束時(shí)銷毀
主線程的RunLoop已經(jīng)自動(dòng)獲取(創(chuàng)建)已旧,子線程默認(rèn)沒有開啟RunLoop

4. timer 與 runloop 的關(guān)系秸苗?
5. 程序中添加每3秒響應(yīng)一次的NSTimer,當(dāng)拖動(dòng)tableview時(shí)timer可能無法響應(yīng)要怎么解決运褪?
6. runloop 是怎么響應(yīng)用戶操作的惊楼, 具體流程是什么樣的?
7. 說說runLoop的幾種狀態(tài)

eg:添加Observer監(jiān)聽RunLoop的所有狀態(tài)

CFRunLoopObserverRef observe = CFRunLoopObserverCreateWithHandler(kCFAllocatorDefault, kCFRunLoopAllActivities, yearMask, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
            switch (activity) {
                case kCFRunLoopEntry:
                    NSLog(@"kCFRunLoopEntry");//即將進(jìn)入Loop
                    break;
                case kCFRunLoopBeforeTimers:
                    NSLog(@"kCFRunLoopBeforeTimers");//即將處理Timers
                    break;
                case kCFRunLoopBeforeSources:
                    NSLog(@"kCFRunLoopBeforeSources");//即將處理Sources
                    break;
                case kCFRunLoopBeforeWaiting:
                    NSLog(@"kCFRunLoopBeforeWaiting");//即將進(jìn)入休眠
                    break;
                case kCFRunLoopAfterWaiting:
                    NSLog(@"kCFRunLoopAfterWaiting");//剛從休眠中喚醒
                    break;
                case kCFRunLoopExit:
                    NSLog(@"kCFRunLoopExit");//即將退出Loop
                    break;
                default:
                    break;
            }
        });
        CFRunLoopAddObserver(CFRunLoopGetCurrent(), observe, kCFRunLoopCommonModes);
        CFRelease(observe);
8. runloop的mode作用是什么秸讹?

CFRunLoopModeRef代表RunLoop的運(yùn)行模式
一個(gè)RunLoop包含若干個(gè)Mode檀咙,每個(gè)Mode又包含若干個(gè)Source0/Source1/Timer/Observer
RunLoop啟動(dòng)時(shí)只能選擇其中一個(gè)Mode,作為currentMode
如果需要切換Mode嗦枢,只能退出當(dāng)前Loop攀芯,再重新選擇一個(gè)Mode進(jìn)入
不同組的Source0/Source1/Timer/Observer能分隔開來,互不影響
如果Mode里沒有任何Source0/Source1/Timer/Observer文虏,RunLoop會(huì)立馬退出
常見的2種Mode
kCFRunLoopDefaultMode(NSDefaultRunLoopMode):App的默認(rèn)Mode侣诺,通常主線程是在這個(gè)Mode下運(yùn)行
UITrackingRunLoopMode:界面跟蹤 Mode殖演,用于 ScrollView 追蹤觸摸滑動(dòng),保證界面滑動(dòng)時(shí)不受其他 Mode 影響

多線程

1. iOS中的線程同步方案

性能從高到低排序

OSSpinLock

OSSpinLock叫做”自旋鎖”年鸳,等待鎖的線程會(huì)處于忙等(busy-wait)狀態(tài)趴久,一直占用著CPU資源
目前已經(jīng)不再安全,可能會(huì)出現(xiàn)優(yōu)先級(jí)反轉(zhuǎn)問題
如果等待鎖的線程優(yōu)先級(jí)較高搔确,它會(huì)一直占用著CPU資源彼棍,優(yōu)先級(jí)低的線程就無法釋放鎖
需要導(dǎo)入頭文件#import <libkern/OSAtomic.h>

//初始化
OSSpinLock lock = OS_SPINLOCK_INIT;
//嘗試加鎖(如果需要等待就不加鎖,直接返回false;如果不需要等待就加鎖,返回true)
bool result = OSSpinLockTry(&lock);
//加鎖
OSSpinLockLock(&lock);
//解鎖
OSSpinLockUnLock(&lock);
os_unfair_lock

os_unfair_lock
os_unfair_lock用于取代不安全的OSSpinLock ,從iOS10開始才支持
從底層調(diào)用看膳算,等待os_unfair_lock鎖的線程會(huì)處于休眠狀態(tài)座硕,并非忙等
需要導(dǎo)入頭文件#import <os/lock.h>

//初始化
os_unfair_lock lock = OS_UNFAIR_LOCK_INIT;
//嘗試加鎖
os_unfair_lock_trylock(&lock);
//加鎖
os_unfair_lock_lock(&lock);
//解鎖
os_unfair_lock_unlock(&lock);
pthread_mutex

mutex叫做”互斥鎖”,等待鎖的線程會(huì)處于休眠狀態(tài)
需要導(dǎo)入頭文件#import <pthread.h>

dispatch_semaphore:

semaphore叫做”信號(hào)量”
信號(hào)量的初始值涕蜂,可以用來控制線程并發(fā)訪問的最大數(shù)量
信號(hào)量的初始值為1华匾,代表同時(shí)只允許1條線程訪問資源,保證線程同步

//信號(hào)量的初始值
        int value = 1;
        //初始化信號(hào)量
        dispatch_semaphore_t semaphore = dispatch_semaphore_create(value);
        //如果信號(hào)量的值<=0,當(dāng)前線程就會(huì)進(jìn)入休眠等待(直到信號(hào)量的值>0)
        //如果信號(hào)量的值>0,就減1机隙,然后往下執(zhí)行后面的代碼
        dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
        //讓信號(hào)量的值加1
        dispatch_semaphore_signal(semaphore);
dispatch_queue(DISPATCH_QUEUE_SERIAL)

直接使用GCD的串行隊(duì)列蜘拉,也是可以實(shí)現(xiàn)線程同步的

dispatch_queue_t queue = dispatch_queue_create("lock_queue", DISPATCH_QUEUE_SERIAL);
        dispatch_sync(queue, ^{
            //任務(wù)
        });
NSLock:對(duì)mutex普通鎖的封裝

NSRecursiveLock

NSCondition:對(duì)mutex和cond的封裝
NSConditionLock:對(duì)NSCondition的進(jìn)一步封裝,可以設(shè)置具體的條件值
@synchronized:是對(duì)mutex遞歸鎖的封裝
什么情況使用自旋鎖比較劃算有鹿?

預(yù)計(jì)線程等待鎖的時(shí)間很短
加鎖的代碼(臨界區(qū))經(jīng)常被調(diào)用旭旭,但競爭情況很少發(fā)生
CPU資源不緊張
多核處理器

什么情況使用互斥鎖比較劃算?

預(yù)計(jì)線程等待鎖的時(shí)間較長
單核處理器
臨界區(qū)有IO操作
臨界區(qū)代碼復(fù)雜或者循環(huán)量大
臨界區(qū)競爭非常激烈

內(nèi)存管理

1. 使用CADisplayLink葱跋、NSTimer有什么注意點(diǎn)持寄?

CADisplayLink、NSTimer會(huì)對(duì)target產(chǎn)生強(qiáng)引用年局,如果target又對(duì)它們產(chǎn)生強(qiáng)引用际看,那么就會(huì)引發(fā)循環(huán)引用
解決方案
使用block 弱引用weakSelf
使用代理對(duì)象(NSProxy)
NSTimer依賴于RunLoop,如果RunLoop的任務(wù)過于繁重矢否,可能會(huì)導(dǎo)致NSTimer不準(zhǔn)時(shí)仲闽,而GCD的定時(shí)器會(huì)更加準(zhǔn)時(shí)

//創(chuàng)建一個(gè)定時(shí)器
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0));
//設(shè)置時(shí)間(start是幾秒后開始執(zhí)行,interval是時(shí)間間隔)
dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, (int64_t)(start * NSEC_PER_SEC)), (uint64_t)(interval ) * NSEC_PER_SEC);
//設(shè)置回調(diào)
dispatch_source_set_event_handler(timer, ^{
});
//啟動(dòng)定時(shí)器
dispatch_resume(timer);
2. 介紹下內(nèi)存的幾大區(qū)域

代碼段:編譯之后的代碼

數(shù)據(jù)段
字符串常量:比如NSString *str = @"123"
已初始化數(shù)據(jù):已初始化的全局變量、靜態(tài)變量等
未初始化數(shù)據(jù):未初始化的全局變量僵朗、靜態(tài)變量等

棧:函數(shù)調(diào)用開銷赖欣,比如局部變量。分配的內(nèi)存空間地址越來越小

堆:通過alloc验庙、malloc顶吮、calloc等動(dòng)態(tài)分配的空間,分配的內(nèi)存空間地址越來越大

3. 講一下你對(duì) iOS 內(nèi)存管理的理解

在iOS中粪薛,使用引用計(jì)數(shù)來管理OC對(duì)象的內(nèi)存
一個(gè)新創(chuàng)建的OC對(duì)象引用計(jì)數(shù)默認(rèn)是1悴了,當(dāng)引用計(jì)數(shù)減為0,OC對(duì)象就會(huì)銷毀,釋放其占用的內(nèi)存空間
調(diào)用retain會(huì)讓OC對(duì)象的引用計(jì)數(shù)+1湃交,調(diào)用release會(huì)讓OC對(duì)象的引用計(jì)數(shù)-1

內(nèi)存管理的經(jīng)驗(yàn)總結(jié)
當(dāng)調(diào)用alloc熟空、new、copy搞莺、mutableCopy方法返回了一個(gè)對(duì)象息罗,在不需要這個(gè)對(duì)象時(shí),要調(diào)用release或者autorelease來釋放它
想擁有某個(gè)對(duì)象才沧,就讓它的引用計(jì)數(shù)+1迈喉;不想再擁有某個(gè)對(duì)象,就讓它的引用計(jì)數(shù)-1

可以通過以下私有函數(shù)來查看自動(dòng)釋放池的情況
extern void _objc_autoreleasePoolPrint(void);

性能優(yōu)化

1. 列表卡頓的原因可能有哪些温圆?你平時(shí)是怎么優(yōu)化的挨摸?

CPU

  • 盡量用輕量級(jí)的對(duì)象,比如用不到事件處理的地方捌木,可以考慮使用CALayer取代UIView
  • 不要頻繁地調(diào)用UIView的相關(guān)屬性油坝,比如frame嫉戚、bounds刨裆、transform等屬性,盡量減少不必要的修改
  • 盡量提前計(jì)算好布局彬檀,在有需要時(shí)一次性調(diào)整對(duì)應(yīng)的屬性帆啃,不要多次修改屬性
  • Autolayout會(huì)比直接設(shè)置frame消耗更多的CPU資源
  • 圖片的size最好剛好跟UIImageView的size保持一致
  • 控制一下線程的最大并發(fā)數(shù)量
  • 盡量把耗時(shí)的操作放到子線程: 文本處理(尺寸計(jì)算、繪制);圖片處理(解碼窍帝、繪制)

GPU

  • 盡量避免短時(shí)間內(nèi)大量圖片的顯示努潘,盡可能將多張圖片合成一張進(jìn)行顯示
  • GPU能處理的最大紋理尺寸是4096x4096,一旦超過這個(gè)尺寸坤学,就會(huì)占用CPU資源進(jìn)行處理疯坤,所以紋理盡量不要超過這個(gè)尺寸
  • 盡量減少視圖數(shù)量和層次
  • 減少透明的視圖(alpha<1),不透明的就設(shè)置opaque為YES
  • 盡量避免出現(xiàn)離屏渲染
2. 什么是離屏渲染深浮?

在OpenGL中压怠,GPU有2種渲染方式
On-Screen Rendering:當(dāng)前屏幕渲染,在當(dāng)前用于顯示的屏幕緩沖區(qū)進(jìn)行渲染操作
Off-Screen Rendering:離屏渲染飞苇,在當(dāng)前屏幕緩沖區(qū)以外新開辟一個(gè)緩沖區(qū)進(jìn)行渲染操作

3. 離屏渲染消耗性能的原因

需要?jiǎng)?chuàng)建新的緩沖區(qū)
離屏渲染的整個(gè)過程菌瘫,需要多次切換上下文環(huán)境,先是從當(dāng)前屏幕(On-Screen)切換到離屏(Off-Screen)布卡;等到離屏渲染結(jié)束以后雨让,將離屏緩沖區(qū)的渲染結(jié)果顯示到屏幕上,又需要將上下文環(huán)境從離屏切換到當(dāng)前屏幕

4. 哪些操作會(huì)觸發(fā)離屏渲染忿等?
  • 光柵化栖忠,layer.shouldRasterize = YES
  • 遮罩,layer.mask
  • 圓角,同時(shí)設(shè)置layer.masksToBounds = YES庵寞、layer.cornerRadius大于0(考慮通過CoreGraphics繪制裁剪圓角虚汛,或者叫美工提供圓角圖片)
  • 陰影,layer.shadowXXX(如果設(shè)置了layer.shadowPath就不會(huì)產(chǎn)生離屏渲染)
5. 怎么檢測卡頓皇帮?

平時(shí)所說的“卡頓”主要是因?yàn)樵谥骶€程執(zhí)行了比較耗時(shí)的操作
可以添加Observer到主線程RunLoop中卷哩,通過監(jiān)聽RunLoop狀態(tài)切換的耗時(shí),以達(dá)到監(jiān)控卡頓的目的

暫時(shí)先整理這些属拾,如果有錯(cuò)誤将谊,感謝各位大佬指正。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末渐白,一起剝皮案震驚了整個(gè)濱河市尊浓,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌纯衍,老刑警劉巖栋齿,帶你破解...
    沈念sama閱讀 218,122評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異襟诸,居然都是意外死亡瓦堵,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門歌亲,熙熙樓的掌柜王于貴愁眉苦臉地迎上來菇用,“玉大人,你說我怎么就攤上這事陷揪⊥锱福” “怎么了?”我有些...
    開封第一講書人閱讀 164,491評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵悍缠,是天一觀的道長卦绣。 經(jīng)常有香客問我,道長飞蚓,這世上最難降的妖魔是什么滤港? 我笑而不...
    開封第一講書人閱讀 58,636評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮玷坠,結(jié)果婚禮上蜗搔,老公的妹妹穿的比我還像新娘。我一直安慰自己八堡,他們只是感情好樟凄,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,676評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著兄渺,像睡著了一般缝龄。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,541評(píng)論 1 305
  • 那天叔壤,我揣著相機(jī)與錄音瞎饲,去河邊找鬼。 笑死炼绘,一個(gè)胖子當(dāng)著我的面吹牛嗅战,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播俺亮,決...
    沈念sama閱讀 40,292評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼驮捍,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了脚曾?” 一聲冷哼從身側(cè)響起东且,我...
    開封第一講書人閱讀 39,211評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎本讥,沒想到半個(gè)月后珊泳,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,655評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡拷沸,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,846評(píng)論 3 336
  • 正文 我和宋清朗相戀三年色查,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片堵漱。...
    茶點(diǎn)故事閱讀 39,965評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡综慎,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出勤庐,到底是詐尸還是另有隱情,我是刑警寧澤好港,帶...
    沈念sama閱讀 35,684評(píng)論 5 347
  • 正文 年R本政府宣布愉镰,位于F島的核電站,受9級(jí)特大地震影響钧汹,放射性物質(zhì)發(fā)生泄漏丈探。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,295評(píng)論 3 329
  • 文/蒙蒙 一拔莱、第九天 我趴在偏房一處隱蔽的房頂上張望碗降。 院中可真熱鬧,春花似錦塘秦、人聲如沸讼渊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽爪幻。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間挨稿,已是汗流浹背仇轻。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評(píng)論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留奶甘,地道東北人篷店。 一個(gè)月前我還...
    沈念sama閱讀 48,126評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像臭家,于是被迫代替她去往敵國和親船庇。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,914評(píng)論 2 355