記錄:

UIButton繼承關系: UIControl -> UIView -> UIResponder -> NSObject
    
Model View Controller(模型 視圖 控制器):Control 負責初始化 Model,并將 Model 傳遞給 View 去解析展示   
    
MVP分為 Model(模型)、View(視圖)、Presenter(表示器)三部分組成,Presenter層,其負責調控View與Model之間的間接交互
Model(數(shù)據層)、ViewController/View(展示層)、ViewModel(數(shù)據模型):
MVVM模式主要是減輕Controller層或者View層的壓力,實現(xiàn)更加清晰化代碼。通過對ViewModel層的封裝:封裝業(yè)務邏輯處理,封裝網絡處理、封裝數(shù)據緩存等
    
iOS代理模式: 包含【委托對象】、【代理對象】和【協(xié)議】
    [協(xié)議]:用來指定代理需要做的事
    [委托對象]:根據協(xié)議,指定代理去完成什么功能
    [代理對象]:根據協(xié)議,完成委托方需要實現(xiàn)的功能
    
iOS單例模式:確保某一個類只有一個實例,不能通過其它類來初始化自己,在程序運行的過程中只有一份,節(jié)約內存
    
iOS觀察者模式:定義對象間一對多依賴關系,使得每當一個對象狀態(tài)發(fā)生改變時,其相關依賴對象皆得到通知并被自動更新  NSNotificationCenter和KVO
    
適配器模式 && 策略模式 && 裝飾模式 && 工廠模式
    
NSTimer受RunLoop模式的影響:
    
timerWithTimeInterval: 不會自動加入運行循環(huán),需要我們手動指定模式,并手動加入運行循環(huán)
scheduledTimerWithTimeInterval: 自動以NSDefaultRunLoopModel模式加入運行循環(huán)
CADisplayLink:在屏幕每次刷新時執(zhí)行一次,創(chuàng)建的displayLink添加到runloop中,否則定時器不會執(zhí)行
[displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
解決NSTimer循環(huán)引用:
     1.使用NSTimer提供的API,在block中執(zhí)行定時任務
     2.通過消息轉發(fā)的方法的方式,聲明弱代理
     3. #pragma mark - 第一種方法:合適的時機關閉定時器
            - (void)didMoveToParentViewController:(UIViewController *)parent
            {
                if (!parent) {
                    [_timer invalidate];
                    _timer = nil;
                }
            }
     4.使用NSProxy,此方法無需經過消息轉發(fā),效率更高
            
線程?;?使用端口(addPort:forMode:)?;钭泳€程
    
同步與異步的區(qū)別:是否等待隊列的任務執(zhí)行結束,以及是否具備開啟新線程的能力。
    
    dispatch_sync(dispatch_get_main_queue(), ^{
         NSLog(@"sync - %@", [NSThread currentThread]);
    });
dispatch_sync 立即阻塞當前的主線程,然后把 Block 中的任務放到 main_queue 中, main_queue 中的任務會被取出來放到主線程中執(zhí)行,但主線程這個時候已經被阻塞了

Runloop的作用:保持程序的持續(xù)運行、隨時處理各種事件、節(jié)省cpu資源(沒事件休息釋放資源)、渲染屏幕UI
Mode:主要用來指定事件在運行時循環(huán)的優(yōu)先級
    - (void)setAbcString:(NSString *)abcString {
        if (_abcString != abcString) {
            [_abcString release];
            _abcString = [abcString retain];
        }
    }
    A = A+B   B = A-B   A = A-B
NSOperation是一個抽象類,也就是說它并不能直接使用,而是應該使用它的子類   NSInvocationOperation  &&  NSBlockOperation  && 自定義繼承NSOperation的子類
NSOperation的使用常常是配合NSOperationQueue來進行的  
NSOperationQueue操作隊列之中,一旦添加到隊列,操作就會自動異步執(zhí)行(注意是異步)
    如果沒有添加到隊列,而是使用start方法,則會在當前線程執(zhí)行
    提供了GCD不好實現(xiàn)的:1.最大并發(fā)數(shù),2.暫停和繼續(xù),3.取消所有任務,4.依賴關系
    - (id)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
        UIView *hitView = [super hitTest:point withEvent:event];
        if (hitView == self) {
            return nil;
        } else  {
            return hitView;
        }
    }
觸摸hitTest的調用順序:touch -> UIApplication -> UIWindow -> UIViewController.view -> subViews -> ....-> 合適的view
事件的傳遞順序:view -> superView ...-> UIViewController.view -> UIViewController -> UIWindow -> UIApplication -> 事件丟棄
    - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
    }
    
