塊代碼編程---開始使用塊代碼

本文檔版權歸NickTang所有,沒有本人書面或電子郵件允許,不許轉載,摘錄,發表。多謝!


本章的幾節使用例子代碼來開始塊代碼的學習。

定義和使用塊代碼

插入符^有兩個作用,一個是聲明一個塊代碼變量,另一個是開始一個塊代碼的定義。塊代碼的代碼部分是包含在一對大括號中的,就像下面演示的這樣(使用C語言風格的分號;作爲塊代碼行的結束):

int multiplier = 7;
int (^myBlock)(int) = ^(int num) {
    return num * multiplier;
};

下圖是對塊代碼的詳細演示:

image: ../Art/blocks.jpg

主義塊代碼中可以使用和它有同一個生存域的變量的。

如果你聲明瞭一個塊代碼變量,你可以在後面像使用函數一樣使用它:

int multiplier = 7;
int (^myBlock)(int) = ^(int num) {
    return num * multiplier;
};
 
printf("%d", myBlock(3));
// prints "21"

直接使用塊代碼

很多情況下,你不需要聲明塊代碼變量,你把一個塊代碼直接做內聯實現,然後作爲函數參數傳入函數。下面的例子使用函數qsort_bqsort_b和函數qsort_r很像,不過它使用一個塊代碼作爲參數。

char *myCharacters[3] = { "TomJohn", "George", "Charles Condomine" };
 
qsort_b(myCharacters, 3, sizeof(char *), ^(const void *l, const void *r) {
    char *left = *(char **)l;
    char *right = *(char **)r;
    return strncmp(left, right, 1);
});
 
// myCharacters is now { "Charles Condomine", "George", "TomJohn" }

Cocoa中的塊代碼

Cocoa框架中有不少函數是使用塊代碼作爲參數的,特別是在容器類中的包含對象的操作,或者一個操作完成後的回調函數。下面的例子演示了在NSArray類中的sortedArrayUsingComparator:函數中使用塊代碼,這個函數僅有一個參數,就是這個塊代碼,爲了演示,塊代碼被聲明爲NSComparator類型的本地變量:

NSArray *stringsArray = [NSArray arrayWithObjects:
                                 @"string 1",
                                 @"String 21",
                                 @"string 12",
                                 @"String 11",
                                 @"String 02", nil];
 
static NSStringCompareOptions comparisonOptions = NSCaseInsensitiveSearch | NSNumericSearch |
        NSWidthInsensitiveSearch | NSForcedOrderingSearch;
NSLocale *currentLocale = [NSLocale currentLocale];
 
NSComparator finderSortBlock = ^(id string1, id string2) {
 
    NSRange string1Range = NSMakeRange(0, [string1 length]);
    return [string1 compare:string2 options:comparisonOptions range:string1Range locale:currentLocale];
};
 
NSArray *finderSortArray = [stringsArray sortedArrayUsingComparator:finderSortBlock];
NSLog(@"finderSortArray: %@", finderSortArray);
 
/*
Output:
finderSortArray: (
    "string 1",
    "String 02",
    "String 11",
    "string 12",
    "String 21"
)
*/

__block類型變量

塊代碼的一個更強力的功能是可以修改具有同一可視週期的變量。當然你必須使用__block來修飾這個變量。考慮上節中的例子,如果我們需要使用一個變量來做一個統計,就像下例一樣。這裏的currentLocale變量對於代碼塊內部而言就是隻讀的。

NSArray *stringsArray = [NSArray arrayWithObjects:
                         @"string 1",
                         @"String 21", // <-
                         @"string 12",
                         @"String 11",
                         @"Strîng 21", // <-
                         @"Striñg 21", // <-
                         @"String 02", nil];
 
NSLocale *currentLocale = [NSLocale currentLocale];
__block NSUInteger orderedSameCount = 0;
 
NSArray *diacriticInsensitiveSortArray = [stringsArray sortedArrayUsingComparator:^(id string1, id string2) {
 
    NSRange string1Range = NSMakeRange(0, [string1 length]);
    NSComparisonResult comparisonResult = [string1 compare:string2 options:NSDiacriticInsensitiveSearch range:string1Range locale:currentLocale];
 
    if (comparisonResult == NSOrderedSame) {
        orderedSameCount++;
    }
    return comparisonResult;
}];
 
NSLog(@"diacriticInsensitiveSortArray: %@", diacriticInsensitiveSortArray);
NSLog(@"orderedSameCount: %d", orderedSameCount);
 
/*
Output:
 
diacriticInsensitiveSortArray: (
    "String 02",
    "string 1",
    "String 11",
    "string 12",
    "String 21",
    "Str\U00eeng 21",
    "Stri\U00f1g 21"
)
orderedSameCount: 2
*/

這個內容在“Blocks and Variables”中有更多細節描述。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章