建立基于Storyboard的集合視圖應用程式
前面建立SimpleCollectionView範例程式的時候,我們取消了Use Storyboard選項,簡單示範了集合視圖的一些基本概念和用法。這裡,我們将更深入建立基于Storyboard的、有趣一點的集合視圖應用程式。下面是最終實作的PhotoCollectionView應用程式的運作效果:
使用Xcode 的Single View Application 模闆,建立一個新的項目PhotoCollectionView,類字首設定為Photo。同時,選擇Use Storyboards和Use Automatic Reference Counting複選框。
删除模闆中的視圖控制器
根據前面選擇的模闆建立的Xcode項目,Xcode自動建立了UIViewController的子類。這個示例項目中,我們需要的是UICollectionViewController子類。是以,選擇項目導航欄中的PhotoViewController.h和PhotoViewController.m檔案,删除這兩個檔案。
接着,選擇MainStoryboard.storyboard檔案,在Storyboard畫布中,選擇視圖控制器,點選鍵盤delete鍵,删除視圖控制器。
添加集合視圖控制器(Collection View Controller)到Storyboard中
從對象庫中拖拉Collection View Controller對象到Storyboard畫布中。
從上圖可以看到,随着UICollectionViewController加入到Storyboard中,同時,一個UICollectionView對象(黑色背景)和一個原型單元格(左上角的一個白色方形格子)也加入到場景中。
接下來,我們在項目中添加UICollectionViewController子類。選擇File > New > File… 菜單項,在iOS Cocoa Touch節點下,選擇Objective-C Class。
在接下來的視窗中,設定類名為PhotoCollectionViewController,Subclass of下拉菜單中選擇UICollectionViewController。
項目中将增加2個新檔案PhotoCollectionViewController.h和PhotoCollectionViewController.m檔案,是UICollectionViewController的子類。
打開Storyboard檔案,選擇Collection視圖控制器,在Identity inspector面闆視窗設定Class 屬性為剛剛建立的PhotoCollectionViewController類。
添加集合視圖單元格類(Collection View Cell Class)
再次選擇File > New > File … 菜單項,然後在iOS Cocoa Touch節點中,選擇Objective-C Class 模闆。在接下來的視窗中,輸入類名PhotoCollectionViewCell,Subclass of 下拉菜單中選擇UICollectionViewCell。點選Next 按鈕,選擇檔案在項目中存放位置,接着點選Create 按鈕,建立集合視圖單元格子類。
傳回MainStoryboard.storyboard檔案,選擇集合視圖中左上角白色方形格子,這個就是集合視圖的原型單元格(Prototype Cell)。然後,在Identity inspector面闆視窗,設定Class屬性為前面建立的PhotoCollectionViewCell。
在Attributes inspector面闆視窗,設定Identifier屬性為photoCell,後面的代碼中會用到這個重用辨別符(reuse identifier)。
設計原型單元格
前面已經完成了集合視圖和集合視圖單元格類的設計。現在我們開始設計單元格,設計單元格就是簡單地從對象庫拖拉一些UI元素到單元格設計界面上。單元格的尺寸大小可以直接進行拖拉或者在Size inspector面闆視窗設定。
下面,我們調整單元格的大小,并從對象庫拖拉Image View對象到單元格中,Image View大小占滿整個單元格,我們将在單元格中顯示圖像。
因為需要對單元格中的Image View進行指派,是以需要定義Image View的輸出口。顯示Assistant Editor編輯器,同時顯示PhotoCollectionViewCell.h代碼檔案,按住Control鍵,拖拉Image View 對象到頭檔案中,位于@interface代碼行下面。在彈出視窗中,選擇OutLet,輸入imageView作為輸出口,建立Image View對象到輸出口之間的連接配接。連接配接完成之後的PhotoCollectionView.h代碼如下所示:
#import <UIKit/UIKit.h>
@interface PhotoCollectionViewCell : UICollectionViewCell
@property (strong, nonatomic) IBOutlet UIImageView *imageView;
@end
OK,現在單元格的實作工作已經完成了。
實作資料模型(Data Model)
本示例項目的資料模型是一系列的圖像檔案,每一個圖像都将顯示在集合視圖的每一個單元格中。
第一步是向項目中加載圖像檔案。首先,我們在項目中建立一個新的檔案夾(group),命名為Images。然後從Finder中拖拉一些需要顯示的圖像到該檔案夾中。
接着,我們打開PhotoCollectionViewControlller.h 檔案,定義一個可變數組photoImages變量,用來存放圖像檔案名稱。
#import <UIKit/UIKit.h>
@interface PhotoCollectionViewController : UICollectionViewController
@property (strong, nonatomic) NSMutableArray *photoImages;
@end
最後,打開PhotoCollectionViewController.m檔案,修改viewDidLoad方法,初始化數組為圖像檔案名。
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.photoImages = [@[
@"IMG_1.JPG",
@"IMG_2.JPG",
@"IMG_3.JPG",
@"IMG_4.JPG",
@"IMG_5.JPG",
@"IMG_6.JPG",
@"IMG_7.JPG",
@"IMG_8.JPG",
@"IMG_9.JPG",
@"IMG_10.JPG",
@"90s-girl.jpg",
@"90s-girl-1.jpg",
@"90s-girl-2.jpg",
@"90s-girl-3.jpg"] mutableCopy];
}
注意上述代碼,我們使用了Modern Objective-C 文法來初始化數組,等同于下面的代碼(之前的文法)來初始化數組。上述文法預設建立的是不可變數組,是以在後面添加了mutableCopy方法的調用,傳回可變數組。
self.photoImages = [[NSMutableArray alloc] initWithObjects:
@"IMG_1.JPG",
@"IMG_2.JPG",
@"IMG_3.JPG",
@"IMG_4.JPG",
@"IMG_5.JPG",
@"IMG_6.JPG",
@"IMG_7.JPG",
@"IMG_8.JPG",
@"IMG_9.JPG",
@"IMG_10.JPG",
@"90s-girl.jpg",
@"90s-girl-1.jpg",
@"90s-girl-2.jpg",
@"90s-girl-3.jpg", nil];
實作資料源(Data Source)
我們知道集合視圖需要一個資料源(Data Source)和一個委托(Delegate)才能提供所有的功能。預設情況下,Xcode指派PhotoCollectionViewController類同時作為UICollectionView對象的委托和資料源。我們可以選擇Storyboard中的UICollectionView對象來驗證一下,右擊UICollectionView對象,顯示該對象的連接配接資訊,如下圖所示。
下一步定義PhotoCollectionViewController 類要實作的協定。另外,這個類需要和PhotoCollectionViewCell 類互動,現在也正好引入對應的頭檔案。更新之後的PhotoCollectionViewController.h檔案如下所示:
#import <UIKit/UIKit.h>
#import "PhotoCollectionViewCell.h"
@interface PhotoCollectionViewController : UICollectionViewController
@property (strong, nonatomic) NSMutableArray *photoImages;
@end
下面實作一系列遵守UICollectionVeiwDataSource協定的資料源方法。首先是讓集合視圖知道需要顯示多少個section。針對本示例程式,我們僅顯示一個section。打開PhotoCollectionViewController.m檔案,編寫numberOfSectionsInCollectionView:方法,傳回數字1。
#pragma mark -
#pragma mark UICollectionViewDataSource
-(NSInteger)numberOfSectionsInCollectionView:
(UICollectionView *)collectionView
{
return 1;
}
集合視圖調用的另外一個方法是了解每一個section中有多少個資料項顯示。在示例程式中,我們需要數組中的每一個圖像顯示在一個單元格中。
-(NSInteger)collectionView:(UICollectionView *)collectionView
numberOfItemsInSection:(NSInteger)section
{
return self.photoImages.count;
}
集合視圖調用的下一個方法是cellForItemAtIndexPath。該方法從重用隊列中擷取一個單元格對象,接着根據indexPath參數,從photoImages數組中擷取圖像,配置并傳回單元格對象。
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
PhotoCollectionViewCell *myCell = [collectionView
dequeueReusableCellWithReuseIdentifier:@"photoCell"
forIndexPath:indexPath];
UIImage *image;
int row = [indexPath row];
image = [UIImage imageNamed:self.photoImages[row]];
myCell.imageView.image = image;
return myCell;
}
測試PhtotoCollectionView應用程式
編譯運作應用程式,如一切正常,将在集合視圖中顯示圖像清單,如前面PhotoCollectionView應用程式運作效果所示,每一個單元格顯示一張固定尺寸的圖像。