UITableView 和 UITableViewController
UITableView:显示有多行数据的一个列。
新建一个过程:Xcode -> File -> New -> Project...,然后选择iOS -> Application -> Single View Application.
Product Name为HomePwner,其他设置如下所示:
当使用UITableView的时候,我们必须考虑还需要什么来让这个table能在你的App上工作。
1)一个UITableView一般需要一个视图控制器来处理其在屏幕上显示的样式;
2)一个UITableView需要一个数据源;
3)一个UITableView一般需要一个委托对象,通知其他对象涉及UITableView的事件。委托可以是任何对象,只要其遵守UITableViewDelegate协议。
UITableViewController类实例满足上述三个角色,即:视图控制器、数据源和委托。当UITableViewController创建了一个UITableView视图时,UITableView的dataSource和delegate实例变量自动设置为指向UITableViewController。其关系如下所示:
创建一个UITableViewController的子类:
File -> New -> File...,iOS -> Source -> Cocoa Touch Class,点击Next,Class为:BNRItemsViewController,其他设置如下:
UITableViewController指定的初始化方法为initWithStyle:,我们现在编写BNRItemsViewController指定初始化方法为init,需要1)调用父类的指定初始化方法;2)重载父类的指定初始化方法。
在BNRItemsViewController.m中添加如下代码:
1 - (instancetype)init { 2 self = [super initWithStyle:UITableViewStylePlain]; 3 return self; 4 } 5 6 - (instancetype)initWithStyle:(UITableViewStyle)style { 7 return [self init]; 8 }
由于不用默认的视图控制器作为根视图控制器,所以修改如下设置:点击工程名Homepwner -> Targets Homepwner -> General -> Deployment Info -> Main Interface 设置为空。
在BNRItemsViewController.m文件的顶部添加如下代码:
#import "BNRItemsViewController.h"
修改application:didFinishLaunchingWithOptions:方法如下:
1 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 2 // Override point for customization after application launch. 3 self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 4 BNRItemsViewController *itemsViewController = [[BNRItemsViewController alloc] init]; 5 self.window.rootViewController = itemsViewController; 6 self.window.backgroundColor = [UIColor whiteColor]; 7 [self.window makeKeyAndVisible]; 8 return YES; 9 }
添加BNRItem类,File -> New -> File...,iOS -> Source -> Cocoa Touch Class,点击Next,Class为:BNRItem;Subclass of:NSObject。
BNRItem.h的内容如下所示:
1 #import <Foundation/Foundation.h> 2 3 @interface BNRItem : NSObject 4 5 @property (nonatomic, copy) NSString *itemName; 6 @property (nonatomic, copy) NSString *serialNumber; 7 @property (nonatomic) int valueInDollars; 8 @property (nonatomic, readonly) NSDate *dateCreated; 9 10 + (instancetype)randomItem; 11 12 // Designated initializer for BNRItem 13 - (instancetype)initWithItemName:(NSString *)name 14 valueInDollars:(int)value 15 serialNumber:(NSString *)sNumber; 16 17 - (instancetype)initWithItemName:(NSString *)name; 18 19 @end
BNRItem.m的内容如下所示:
1 #import "BNRItem.h" 2 3 @implementation BNRItem 4 5 + (instancetype)randomItem 6 { 7 // Create an immutable array of three adjectives 8 NSArray *randomAdjectiveList = @[@"Fluffy", @"Rusty", @"Shiny"]; 9 10 // Create an immutable array of three nouns 11 NSArray *randomNounList = @[@"Bear", @"Spork", @"Mac"]; 12 13 // Get the index of a random adjective/noun from the lists 14 // Note: The % operator, called the modulo operator, gives 15 // you the remainder. So adjectiveIndex is a random number 16 // from 0 to 2 inclusive. 17 NSInteger adjectiveIndex = arc4random() % [randomAdjectiveList count]; 18 NSInteger nounIndex = arc4random() % [randomNounList count]; 19 20 // Note that NSInteger is not an object, but a type definition 21 // for "long" 22 23 NSString *randomName = [NSString stringWithFormat:@"%@ %@", 24 randomAdjectiveList[adjectiveIndex], 25 randomNounList[nounIndex]]; 26 27 int randomValue = arc4random() % 100; 28 29 NSString *randomSerialNumber = [NSString stringWithFormat:@"%c%c%c%c%c", 30 '0' + arc4random() % 10, 31 'A' + arc4random() % 26, 32 '0' + arc4random() % 10, 33 'A' + arc4random() % 26, 34 '0' + arc4random() % 10]; 35 36 BNRItem *newItem = [[self alloc] initWithItemName:randomName 37 valueInDollars:randomValue 38 serialNumber:randomSerialNumber]; 39 40 return newItem; 41 } 42 43 - (instancetype)initWithItemName:(NSString *)name 44 valueInDollars:(int)value 45 serialNumber:(NSString *)sNumber 46 { 47 // Call the superclass's designated initializer 48 self = [super init]; 49 50 // Did the superclass's designated initializer succeed? 51 if (self) { 52 // Give the instance variables initial values 53 _itemName = name; 54 _serialNumber = sNumber; 55 _valueInDollars = value; 56 // Set _dateCreated to the current date and time 57 _dateCreated = [[NSDate alloc] init]; 58 } 59 60 // Return the address of the newly initialized object 61 return self; 62 } 63 64 - (instancetype)initWithItemName:(NSString *)name 65 { 66 return [self initWithItemName:name 67 valueInDollars:0 68 serialNumber:@""]; 69 } 70 71 - (instancetype)init 72 { 73 return [self initWithItemName:@"Item"]; 74 } 75 76 - (void)dealloc 77 { 78 NSLog(@"Destroyed: %@", self); 79 } 80 81 - (NSString *)description 82 { 83 NSString *descriptionString = 84 [[NSString alloc] initWithFormat:@"%@ (%@): Worth $%d, recorded on %@", 85 self.itemName, 86 self.serialNumber, 87 self.valueInDollars, 88 self.dateCreated]; 89 return descriptionString; 90 } 91 92 @end
添加BNRItemStore类,File -> New -> File...,iOS -> Source -> Cocoa Touch Class,点击Next,Class为:BNRItemStore;Subclass of:NSObject。
BNRItemStore将是一个singleton,意味着在app中,这个类的对象就只有一个。
BNRItemStore.h添加如下代码:
1 #import <Foundation/Foundation.h> 2 @class BNRItem; 3 4 @interface BNRItemStore : NSObject 5 6 @property (nonatomic, readonly) NSArray *allItems; 7 8 + (instancetype)sharedStore; 9 - (BNRItem *)createItem; 10 11 @end
BNRItemStore.m添加如下代码:
1 #import "BNRItemStore.h" 2 #import "BNRItem.h" 3 4 @interface BNRItemStore () 5 6 @property (nonatomic) NSMutableArray *privateItems; 7 8 @end 9 10 @implementation BNRItemStore 11 12 + (instancetype)sharedStore { 13 static BNRItemStore *sharedStore = nil; 14 if (!sharedStore) { 15 sharedStore = [[self alloc] initPrivate]; 16 } 17 return sharedStore; 18 } 19 20 - (instancetype)init { 21 @throw [NSException exceptionWithName:@"Singleton" 22 reason:@"Use+[BNRItemStore sharedStore]" userInfo:nil]; 23 return nil; 24 } 25 26 - (instancetype)initPrivate { 27 self = [super init]; 28 if (self) { 29 _privateItems = [[NSMutableArray alloc] init]; 30 } 31 return self; 32 } 33 34 - (NSArray *)allItems { 35 return self.privateItems; 36 } 37 38 - (BNRItem *)createItem { 39 BNRItem *item = [BNRItem randomItem]; 40 [self.privateItems addObject:item]; 41 return item; 42 } 43 44 @end
在sharedStore类方法中声明了一个static变量为sharedStore,当该方法执行完毕的时候,该指针指向的变量不会被销毁。
返回BNRItemsViewController.m文件,如下,导入BNRItemStore.h和BNRItem.h:
#import "BNRItem.h" #import "BNRItemStore.h"
然后,更新指定初始化方法:
1 - (instancetype)init { 2 self = [super initWithStyle:UITableViewStylePlain]; 3 if (self) { 4 // 添加5个随机item 5 for (int i = 0; i < 5; ++i) { 6 [[BNRItemStore sharedStore] createItem]; 7 } 8 } 9 return self; 10 }
BNRItemsViewController遵守UITableViewwDataSource,必须实现tableView:numberOfRowsInSection:和tableView:cellForRowAtIndexPath:。
1 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 2 return [[[BNRItemStore sharedStore] allItems] count]; 3 }
1 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 2 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"UITableViewCell" 3 forIndexPath:indexPath]; 4 NSArray *items = [[BNRItemStore sharedStore] allItems]; 5 BNRItem *item = items[indexPath.row]; 6 cell.textLabel.text = [item description]; 7 return cell; 8 }
1 - (void)viewDidLoad { 2 [super viewDidLoad]; 3 [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"UITableViewCell"]; 4 }
运行程序,结果如下所示: