[OC] 使用 block 實現函式巢狀
在 Swift 中,在函式內部定義一個函式即函式巢狀,舉例如下:
func foo() { var a = 1 func bar() { a += 1 } bar() } 複製程式碼
在 OC 中沒有這類特性,不過如果聯想到 Swift 中函式實際是一種有名字的閉包,那麼函式巢狀的思想就可以延伸到 OC 語言中了。
OC 函式巢狀的實現
- (void)foo { __block NSInteger a = 1; void(^bar)(void) = ^{ a += 1; }; bar(); } 複製程式碼
由此可見,將巢狀的函式邏輯封裝到一個 block,這樣就可以在需要時直接呼叫 block,而不需要另外宣告一個方法了。
應用場景的延伸
凡用到巢狀函式的場景,往往也是這一段需要在一個函式/方法的內部多次使用邏輯,不需要外界知曉,比如:
- 地址格式化邏輯
- 日期格式化
- 資料解析操作
這些 block 變數就像一個個小函式一樣隨時呼叫,舉個應用的例子:
NSString *(^formatDate)(NSDate *) = ^NSString *(NSDate *date) { NSString *str = [date formatYMD]; return str ?: @""; }; NSString *(^formatStamp)(NSString *) = ^NSString *(NSString *stamp){ NSDate *date = [NSDate dateWithTimeIntervalSince1970:stamp.doubleValue]; return formatDate(date); }; userInfo = @{ kCellLeftTitle : @"起運時間", kCellRightContent : formatStamp(self.model.from_begin_time), kCellModelKey : [NSDate dateWithTimeIntervalSince1970:self.model.from_begin_time.doubleValue], kTextFieldDisableKey : @YES, kHasIndicatorKey : @YES, }; row.didSelectCellBlock = ^(NSIndexPath *indexPath, id value, id cell) { WSDatePickerView *picker = [[WSDatePickerView alloc] initWithDateStyle:DateStyleShowYearMonthDay CompleteBlock:^(NSDate *selected) { value[kCellModelKey] = selected; value[kCellRightContent] = formatDate(selected); [weakSelf.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone]; }]; picker.selectedDate = value[kCellModelKey]; [picker show]; }; 複製程式碼
上述程式碼中是在一個方法體的內部,聲明瞭兩個 block 變數做巢狀函式使用,分別是 formatDate 和 formatStamp,用於處理模型資料中的 日期和時間戳的字串表示邏輯。