![]() |
主畫面 |
![]() |
Table-Based Detail View |
Note: > 英文叫做 disclosure indicator
而 Detail View 設計的困難在於其對應關係,例如我按下 Name 這個 cell 、或是按下 Birthdate cell,會有不同的 Editing SubController 產生,要如何設計其對應關係, that's a challenge。
下面的 code 是一般的做法,這種 nested switch 的方式造成 maintain 上的困難,本章是結合 paired array 和 nested array 的方式來處理對應關係,有彈性的多。
enum HeroEditControllerSections {HeroEditControllerSectionName = 0,HeroEditControllerSectionGeneral,HeroEditControllerSectionCount};enum HeroEditControllerNameSection {HeroEditControllerNameRow = 0,HeroEditControllerNameSectionCount};enum HeroEditControllerGeneralSection {HeroEditControllerGeneralSectionSecretIdentityRow,HeroEditControllerGeneralSectionBirthdateRow,HeroEditControllerGeneralSectionSexRow,HeroEditControllerGeneralSectionCount};//Then, in every method where you are provided with an index path, you can take the//appropriate action based on the row and section represented by the index path, using//switch statements, like this:- (void)tableView:(UITableView *)tableViewdidSelectRowAtIndexPath:(NSIndexPath *)indexPath {NSUInteger section = [indexPath section];NSUInteger row = [indexPath row];switch (section) {case HeroEditControllerSectionName:switch (row){case HeroEditControllerNameRow :// Create a controller to edit name// and push it on the stack...break;default:break;}break;case HeroEditControllerSectionGeneral:switch (row) {case HeroEditControllerGeneralSectionSecretIdentityRow:// Create a controller to edit secret identity// and push it on the stack...CHAPTER 4: The Devil in the Detail View 87break;case HeroEditControllerGeneralSectionBirthdateRow:// Create a controller to edit birthdate and// push it on the stack...break;case HeroEditControllerGeneralSectionSexRow:// Create a controller to edit sex and push it// on the stack...break;default:break;}break;default:break;}}
// combine nested and paired array
- (void)viewDidLoad {sectionNames = [[NSArray alloc] initWithObjects:[NSNull null],NSLocalizedString(@"General", @"General"),nil];rowLabels = [[NSArray alloc] initWithObjects:// Section 1[NSArray arrayWithObjects:NSLocalizedString(@"Name", @"Name"), nil],// Section 2[NSArray arrayWithObjects:NSLocalizedString(@"Identity", @"Identity"),NSLocalizedString(@"Birthdate", @"Birthdate"),NSLocalizedString(@"Sex", @"Sex"),nil],// Sentinelnil];rowKeys = [[NSArray alloc] initWithObjects:// Section 1[NSArray arrayWithObjects:@"name", nil],// Section 2[NSArray arrayWithObjects:@"secretIdentity", @"birthdate", @"sex", nil],// Sentinelnil];rowControllers = [[NSArray alloc] initWithObjects:// Section 1[NSArray arrayWithObject:@"ManagedObjectStringEditor"],// Section 2[NSArray arrayWithObjects:@"ManagedObjectStringEditor",@"ManagedObjectDateEditor",@"ManagedObjectSingleSelectionListEditor", nil],// Sentinelnil];rowArguments = [[NSArray alloc] initWithObjects:// Section 1[NSArray arrayWithObject:[NSNull null]],// Section 2,[NSArray arrayWithObjects:[NSNull null],[NSNull null],[NSDictionary dictionaryWithObject:[NSArrayarrayWithObjects:@"Male", @"Female", nil]forKey:@"list"],nil],// Sentinelnil];[super viewDidLoad];}
這裡有用到 [NSNull null]] 到的技巧,第一次看不是很明白,主要是用於 unname section 的情況??
接下來是設計真正的 editing subcontroller 的部份,下面兩張圖分別是 Birthdate 和 Name 欄位的editing subcontroller,這裡用了相同的父類別 (終於用到繼承了 XD) 來提取相同的部份。
對於 attribute 的字串處理 ,用到了 category 的技巧,如下 code
@protocol HeroValueDisplay- (NSString *)heroValueDisplay;@end@interface NSString (HeroValueDisplay)- (NSString *)heroValueDisplay;@end@interface NSDate (HeroValueDisplay)- (NSString *)heroValueDisplay;@end@interface NSNumber (HeroValueDisplay)- (NSString *)heroValueDisplay;@end@interface NSDecimalNumber (HeroValueDisplay)- (NSString *)heroValueDisplay;@end
其他要注意的是
- loadview 的使用時機 (在 datapicker 中有用到)
- UIButton 和 Bar Button 之間的不同
- NSClassFromString 的使用技巧 (like Java's Introspection)
這章很多東西 = =

hi
沒有留言:
張貼留言