iOS programming UITableView and UITableViewController,iosuitableview多選
iOS programming UITableView and UITableViewController
A UITableView displays a single column of data with a variable number of rows.
UITableView 展示單列資料和不定數量的行。
Create a new iOS Empty Application project and configure it
1.1 UITableViewController
Model-View-Controller design pattern
(1)Model: Holds data and knows nothing about the user interface.
擁有資料卻不知道使用者介面。
(2)View: Is visible to the user and knows nothing about the model objects.
可以被使用者看到,卻不知道model對象
(3)Controller: Keeps the user interface and the model objects in sync. Controls the flow of the application; for example, the controller might be responsible for showing a "Really delete this item?" message before actually deleting some data.
保持使用者介面和模型對象同步。例如控制器可能在確定要刪除一些資料之前,負責顯示 "確定要刪除這項嗎" 。
a UITableView, a view object, does not handle application logic or data.
因此,UITableView,一個view object ,不知道如何處理邏輯和資料。
When using a UITableView, you must consider what else is necessary to get the table working in your application:
當你想使用一個UITableIView時,你必須考慮在你的應用程式中還有什麼需要的才能讓table 工作。
(1)A UITableView typically needs a view controller to handle its appearance on the screen.
一個UITableView 一般需要一個view controller 處理它的顯示部分。
(2)A UITableView needs a data source. A UITableView asks its data source for the number of rows
to display, the data to be shown in those rows, and other tidbits that make a UITableView a useful user interface. Without a data source, a table view is just an empty container. The dataSource for a UITableView can be any type of Objective-C object as long as it conforms to the UITableViewDataSource protocol.
UITableView需要一個data source.一個UITableView 要求data source 有幾行要顯示,要顯示的資料,和其他好東西讓UITableView 成為一個有用的user interface .datasource 可以是任何順從了UITableViewDataSource protocol 的對象。
(3)A UITableView typically needs a delegate that can inform other objects of events involving the UITableView. The delegate can be any object as long as it conforms to the UITableViewDelegate protocol.
UITableVIew 一般需要一個delegate 來通知其他涉及UITableView的對象。delegate可以是任何遵守了UITableViewDelegate protocol 的對象。
An instance of the class UITableViewController can fill all three roles: view controller, data source, and delegate.
一個UITableViewController的執行個體能填充三個角色:view controller ,data source ,and delegate.
UITableViewController is a subclass of UIViewController, so a UITableViewController has a view. A UITableViewController's view is always an instance of UITableView, and the UITableViewController handles the preparation and presentation of the UITableView.
UITableViewController 是UIViewController的子類。所以UITableViewController有一個view,它的view是UITableView,UITableViewCOntroller負責UITableView的準備和展現
When a UITableViewController creates its view, the dataSource and delegate instance variables of the UITableView are automatically set to point at the UITableViewController
當UITableViewController建立一個view時,UITableView 的dataSource和delegate將自動的指向UITableViewController。
1.2 Subclassing UITableViewController
#import <UIKit/UIKit.h>
@interface BNRItemsViewController : UITableViewController
The designated initializer of UITableViewController is initWithStyle:, which takes a constant that determines the style of the table view.
UITableViewController指定的初始化方法是initWithStyle,將有一個常量決定table view的樣式。
There are two options: 有兩個選擇:
UITableViewStylePlain and
UITableViewStyleGrouped.
You are changing the designated initializer to init. As such, you need to follow the two rules of initializers:
你將初始化部分放在了init 方法裡。這樣你要做兩件事情。
(1)Call the superclass's designated initializer from yours
調用superclass 的指定initializer初始化你的。
(2)Override the superclass's designated initializer to call yours
重現superclass的指定的initializer來調用你自己。
- (instancetype)init
{
// Call the superclass's designated initializer
self = [super initWithStyle:UITableViewStylePlain];
return self;
}
- (instancetype)initWithStyle:(UITableViewStyle)style
{
return [self init];
}
in BNRAppDelegate ,
#import "BNRItemsViewController.h"
// Create a BNRItemsViewController BNRItemsViewController *itemsViewController =
[[BNRItemsViewController alloc] init];
// Place BNRItemsViewController's table view in the window hierarchy self.window.rootViewController = itemsViewController;
1.3 UITableView's Data Source
1.4 Creating BNRItemStore
BNRItemStore will be a singleton.
BNRItemStore將會是單例的。
This means there will only be one instance of this type in the application; if you try to create another instance, the class will quietly return the existing instance
也就是說將在應用中將只有一個執行個體。如果你想建立另外一個執行個體,這個類將返回一個已經存在的執行個體。
#import <Foundation/Foundation.h>
@interface BNRItemStore : NSObject
// Notice that this is a class method and prefixed with a + instead of a -
+ (instancetype)sharedStore;
@end
When this message is sent to the BNRItemStore class, the class will check to see if the single instance of BNRItemStore has already been created. If it has, the class will return the instance. If not, it will create the instance and return it.
當這個訊息發送給BNRItemStore,這個類將會檢查是否已經建立了一個執行個體,如果建立了,就返回這個執行個體,如果沒有,就建立並返回一個執行個體。
@implementation BNRItemStore
+ (instancetype)sharedStore
{
static BNRItemStore *sharedStore = nil;
// Do I need to create a sharedStore?
if (!sharedStore) {
sharedStore = [[self alloc] initPrivate]; }
return sharedStore; }
// If a programmer calls [[BNRItemStore alloc] init], let him know the error of his ways
- (instancetype)init
{
@throw [NSException exceptionWithName:@"Singleton" reason:@"Use +[BNRItemStore sharedStore]"
return nil; {
userInfo:nil];
// Here is the real (secret) initializer
- (instancetype)initPrivate
{
self = [super init];
return self; }
Notice that the variable sharedStore is declared as static. A static variable is not destroyed when the method is done executing. Like a global variable, it is not kept on the stack.
注意到sharedStore聲明為一個static 。當一個方法執行完成後,一個static 變數不被銷毀。像全域變數,它並不儲存在stack中。
@class BNRItem;
@property (nonatomic, readonly) NSArray *allItems;
- (BNRItem *)createItem;
See the @class directive? That tells the compiler that there is a BNRItem class and that the compiler does not need to know this class's details in the current file – only that it exists.
它告訴編譯器有一個這樣的BNRItem類,而編譯器現在不需要知道它的細節,只需要知道它存在就行了。
Using the @class directive can speed up compile times considerably because fewer files have to be recompiled when one file changes.
如果考慮到有些時候當檔案變化時,檔案需要重新編譯 ,用@class命令可能加速編譯。、
但是當我們需要知道這個類中得細節的時候,我們還是需要匯入的。
@interface BNRItemStore ()
@property (nonatomic) NSMutableArray *privateItems;
@end
- (BNRItem *)createItem
{
BNRItem *item = [BNRItem randomItem];
[self.privateItems addObject:item];
return item; }
1.5 Implementing data source methods
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [[[BNRItemStore sharedStore] allItems] count];
}
When Apple started supporting both 32-bit and 64-bit systems, they needed an integer type that was a 32-bit int in 32-bit applications and a 64-bit int in 64-bit applications.
當apple 開始支援32-bit 和64-bit系統,他們需要32和64的實數在32和64位的機器裡面。
Thus, NSInteger (which is signed) and NSUInteger (which is unsigned) were born. These types are used extensively throughout Apple's frameworks.
因此NSInteger(有符號)和NSUInteger(無符號)就出現了。
1.6 UITableViewCells
Each row of a table view is a view.
table view 的每一行都是一個view。
These views are instances of UITableViewCell.
這些view是UITableViewCell的一個執行個體。
A cell itself has one subview – its contentView
每一個cell 又有一個contentView。
The contentView is the superview for the content of the cell.
每個contentView是這個cell 內容的superview。
The real meat of a UITableViewCell is the three subviews of the contentView. Two of those subviews are UILabel instances that are properties of UITableViewCell named textLabel and detailTextLabel. The third subview is a UIImageView called imageView
實際中,UITableViewCell 是contentView的三個子類。兩個是UILabel 為textLabel 和detailTextLabel。第三個是UIImageVIew 叫做imageView。
Each cell also has a UITableViewCellStyle that determines which subviews are used and their position within the contentView.
每個cell 都有一個UITableViewCellStyle決定那個subview 需要用到和在contentView 的位置。
How do you decide which cell a BNRItem corresponds to? One of the parameters sent to tableView:cellForRowAtIndexPath: is an NSIndexPath, which has two properties: section and row. When this message is sent to a data source, the table view is asking, "Can I have a cell to display in section X, row Y?" Because there is only one section in this exercise, your implementation will only be concerned with the row.
When this message is sent to a data source, the table view is asking, "Can I have a cell to display in section X, row Y?" 當這個訊息被發送給data source,table view 正在詢問:"我能不能有一個展現在x section,y row的cell "。
1.7 Resuing UITableViewCells
When the user scrolls the table, some cells move offscreen. Offscreen cells are put into a pool of cells available for reuse.
當使用者scroll table,一些cell 移動到offscreen。Offscreen cells 放在一個能重新利用的cell pool中。
Then, instead of creating a brand new cell for every request, the data source first checks the pool.
不是先為每次請求建立一個新的cell,data source 首先檢查這個pool
If there is an unused cell, the data source configures it with new data and returns it to the table view.
如果裡面有一個未被利用的cell,那麼data source 配置給他新的資料並返回給table view。
There is one problem: sometimes a UITableView has different types of cells.
有時候 UITableView有不同類型的cell。
Occasionally, you have to subclass UITableViewCell to create a special look or behavior.
有時候你還需要繼承UITableView建立不同外觀的table view。
However, different subclasses floating around the pool of reusable cells create the possibility of getting back a cell of the wrong type.
由於不同的子類產生了
You must be sure of the type of the cell returned to you so that you can be sure of what properties and methods it has.
你必須確定返回給你的cell的類型,這樣你才能確定它有什麼屬性和方法。
you do not care about getting any specific cell out of the pool because you are going to change the cell content anyway.
你並不關心從pool中獲得特殊的cell 因為不管怎樣,你都會改變cell content。
What you need is a cell of a specific type.
你所需要的是cell 的特殊類型。
The good news is that every cell has a reuseIdentifier property of type NSString.
好訊息是每個cell 都有一個類型為NSString的reuseIdentifier屬性。
When a data source asks the table view for a reusable cell, it passes a string and says, "I need a cell with this reuse identifier."
當一個資料來源請求table view 一個reusable cell時,它傳遞了一個string並說:"我需要一個cell 有這樣的reuse identifier"
// Get a new or recycled cell UITableViewCell *cell =
[tableView dequeueReusableCellWithIdentifier:@"UITableViewCell" forIndexPath:indexPath];
you are giving that control to Apple to get the benefits of the reuse identifier.
你把控制權給Apple 來獲得reuse identifier的好處 。
For this to work, you need to tell the table view which kind of cell it should instantiate if there are no cells in the reuse pool.
為了讓這個工作,你需要告訴table view 假若在reuse pool 裡沒有可用的cell時我們選擇那樣類型的cell 來初始化。
In BNRItemsViewController.m, override viewDidLoad to register UITableViewCell class with the table view.
- (void)viewDidLoad
{
[super viewDidLoad];
[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"UITableViewCell"];
}
Reusing cells means that you only have to create a handful of cells, which puts fewer demands on memory.
重新利用cells意味著 你只需要建立一把cell,這將會要求很少的記憶體。