2015年7月29日 星期三

iOS筆記:UITableView (2)

Cell Type

enter image description here

如果TableView是屬於static cell的話, static means that these cells are set, up in the storyboard only, You can edit them however you want
including dragging butto

UITableView Protocols

UITableViewController
Automatically sets itself as its UITableView’s delegate & dataSource.!
Also has a property pointing to its UITableView:!

@property (nonatomic, strong) UITableView *tableView;
#(this property is actually == self.view in UITableViewController! 但我們不這樣用)

The delegate is used to control how the table is displayed. include what if someone touch the row, we want to react that, and how we arrange things.

The dataSource provides the data what is displayed inside the cells. 指的是TableView的內容(content), 從database出來要填入表格的數據.dataSource is a protocol to bring the model’s data into the View.

UITableViewDataSource

We have to implement these 3 to be a “dynamic” (arbitrary number of rows) table . static的tableView已經在storyboard中設置好了.

  1. How many sections in the table?
  2. How many rows in each section?
  3. Give me a UITableViewCell to use to draw each cell at a given row in a given section.
- (UITableViewCell *)tableView:(UITableView *)sender
         cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
   #get a cell to use (instance of UITableViewCell)
   UITableViewCell *cell;
cell = [self.tableView dequeueReusableCellWithIdentifier:@“Flickr Photo Cell” forIndexPath:indexPath];                                         

   #dequeueReusableCell只創建會出現在螢幕上的行數,當往下滑TableView時, 離開螢幕的行會補到下面再次填上資料出現

   #set @propertys on the cell to prepare it to display
   ...
   return cell;
}

How does a dynamic table know how many rows there are?
Number of sections is 1 by default, if you don’t implement numberOfSectionsInTableView:, it will be 1.

- (NSInteger)numberOfSectionsInTableView:(UITableView *)sender; !
- (NSInteger)tableView:(UITableView *)sender numberOfRowsInSection:(NSInteger)section; 
#This is a required method in this protocol

What about a static table?

Do not implement these dataSource methods for a static table. UITableViewController will take care of that for you.

UITableViewDelegate.

負責如何顯示表格, 而不是任何關於顯示出來的數據內容.The delegate also lets you observe what the table view is doing.The classic “will/did” sorts of things.

- (void)tableView:(UITableView *)sender didSelectRowAtIndexPath:(NSIndexPath *)path ! {!
# go do something based on information about my Model! # corresponding to indexPath.row in indexPath.section
}

UITableView Segue

The sender of prepareForSegue:sender: is the UITableViewCell! Use the important method indexPathForCell:to find out the indexPath of the row that’s segueing.!

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];
# prepare segue.destinationController to display based on information
# about my Model corresponding to indexPath.row in indexPath.section }

UITableView Spinner

當內容是透過網路加載的時候, 用spinner可以讓使用者知道正在透過其他queue下載資料.You get it via this property in UITableViewController.

@property (strong) UIRefreshControl *refreshControl;
# Start it with ...
- (void)beginRefreshing;
# Stop it with ...
- (void)endRefreshing;

enter image description here

What if your Model changes?

- (void)reloadData;
# 這會把整個資料重新更新會使程式變慢
- (void)reloadRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animationStyle;
# 只更新有變化的部分

Universal Applications

The iPad has more screen real estate, so it can present MVCs in a couple of other ways.
enter image description here

UISplitViewController

enter image description here

@property (strong) UISplitViewController *splitViewController; !

The UISplitViewController has a property which is an array containing Master and Detail:

@property (copy) NSArray *viewControllers; 
# index 0 is Master, 1 is Detail!

UISplitViewControllerDelegete

You must set this delegate very early, probably in awakeFromNib.

e.g., UISplitViewController starts sending its delegate methods way before viewDidLoad.! And then, unfortunately, when its delegate methods get sent to you, your outlets aren’t set yet!! This can make being a UISplitViewController’s delegate a real pain.!

常使用的有:
Never hide the left side (Master) behind a bar button

- (BOOL)splitViewController:(UISplitViewController *)sender shouldHideViewController:(UIViewController *)master
                 inOrientation:(UIInterfaceOrientation)orientation
{
return NO; // never hide it
}

Hide Master in portrait orientation only (the default)

- (BOOL)splitViewController:(UISplitViewController *)sender shouldHideViewController:(UIViewController *)master
                  inOrientation:(UIInterfaceOrientation)orientation
    {
        return UIInterfaceOrientationIsPortrait(orientation);
}

If you forget to set the delegate, you’ll get this …
enter image description here
This gets called in your delegate when the master gets hidden …

- (void)splitViewController:(UISplitViewController *)sender
     willHideViewController:(UIViewController *)master
          withBarButtonItem:(UIBarButtonItem *)barButtonItem
       forPopoverController:(UIPopoverController *)popover
{
barButtonItem.title = master.title;
# this next line would only work in the Detail
# and only if it was in a UINavigationController self.navigationItem.leftBarButton = barButtonItem;
}

This gets called in your delegate when the master reappears .

    - (void)splitViewController:(UISplitViewController *)sender
         willShowViewController:(UIViewController *)master
      invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem
    {
# this next line would only work in the Detail
# and only if it was in a UINavigationController self.navigationItem.leftBarButton = nil;
}

Updating the Detail when the Master is touched

  1. Target/Action!
    Example (code in the Master view controller)
  - (IBAction)doit
  {
      id detailViewController = self.splitViewController.viewControllers[1];
[detailViewController setSomeProperty:...]; 
# might want some Introspection first }
  1. Replace Segue (entirely replaces the Detail view controller)
    Segue 只會重新產生新的view, 而不會重新利用同一個view controller.

Popovers

Creating a Popover Segue in your Storyboard!

Just drag from the UI element you want to cause the popover to the scene you want to pop up. In your prepareForSegue:sender:, the argument will be isKindOf:UIStoryboardPopoverSegue.!
And UIStoryboardPopoverSegue has a @property you can use to get the UIPopoverController:
- (UIPopoverController *)popoverController;
Example:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([segue isKindOfClass:[UIStoryboardPopoverSegue class]]) {
        UIPopoverController *popoverController =
            ((UIStoryboardPopoverSegue *)segue).popoverController;
...
} }

參考:
http://lokanghung.blogspot.tw/2013/06/ios-delegate-protocol.html

沒有留言:

張貼留言