KVO全稱KeyValueObserving,是蘋果提供的一套事件通知機制。允許對象監(jiān)聽另一個對象特定屬性的改變,并在改變時接收到事件。由于KVO的實現(xiàn)機制,所以對屬性才會發(fā)生作用,一般繼承自NSObject的對象都默認支持KVO。
    
dispatch_barrier_async:會等待前邊追加到并發(fā)隊列中的任務全部執(zhí)行完畢之后,再將指定的任務追加到該異步隊列中 針對全局隊列無效
dispatch_after:延時執(zhí)行方法
dispatch_once: 一次性代碼(只執(zhí)行一次)
dispatch_apply:快速迭代方法
dispatch_group:
        dispatch_group_notify
        dispatch_group_enter
        dispatch_group_leave
dispatch_semaphore:
        dispatch_semaphore_create:創(chuàng)建一個 Semaphore 并初始化信號的總量
        dispatch_semaphore_signal:發(fā)送一個信號,讓信號總量加 1
        dispatch_semaphore_wait:可以使總信號量減 1,信號總量小于 0 時就會一直等待(阻塞所在線程),否則就可以正常執(zhí)行。
    
UIView為CALayer提供內容,以及負責處理觸摸等事件,參與響應鏈
CALayer負責顯示內容contents
    
Off-Screen Rendering:離屏渲染,分為CPU離屏渲染和GPU離屏渲染兩種形式。GPU離屏渲染指的是GPU在當前屏幕緩沖區(qū)外新開辟一個緩沖區(qū)進行渲染操作,應當盡量避免的則是GPU離屏渲染
    
export JAVA_HOME=$(/usr/libexec/java_home -v 1.8)

iOS中的內存大致可以分為代碼區(qū),常量區(qū),全局/靜態(tài)區(qū),堆區(qū),棧區(qū);
棧區(qū)是由編譯器自動分配并釋放的,棧區(qū)地址從高到低分配;
堆區(qū)使用alloc分配內存,堆區(qū)地址是從低到高分配;
https://www.cnblogs.com/dins/p/ios-nei-cun-fen-pei-yu-fen-qu.html

結構體一般采用內存對齊的方式分配,其大小為結構體最寬成員大小的整數(shù)倍
    
bool  1個字節(jié)  char  1個字節(jié)
int   4個字節(jié)  float 4個字節(jié)
double 8個字節(jié)  long 8個字節(jié)  class isa 8個字節(jié)
    
autoreleasePool什么時候創(chuàng)建的,里面的對象又是什么時候釋放的?
    
App啟動后,蘋果在主線程 RunLoop 里注冊了兩個 Observer,其回調都是 _wrapRunLoopWithAutoreleasePoolHandler()
    第一個 Observer 監(jiān)視的事件是 Entry(即將進入Loop),其回調內會調用 _objc_autoreleasePoolPush() 創(chuàng)建自動釋放池
    第二個 Observer 監(jiān)視了兩個事件: BeforeWaiting(準備進入休眠) 時調用_objc_autoreleasePoolPop() 和 _objc_autoreleasePoolPush() 釋放舊的池并創(chuàng)建新池;Exit(即將退出Loop) 時調用 _objc_autoreleasePoolPop() 來釋放自動釋放池
    
手動autoreleasePool:@autoreleasepool {}方式手動創(chuàng)建autoreleasepool對象,出了autoreleasepool的大括號就釋放了
    
