1.UIControlEventTouchDown
單點觸摸按下事件:用戶點觸屏幕,或者又有新手指落下的時候。
2.UIControlEventTouchDownRepeat
多點觸摸按下事件,點觸計數大於1:用戶按下第二、三、或第四根手指的時候。
3.UIControlEventTouchDragInside
當一次觸摸在控件窗口內拖動時。
4.UIControlEventTouchDragOutside
當一次觸摸在控件窗口之外拖動時。
5.UIControlEventTouchDragEnter
當一次觸摸從控件窗口之外拖動到內部時。
6.UIControlEventTouchDragExit
當一次觸摸從控件窗口內部拖動到外部時。
7.UIControlEventTouchUpInside
所有在控件之內觸摸擡起事件。
8.UIControlEventTouchUpOutside
所有在控件之外觸摸擡起事件(點觸必須開始與控件內部纔會發送通知)。
9.UIControlEventTouchCancel
所有觸摸取消事件,即一次觸摸因爲放上了太多手指而被取消,或者被上鎖或者電話呼叫打斷。
10.UIControlEventTouchChanged
當控件的值發生改變時,發送通知。用於滑塊、分段控件、以及其他取值的控件。你可以配置滑塊控件何時發送通知,在滑塊被放下時發送,或者在被拖動時發送。
11.UIControlEventEditingDidBegin
當文本控件中開始編輯時發送通知。
12.UIControlEventEditingChanged
當文本控件中的文本被改變時發送通知。
13.UIControlEventEditingDidEnd
當文本控件中編輯結束時發送通知。
14.UIControlEventEditingDidOnExit
當文本控件內通過按下回車鍵(或等價行爲)結束編輯時,發送通知。
15.UIControlEventAlltouchEvents
通知所有觸摸事件。
16.UIControlEventAllEditingEvents
通知所有關於文本編輯的事件。
17.UIControlEventAllEvents
通知所有事件
一、明確兩點
1.Block可以訪問Block函數以及語法作用域以內的外部變量。也就是說:一個函數裏定義了一個block,這個block可以訪問該函數的內部變量(當然還包括靜態,全局變量),即block可以使用和本身定義範圍相同的變量。
2.Block其實是特殊的Objective-C對象,可以使用copy、release等來管理內存,但和一般的NSObject的管理方式有些不同,稍後會說明。
二、Block語法
Block很像函數指針,這從Block的語法上就可以看出。
Block的原型:
返回值 (^名稱)(參數列表)
Block的定義
^ 返回值類型 (參數列表) { 表達式 }
其中返回值類型和參數列表都可以省略,最簡單的Block就是:
^{ ; };
一般的定義就是:
返回值 (^名稱)(參數列表) = ^(參數列表){代碼段};
爲了方便通常使用typedef定義:
typedef void (^blk) (void);
三、Block存儲域
Block能夠截獲自動變量,自動變量的當前值會被拷貝到棧上作爲常量,此時不能在Block內對自動變量進行賦值操作,如果有這種需求,則需要該變量是:
1.靜態變量
2.全局變量
3.或者使用__block修飾符
根據Block中是否引用了自動變量,可以將Block存儲區域分類:
1.__NSStackBlock__存儲在棧上
2.__NSGlobalBlock__存儲在全局數據區域(和全局變量一樣)
3.__NSMallocBlock__存儲在堆上
沒有引用自動變量或者在全局作用域的Block爲__NSGlobalBlock__,其他的基本上都是__NSStackBlock__。對__NSStackBlock__執行copy操作會生成__NSMallocBlock__。
一般來說出問題的Block大部分都是__NSStackBlock__,超過了__NSStackBlock__的作用域__NSStackBlock__就會銷燬。
四、對Block執行retain,copy方法的效果
Block是C語言的擴展,C語法也可以使用Block的語法,對應的C語言使用Block_copy、Block_release。
無論是__NSStackBlock__,還是__NSGlobalBlock__,執行retain都不起作用。而__NSMallocBlock__執行retain引用計數+1。
對於copy操作,__NSStackBlock__會被複制到堆上得到一份新的__NSMallocBlock__,__NSStackBlock__還是存在的,而__NSGlobalBlock__執行copy操作不起作用。而對__NSMallocBlock__執行copy操作會引起引用計數加1。
五、什麼時候要對__NSStackBlock__執行copy操作?
配置在棧上的Block也就是__NSStackBlock__類型的Block,如果其所屬的變量作用域結束該Block就會廢棄。這個時候如果繼續使用該Block,就應該使用copy方法,將__NSStackBlock__拷貝爲__NSMallocBlock__。當__NSMallocBlock__的引用計數變爲0,該__NSMallocBlock__就會被釋放。
如果是非ARC環境,需要顯式的執行copy或者antorelease方法。
而當ARC有效的時候,實際上大部分情況下編譯器已經爲我們做好了,自動的將Block從棧上覆制到堆上。包括以下幾個情況:
1.Block作爲返回值時,類似在非ARC的時候,對返回值Block執行[[returnedBlock copy] autorelease];
2.方法的參數中傳遞Block時
3.Cocoa框架中方法名中還有useringBlock等時
4.GCD相關的一系列API傳遞Block時
比如:[mutableAarry addObject:stackBlock];這段代碼在非ARC環境下肯定有問題,而在ARC環境下方法參數中傳遞__NSStackBlock__會自動執行copy,所以就不會出現問題。
六、Block的循環引用
對於非ARC下,爲了防止循環引用,我們使用__block來修飾在Block中使用的對象。
對於ARC下,爲了防止循環引用,我們使用__weak來修飾在Block中使用的對象。
原理就是:ARC中,Block中如果引用了__strong修飾符的自動變量,則相當於Block對該對象的引用計數+1。
七、代碼驗證
驗證__NSStackBlock__
我們往可變數組中添加一個__NSStackBlock__。
在MRC環境下,__NSStackBlock__在自身作用域結束後就從棧中釋放,所以我們再次使用它的時候,程序就會發生崩潰。
在ARC環境下,編譯器會自動對__NSStackBlock__執行copy,拷貝一份到堆上生成一個新的__NSMallocBlock__,我們再次使用它的時候,程序正常運行
-
棧(stack):由編譯器自動分配釋放 ,存放函數的參數值,局部變量的值等。其操作方式類似於數據結構中的棧。
堆(heap): 一般由程序員分配釋放, 若程序員不釋放,程序結束時可能由OS回收 。注意它與數據結構中的堆是兩回事,分配方式類似於鏈表。
全局區(靜態區static):全局變量和靜態變量的存儲是放在一塊的,初始化的全局變量和靜態變量在一塊區域, 未初始化的全局變量和未初始化的靜態變量在相鄰的另一塊區域,程序結束後由系統釋放。
文字常量區:常量字符串放在這裏, 程序結束後由系統釋放
程序代碼區:存放函數體的二進制代碼。
程序示例
Block基本語法
修飾Block的成員變量
Block 成員需要使用 copy 進行修飾,需要考慮Block是否線程安全,必要情況下使用atomic參數,當使用atomic參數也不能百分百確保線程安全,因此在使用時最好將block屬性賦值給本地變量在使用,以防止其它線程將self.block置空。實際上,我們使用修飾符 copy 是因爲將存在棧區上的block轉移到堆區上,這個習慣是在MRC下的,現在在ARC下使用 copy 和 strong 是相同的。
解決self循環引用的問題(ARC)
AFNetworking的使用技巧
把變量在 block 外先用 __weak
聲明,在
block 內把前面 __weak
聲明的變量在賦值給 __strong
修飾的變量。這種寫法的好處就是可以讓變量在
block 內部安全使用,即使外部對象釋放了,也會在 block 的生命週期內保留該變量。這種寫法非常巧妙,既避免了循環引用的問題,又可以在 block 內部持有該變量。
棧(stack):由編譯器自動分配釋放 ,存放函數的參數值,局部變量的值等。其操作方式類似於數據結構中的棧。
堆(heap): 一般由程序員分配釋放, 若程序員不釋放,程序結束時可能由OS回收 。注意它與數據結構中的堆是兩回事,分配方式類似於鏈表。
全局區(靜態區static):全局變量和靜態變量的存儲是放在一塊的,初始化的全局變量和靜態變量在一塊區域, 未初始化的全局變量和未初始化的靜態變量在相鄰的另一塊區域,程序結束後由系統釋放。
文字常量區:常量字符串放在這裏, 程序結束後由系統釋放
程序代碼區:存放函數體的二進制代碼。
程序示例
Block基本語法
修飾Block的成員變量
Block 成員需要使用 copy 進行修飾,需要考慮Block是否線程安全,必要情況下使用atomic參數,當使用atomic參數也不能百分百確保線程安全,因此在使用時最好將block屬性賦值給本地變量在使用,以防止其它線程將self.block置空。實際上,我們使用修飾符 copy 是因爲將存在棧區上的block轉移到堆區上,這個習慣是在MRC下的,現在在ARC下使用 copy 和 strong 是相同的。
解決self循環引用的問題(ARC)
AFNetworking的使用技巧
把變量在 block 外先用 __weak
聲明,在
block 內把前面 __weak
聲明的變量在賦值給 __strong
修飾的變量。這種寫法的好處就是可以讓變量在
block 內部安全使用,即使外部對象釋放了,也會在 block 的生命週期內保留該變量。這種寫法非常巧妙,既避免了循環引用的問題,又可以在 block 內部持有該變量。
寫博客第九十九天;
QQ:565803433