/**直接進行消息發(fā)送機制: objc_msgSend **/
- (id)performSelector:(SEL)aSelector;
- (id)performSelector:(SEL)aSelector withObject:(id)object;
- (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2;
    
 /**使用Runloop方法 **/
    - (void)performSelector:(SEL)aSelector withObject:(nullable id)anArgument afterDelay:(NSTimeInterval)delay inModes:(NSArray<NSRunLoopMode> *)modes;
    - (void)performSelector:(SEL)aSelector withObject:(nullable id)anArgument afterDelay:(NSTimeInterval)delay;
    waitUntilDone : YES, 需要等待這個selector 執(zhí)行完之后,才會往下執(zhí)行,相當于同步
    waitUntilDone : NO, 不用等待這個selector,就會往下執(zhí)行,相當于異步
    - (void)performSelector:(SEL)aSelector onThread:(NSThread *)thread waitUntilDone:(BOOL)wait;

如果,當前線程就是主線程,那么aSelector方法會馬上執(zhí)行。
    - (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait;
    
+ (void)load {}   runtime加載類和分類的時候調用     直接拿到函數(shù)地址,直接調用
    1.先調用父類的load   
    2.再調用子類的load   
    3.再調用分類的load,先編譯先調用

    + (void)initialize{}  當前類第一次接收到消息的時候調用     通過消息發(fā)送方式
    1.先調用父類的initialize   
    2.再調用子類的initialize 
    3.子類未實現(xiàn)initialize方法時,會調用父類initialize方法
    
    // 串行隊列的創(chuàng)建方法
    dispatch_queue_t queue = dispatch_queue_create("net.bujige.testQueue", DISPATCH_QUEUE_SERIAL);
    // 并發(fā)隊列的創(chuàng)建方法
    dispatch_queue_t queue = dispatch_queue_create("net.bujige.testQueue", DISPATCH_QUEUE_CONCURRENT);
    // 全局隊列
    dispatch_get_main_queue()
    // 全局并發(fā)隊列
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    同步執(zhí)行任務:
    dispatch_sync(queue, ^{
        // 這里放同步執(zhí)行任務代碼
    });
    異步執(zhí)行任務:
    dispatch_async(queue, ^{
        // 這里放異步執(zhí)行任務代碼
    });
    
    柵欄函數(shù):
    放全局并發(fā)隊列跟異步是同一個效果    A、B操作、柵欄柵欄柵欄操作、C、D操作并發(fā)執(zhí)行
    放自己創(chuàng)建的并發(fā)隊列則有效    A、B操作并發(fā)執(zhí)行   柵欄柵欄柵欄操作   C、D操作并發(fā)執(zhí)行
    dispatch_queue_t queue = dispatch_queue_create("testqueue",DISPATCH_QUEUE_CONCURRENT);
    dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
    dispatch_async(queue,^{
        for (int i = 0; i < 3; i++) {
            CHSLOG(@"A操作");
        }
    });
    dispatch_async(queue,^{
        for (int i = 0; i < 3; i++) {
            CHSLOG(@"B操作");
        }
    });
    dispatch_barrier_async(queue,^{
        for (int i = 0; i < 3; i++) {
            CHSLOG(@"柵欄柵欄柵欄操作");
        }
    });
    dispatch_async(queue,^{
        for (int i = 0; i < 3; i++) {
            CHSLOG(@"C操作");
        }
    });
    dispatch_async(queue,^{
        for (int i = 0; i < 3; i++) {
            CHSLOG(@"D操作");
        }
    });
    
    類擴展和分類的區(qū)別:
    類擴展:編譯的時候會把屬性和方法一起放到類中
    分類:利用Runtime把屬性和方法放到原類中,同名方法會覆蓋掉原來類中的方法,優(yōu)先調用后編譯的方法
    
    struct __main_block_impl_0 {
        struct __block_impl impl;
        struct __main_block_desc_0* Desc;
        int a;
        __Block_byref_b_0 *b; 
        __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, int _a, int flags=0) : a(_a) {
            impl.isa = &_NSConcreteStackBlock;
            impl.Flags = flags;
            impl.FuncPtr = fp;  
            Desc = desc;
        }
    }
    
    struct __Block_byref_b_0 {
        void *__isa;
        __Block_byref_b_0 *__forwarding;
        int __flags;
        int __size;
        int b;
    };
    
    struct __block_impl {
        void *isa;
        int Flags;
        int Reserved;
        void *FuncPtr;
    }
    
    block =  &__main_block_impl_0(__main_block_func_0, &__main_block_desc_0_DATA, a)
    block->FuncPtr(block);
    
    獲取到的基礎變量的值在block初始化的時候已經確定了,block外部的變量a在后續(xù)無論做什么操作,都不會影響block內部保存的變量a
    
    UIView 繼承 UIResponder,而 UIResponder 是響應者對象,可以對iOS 中的事件響應及傳遞,CALayer 沒有繼承自 UIResponder,所以 CALayer 不具備響應處理事件的能力
    
    self和super底層實現(xiàn)原理:

    id objc_msgSend(id theReceiver, SEL theSelector, ...) 當使用 self 調用方法時,會從當前類的方法列表中開始找,如果沒有,就從父類中再找;
    
    id objc_msgSendSuper(struct objc_super *super, SEL op, ...) 而當使用 super 時,則從父類的方法列表中開始找,然后調用父類的這個方法
    
    @synthesize 是如果你沒有手動實現(xiàn) setter 方法和 getter 方法,那么編譯器會自動為你加上這兩個方法
    @dynamic 告訴編譯器:屬性的 setter 與 getter 方法由用戶自己實現(xiàn),不自動生成
    
    oc調用js代碼兩種方式:
    1.通過webVIew調用 webView stringByEvaluatingJavaScriptFromString: 調用
    2.通過JSContext調用[context evaluateScript:];
    
    物理層 數(shù)據鏈路層 網絡層 傳輸層(TCP協(xié)議) 會話層 表示層 應用層(HTTP協(xié)議)
    
    TCP:面向連接、傳輸可靠(保證數(shù)據正確性,保證數(shù)據順序)、用于傳輸大量數(shù)據(流模式)、速度慢,建立連接需要開銷較多(時間,系統(tǒng)資源)。
    UDP:面向非連接、傳輸不可靠、用于傳輸少量數(shù)據(數(shù)據包模式)、速度快。
    
    
    - (void)viewDidLoad{
            [super viewDidLoad];
            dispatch_sync(dispatch_get_main_queue(),^{
                NSLog(@"deadlock");
            });
    }
    在主線程中運用主隊列同步,也就是把任務放到了主線程的隊列中。
    同步對于任務是立刻執(zhí)行的,那么當把任務放進主隊列時,它就會立馬執(zhí)行,只有執(zhí)行完這個任務,viewDidLoad才會繼續(xù)向下執(zhí)行。
    而 viewDidLoad 和任務都是在主隊列上的,由于隊列的先進先出原則,
    任務又需等待viewDidLoad執(zhí)行完畢后才能繼續(xù)執(zhí)行,
    viewDidLoad 和這個任務就形成了相互循環(huán)等待,就造成了死鎖。
    
    dispatch_queue_t serialQueue = dispatch_queue_create("test",DISPATCH_QUEUE_SERIAL);
    dispatch_async(serialQueue,^{
            dispatch_sync(serialQueue,^{
                NSLog(@"deadlock");
            });
    });
    外面的函數(shù)無論是同步還是異步都會造成死鎖。
    這是因為里面的任務和外面的任務都在同一個 serialQueue 隊列內,又是同步,這就和上邊主隊列同步的例子一樣造成了死鎖;
    解決方法也和上邊一樣,將里面的同步改成異步dispatch_async
    或者將 serialQueue 換成其他串行或并行隊列,都可以解決
    
    dispatch_queue_t serialQueue = dispatch_queue_create("test",DISPATCH_QUEUE_SERIAL);
    dispatch_queue_t serialQueue2 = dispatch_queue_create("test2",DISPATCH_QUEUE_SERIAL);
    dispatch_async(serialQueue,^{
            dispatch_sync(serialQueue2,^{
                NSLog(@"deadlock");
            });
    });
    這樣是不會死鎖的,并且 serialQueue和serialQueue2是在同一個線程中的。
    
    5、自旋鎖:OSSpinLock
    6、互斥鎖:pthread_mutex、@synchronized、NSLock、NSConditionLock 、NSCondition、NSRecursiveLock、dispatch_semaphore_t  os_unfair_lock
    
    對稱加密(3DES|AES|DES)  加密和解密使用同一個密鑰 
    
    非對稱加密(RSA)  需要兩個密鑰:公開密鑰(publickey) 和私有密(privatekey) 
    如果用公開密鑰對數(shù)據進行加密,只有用對應的私有密鑰才能解密。 
    如果用私有密鑰對數(shù)據進行加密,只有用對應的公開密鑰才能解密。
    
    原始報文/摘要/數(shù)字簽名:原始報文即為經過加密處理的報文,當原始報文經過了一些hash算法處理之后就成為了數(shù)字摘要,再經過RSA處理之后,當數(shù)字摘要經過密鑰加密之后就成為了數(shù)字簽名
    
    數(shù)字簽名的作用主要是:確保發(fā)送的報文沒有被篡改
    
    class方法和object_getClass方法的區(qū)別:
    
    object_getClass(obj): 返回的是obj的isa指針
    [obj class]: obj為實例對象   返回的obj對象中的isa指針;
                obj為類對象(包括元類和根類以及根元類)   返回的結果為調用者本身;
                
    Class Extension在編譯的時候,它的數(shù)據就已經包含在類信息中;
    Category是在運行時,才會將數(shù)據合并到類信息中; 為一個類添加額外的原來沒有變量,方法和屬性
    
    
    iOS和h5之間的交互:
    
    1.利用UIWebView交互    通過調用JS來實現(xiàn)OC調用JS    stringByEvaluatingJavaScriptFromString
                         通過協(xié)議攔截實現(xiàn)JS調用OC     webView:shouldStartLoadWithRequest:navigationType:
                         
    2.JavaScriptCore.framework原生框架 
                         OC調用JS    evalueScript()
                         
    3.WKWebView的交互     JS調用OC   [self.webView.configuration.userContentController addScriptMessageHandler:self name:@"Share"];  
                         OC調用JS evaluateJavaScript:
                         
    4.WebViewJavascriptBridge  
    
    1、客戶端APP將蘋果APNS服務器返回的devicetoken發(fā)送給我們自己的服務端程序;
    2、推消息時,我們服務器根據devicetoken向蘋果APNS服務器發(fā)送消息;
    3、蘋果APNS服務器將消息根據devicetoken發(fā)送給客戶端;
    
iOS匯編相關知識:
    1.寄存器: ARM64 有34個寄存器,包括31個通用寄存器、SP、PC、CPSR
    2.通用寄存器:x0~x28(64位的) (w0~w28(32位)對應的的x0~x28的低32位) ,x0~x7一般是用來存儲函數(shù)的參數(shù),更多參數(shù),則用堆棧來傳遞,x0一般用作函數(shù)的返回值
    3.PC: 程序計數(shù)器,存儲著當前執(zhí)行的指令
    4.FP:棧頂指針,指向一個棧幀的頂部,當函數(shù)發(fā)生跳轉時,會記錄當時的棧的起始位置。
    5.SP:棧指針(也稱為棧底指針),指向棧當前的位置。
    6.CPSR:狀態(tài)寄存器
        NZCV是狀態(tài)寄存器的條件標志位,分別代表運算過程中產生的狀態(tài),其中:
        N, negative condition flag,一般代表運算結果是負數(shù)
        Z, zero condition flag, 指令結果為0時Z=1,否則Z=0;
        C, carry condition flag, 無符號運算有溢出時,C=1。
        V, oVerflow condition flag 有符號運算有溢出時,V=1。
    7.LR:通常稱X30為程序鏈接寄存器,保存子程序結束后需要執(zhí)行的下一條指令
    8.wzr:32位零寄存器
    9.xzr:64位零寄存器

    mov    X1,X0         將寄存器X0的值傳送到寄存器X1
    add    X0,X1,X2     寄存器X1和X2的值相加后傳送到X0
    sub    X0,X1,X2     寄存器X1和X2的值相減后傳送到X0

    and    X0,X0,#0xF    X0的值與0xF相位與后的值傳送到X0
    orr    X0,X0,#9      X0的值與9相位或后的值傳送到X0
    eor    X0,X0,#0xF    X0的值與0xF相異或后的值傳送到X0
    
    ldr    X5,[X6,#0x08]           ld:load X6寄存器加0x08的和的地址值內的數(shù)據傳送到X5
    ldp    x29, x30, [sp, #0x10]    ldp :load pair 一對寄存器, 從內存讀取數(shù)據到寄存器
    
    str    X0, [sp, #0x8]           st:store, str:往內存中寫數(shù)據(偏移值為正); X0寄存器的數(shù)據傳送到SP+0x8地址值指向的存儲空間
    stur   w0, [x29, #-0x8]         往內存中寫數(shù)據(偏移值為負)
    stp    x29, x30, [sp, #0x10]    store pair,存放一對數(shù)據, 入棧指令
    
    cmp   比較指令,影響程序狀態(tài)寄存器CPSR 
    b     跳轉指令,可帶條件跳轉與cmp配合使用
    bl    帶返回的跳轉指令, 返回地址保存到LR(X30)  
    
    ret:函數(shù)返回,相當于return
    
    
    葉子函數(shù):
    void test(){
        int a = 2;
        int b = 3;
    }
    sub sp, sp, #16             ; =16,sp棧頂指針上移16個字節(jié)
    .cfi_def_cfa_offset 16
    mov w8, #2                  ;將2存入w8寄存器
    str w8, [sp, #12]           ;將w8寄存器的數(shù)據存入到sp下移12個字節(jié)的所在位置下面的4字節(jié)
    mov w8, #3                  ;將3存入w8寄存器
    str w8, [sp, #8]            ;將w8寄存器的數(shù)據存入到sp下移8個字節(jié)的所在位置下面的4字節(jié)
    add sp, sp, #16             ; =16,sp棧頂指針下移16個字節(jié),恢復到初始位置
    ret
    
    非葉子函數(shù),除了葉子函數(shù),其他函數(shù)叫非葉子函數(shù):
    void excute(){
        int a = 4;
        int b = 5;
        test();
    }
    void test(){
        int a = 2;
        int b = 3;
    }
    
    Mach-O包括以下幾種類型:
        OBJECT,指的是.o或.a文件(目標文件)
        EXECUTE,指的是IPA拆包后的文件(可執(zhí)行文件)
        DYLIB,指的是.dylib或.framework文件(動態(tài)庫文件)
        DYLINKER,指的是動態(tài)連接器(動態(tài)鏈接器文件)
        DSYM(符號表),指的是有保存符號信息用于分析閃退信息的文件(符號表文件)
        
    加載過程:
        1.把可執(zhí)行文件加載到內存中,并從它中分析出dyld的路徑,再把dyld加載到內存中,最后dyld遞歸加載所有的動態(tài)鏈接庫dylib
        
    dyld可以用來加載以下三種類型的Mach-O文件
        MH_EXECUTE
        MH_DYLIB
        MH_BUNDLE
        
    .p12 文件:Mac本地生成的鑰匙對私鑰。由于私鑰是本地私有的,.p12將私鑰導出給其他團隊成員使用
    
    當一個對象obj被weak指針指向時,這個weak指針會以obj作為key,weak指針的地址數(shù)組作為value,被存儲到sideTable類的weak_table這個散列表上對應的一個weak指針數(shù)組里面。
    當一個對象obj的dealloc方法被調用時,Runtime會以obj為key,從sideTable的weak_table散列表中,找出對應的weak指針列表,然后將里面的weak指針逐個置為nil。

    + (BOOL)isKindOfClass:(Class)cls {
        for (Class tcls = self->ISA(); tcls; tcls = tcls->superclass) {
            if (tcls == cls) return YES;
        }
        return NO;
    }
    
    - (BOOL)isKindOfClass:(Class)cls {
        for (Class tcls = [self class]; tcls; tcls = tcls->superclass) {
            if (tcls == cls) return YES;
        }
        return NO;
    }
    
    + (BOOL)isMemberOfClass:(Class)cls {
        return self->ISA() == cls;
    }
    
    - (BOOL)isMemberOfClass:(Class)cls {
        return [self class] == cls;
    }

    (lldb) e id $hgView = (id)0x7fdfc66127f0
    (lldb) e (void)[$hgView setBackgroundColor:[UIColor redColor]]
    (lldb) e (void)[CATransaction flush]

    iOS UITableView 的 優(yōu)化:   
        1.Tableview 懶加載、Cell 重用
        2.高度緩存(因為 heightForRowAtIndexPath: 是調用最頻繁的方法)
        3.數(shù)據處理:
            3.1.使用正確的數(shù)據結構來存儲數(shù)據
            3.2.數(shù)據盡量采用局部的 section,或 cellRow 的刷新,避免 reloadData
            3.3.大量數(shù)據操作時,使用異步子線程處理,避免主線程中直接操作
        4.異步加載圖片:SDWebImage 的使用:
            4.1.使用異步子線程處理,然后再返回主線程操作
            4.2.圖片緩存處理,避免多次處理操作
        5.按需加載內容,只顯示目標范圍內的 Cell 內容
        6.減少Subviews 的數(shù)量
        7.不要動態(tài)添加視圖或移除視圖,用hidden顯示(隱藏)Subviews
    
    同步執(zhí)行(sync):
        1.同步添加任務到指定的隊列中,在添加的任務執(zhí)行結束之前,會一直等待,直到隊列里面的任務完成之后再繼續(xù)執(zhí)行
        2.只能在當前線程中執(zhí)行任務,不具備開啟新線程的能力
    異步執(zhí)行(async)
        1.異步添加任務到指定的隊列中,它不會做任何等待,可以繼續(xù)執(zhí)行任務
        2.可以在新的線程中執(zhí)行任務,具備開啟新線程的能力
        
    iOS編譯的過程:
        預處理:處理以#開頭的命令,刪除注釋,解開宏定義等
        編譯:詞法分析、語法分析、語義分析、中間代碼生成與優(yōu)化,最終生成匯編代碼
        匯編:將匯編代碼翻譯成機器碼,生成.o目標文件
        鏈接:將多個.o目標文件和其他函數(shù)庫鏈接成可執(zhí)行文件
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容