1 创建集合视图,设置相关属性以满足要求
1.1 问题
集合视图控制器UIConllectionViewController是一个展示大量数据的控制器,系统默认管理着一个集合视图UICollectionView,功能几乎和UITableViewController差不多,能够以多行多列的形式展示数据。
集合视图UICollectionView继承至UIScrollView,也同tableView一样有两个协议,分别是UICollectionViewDataSource数据源协议和UICollectionViewDelegate委托协议,本案例将学习如何使用UICollectionView来展示数据,如图-1所示:
![](http://pdf7.tarena.com.cn/tts8_source/ttsPage/IOS/ISD_V01/CONTROLLERS2/DAY04/CASE/01/index.files/image001.png)
图-1
1.2 方案
首先创建一个SingleViewApplication项目,然后创建一个TRMyCollectionViewController集合视图控制器,该视图控制器继承至UICollectionViewController,然后在TRAppDelegate中创建一个带有导航的TRMyCollectionViewController集合视图控制作为根视图控制器。
其次在xib文件删除自动生成的View视图,增加一个CollectionView视图,并将File’s Owner的view属性连线到CollectionView,同时也将collectionView的dataSource和delegate进行连线。
在xib中选中collectionView在右边栏的检查器中设置collectionView的各种属性,包括单元格的宽高、分区的边距,单元格之间的间距,滚动方向等。
然后创建一个带有xib文件的TRMyCell类,该类继承至UICollectionViewCell,UICollectionViewCell是集合视图的单元格类,是集合视图的重要组成部分,与表视图的单元格不同,由于集合视图的单元格没有系统定义好的内容视图和辅助视图,所以集合视图的单元格通常都需要自定义。
最后在TRMyCollectionViewController中注册集合视图的单元格,然后实现集合视图的协议方法,给集合视图加载数据。
1.3 步骤
实现此案例需要按照如下步骤进行。
步骤一:创建TRMyCollectionViewController类
在Xcode项目中创建一个TRMyCollectionViewController集合视图控制器,该视图控制器继承至UICollectionViewController,然后在TRAppDelegate中创建一个带有导航的TRMyCollectionViewController集合视图控制作为根视图控制器,代码如下所示:
- -(BOOL)application:(UIApplication *)application
- didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
- {
- self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
- self.window.backgroundColor = [UIColor whiteColor];
- TRMyCollectionViewController *myCVC = [[TRMyCollectionViewController alloc]initWithNibName:@"TRMyCollectionViewController" bundle:nil];
- UINavigationController *navi = [[UINavigationController alloc]initWithRootViewController:myCVC];
- self.window.rootViewController = navi;
- [self.window makeKeyAndVisible];
- return YES;
- }
步骤二:在xib文件中设置集合视图
将xib文件中的view视图删除,从对象库中拖拽一个CollectionView到xib中,注意不要选成了CollectionViewController,如图-2所示:
![](http://pdf7.tarena.com.cn/tts8_source/ttsPage/IOS/ISD_V01/CONTROLLERS2/DAY04/CASE/01/index.files/image002.png)
图-2
然后将File’s Owner的view属性连线到CollectionView,同时也将collectionView的dataSource和delegate进行连线,如图-3所示:
![](http://pdf7.tarena.com.cn/tts8_source/ttsPage/IOS/ISD_V01/CONTROLLERS2/DAY04/CASE/01/index.files/image003.png)
图-3
最后在右边栏的第五个检查器中设置collectionView的相关属性,包括单元格的宽高,分区的边距以及单元格之间的间距等,如图-4所示:
![](http://pdf7.tarena.com.cn/tts8_source/ttsPage/IOS/ISD_V01/CONTROLLERS2/DAY04/CASE/01/index.files/image004.png)
图-4
由于UICollectionView是继承至UIScrollView,所以也可以滚动,默认的滚动方向是垂直的,也可以通过右边栏的第四个检查器将滚动方向设置为水平的,如图-5所示:
![](http://pdf7.tarena.com.cn/tts8_source/ttsPage/IOS/ISD_V01/CONTROLLERS2/DAY04/CASE/01/index.files/image005.png)
图-5
步骤三:创建单元格类TRMyCell,自定义集合视图单元格
创建一个带有xib文件的TRMyCell类,该类继承至UICollectionViewCell,在xib文件中拖放一个Label控件到CollectionViewCell中,并设置Label的相关属性,如图-6所示:
![](http://pdf7.tarena.com.cn/tts8_source/ttsPage/IOS/ISD_V01/CONTROLLERS2/DAY04/CASE/01/index.files/image006.png)
图-6
将Label控件关联成TRMyCell的公开属性displayLabel,代码如下所示:
- @interface TRMyCell : UICollectionViewCell
- @property (weak, nonatomic) IBOutlet UILabel *displayLabel;
- @end
然后在TRMyCollectionViewController中导入头文件“TRMyCell.h”,并且在viewDidLoad方法里面注册cell,代码如下所示:
- //定义个cell标识
- static NSString *cellIdentifier = @"MyCell";
- - (void)viewDidLoad
- {
- [super viewDidLoad];
- self.title = @"CollectionView";
- //注册cell
- [self.collectionView registerNib:[UINib nibWithNibName:@"TRMyCell" bundle:nil] forCellWithReuseIdentifier:cellIdentifier];
- }
步骤四:实现集合视图的协议方法,加载数据
首先实现集合视图的协议方法numberOfSectionsInCollectionView:告诉集合视图需要显示的分区数,代码如下所示:
- - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
- {
- return 15;
- }
然后实现协议方法告诉集合视图每个分区需要显示的单元格数,如图-6所示:
- -(NSInteger)collectionView:(UICollectionView *)collectionView
- numberOfItemsInSection:(NSInteger)section
- {
- return 10;
- }
最后实现协议方collectionView:cellForItemAtIndexPath:告诉集合视图需要显示的内容。同表视图一样在该方法里面使用dequeueReusableCellWithReuseIdentifier:forIndexPath:方法创建cell对象,并且根据indexPath参数设置每个cell的显示内容,代码如下所示:
- -(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
- cellForItemAtIndexPath:(NSIndexPath *)indexPath
- {
- TRMyCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
- cell.displayLabel.text = [NSString stringWithFormat:@"%d",indexPath.row];
- cell.backgroundColor = [UIColor colorWithRed:0 green:1 blue:0 alpha:indexPath.row * 0.1];
- return cell;
- }
1.4 完整代码
本案例中,TRAppDelegate.m文件中的完整代码如下所示:
- #import "TRAppDelegate.h"
- #import "TRCustomLayoutCollectionViewController.h"
- @implementation TRAppDelegate
- -(BOOL)application:(UIApplication *)application
- didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
- self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
- self.window.backgroundColor = [UIColor whiteColor];
- TRCustomLayoutCollectionViewController *myCVC = [[TRCustomLayoutCollectionViewController alloc]initWithNibName:@"TRCustomLayoutCollectionViewController" bundle:nil];
- UINavigationController *navi = [[UINavigationController alloc]initWithRootViewController:myCVC];
- self.window.rootViewController = navi;
- [self.window makeKeyAndVisible];
- return YES;
- }
- @end
本案例中,TRMyCollectionViewController.m文件中的完整代码如下所示:
- #import "TRMyCollectionViewController.h"
- #import "TRMyCell.h"
- @implementation TRMyCollectionViewController
- //定义个cell标识
- static NSString *cellIdentifier = @"MyCell";
- - (void)viewDidLoad
- {
- [super viewDidLoad];
- self.title = @"CollectionView";
- //注册cell
- [self.collectionView registerNib:[UINib nibWithNibName:@"TRMyCell" bundle:nil] forCellWithReuseIdentifier:cellIdentifier];
- }
- - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
- {
- return 15;
- }
- -(NSInteger)collectionView:(UICollectionView *)collectionView
- numberOfItemsInSection:(NSInteger)section
- {
- return 10;
- }
- - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
- cellForItemAtIndexPath:(NSIndexPath *)indexPath
- {
- TRMyCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
- cell.displayLabel.text = [NSString stringWithFormat:@"%d",indexPath.row];
- cell.backgroundColor = [UIColor colorWithRed:0 green:1 blue:0 alpha:indexPath.row * 0.1];
- return cell;
- }
- @end
本案例中,TRMyCell.h文件中的完整代码如下所示:
2 使用布局创建集合视图
2.1 问题
CollectionView的布局是其精髓,相当于CollectionView的大脑和中枢,负责设置CollectionView的一些属性,包括位置、尺寸、透明度、层级关系、形状等,本案例将使用集合视图的布局用代码创建一个集合视图,如图-7所示:
![](http://pdf7.tarena.com.cn/tts8_source/ttsPage/IOS/ISD_V01/CONTROLLERS2/DAY04/CASE/01/index.files/image007.png)
图-7
2.2 方案
UICollectionViewFlowLayout布局类是UICollectionViewLayout类的子类,称为流式布局类,所有的单元格都依次挨着摆放。
首先创建一个SingleViewApplication项目,然后创建一个带有导航的TRCustomLayoutCollectionViewController视图控制器作为根视图控制器,该视图继承至UIViewController。
其次在viewDidLoad方法里面创建一个UICollectionViewFlowLayout布局对象,设置布局对象的各种属性。
然后在viewDidLoad方法里面创建集合视图对象collectionView,使用初始化方法initWithFrame:collectionViewLayout:进行初始化,collectionViewLayout:所传递的参数就是上一步所创建的布局对象。
最后注册集合视图的cell,TRCustomLayoutCollectionViewController遵守集合视图协议,并且实现协议方法给集合视图加载数据。
2.3 步骤
实现此案例需要按照如下步骤进行。
步骤一:创建集合视图项目
在Xcode项目中创建一个TRCustomLayoutCollectionViewController视图控制器类,继承至UIViewController。然后在TRAppDelegate中创建一个带有导航的TRCustomLayoutCollectionViewController视图控制器作为根视图控制器,代码如下所示:
- -(BOOL)application:(UIApplication *)application
- didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
- {
- self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
- self.window.backgroundColor = [UIColor whiteColor];
- TRCustomLayoutCollectionViewController *myCVC = [[TRCustomLayoutCollectionViewController alloc]initWithNibName:@"TRCustomLayoutCollectionViewController" bundle:nil];
- UINavigationController *navi = [[UINavigationController alloc]initWithRootViewController:myCVC];
- self.window.rootViewController = navi;
- [self.window makeKeyAndVisible];
- return YES;
- }
步骤二:创建UICollectionViewFlowLayout布局对象
首先在viewDidLoad方法里面创建集合视图对象collectionView,使用初始化方法initWithFrame:collectionViewLayout:进行初始化,frame:所传递的参数就是屏幕的大小,collectionViewLayout:所传递的参数就是上一步所创建的布局对象,代码如下所示:
- //创建集合视图的布局对象
- UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc]init];
- //设置每个cell的大小
- layout.itemSize = CGSizeMake(150, 150);
- //设置每个cell之间的间距
- layout.minimumInteritemSpacing = 10;
- //设置每个分局的边距
- layout.sectionInset = UIEdgeInsetsMake(150, 20, 150, 20);
- //设置滚动方向为水平方向
- layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
步骤三:创建集合视图对象collectionView
在xib界面上拖拽一个UISlider控件,在右边栏的第四个检查器中将miniMum、maxiMum和current分别设置为0、1和0,然后将slider关联成TRViewController的方法sliderValueChange:,该方法主要实现功能是拖动滑块能控制tableView1在界面中的显示第几行单元格,在方法里面根据slider的value值计算出tableView的contentOffset即可,代码如下所示:
- //创建集合视图对象
- CGSize screenSize = [[UIScreen mainScreen] bounds].size;
- UICollectionView *collectionView = [[UICollectionView alloc]initWithFrame:CGRectMake(0, 0, screenSize.width, screenSize.height) collectionViewLayout:layout];
然后设置collectionView的数据源对象和委托对象,并添加到父视图中,代码如下所示:
- //设置collectionView的委托对象
- collectionView.dataSource = self;
- collectionView.delegate = self;
- //将集合视图添加到父视图中
- [self.view addSubview:collectionView];
步骤四:遵守委托协议,实现协议方法
首先在viewDidLoad方法里面注册集合视图的单元格,本案例没有使用自定义的cell,而是直接使用系统提供的UICollectionViewCell,所以使用方法registerClass:forCellWithReuseIdentifier:进行注册,registerClass:参数传递的是UICollectionViewCell类,代码如下所示:
- //在viewDidLoad方法外面定义cell的注册标识
- static NSString *cellIdentifier = @"MyCell";
- //在viewDidLoad方法里面进行cell的注册
- [collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:cellIdentifier];
然后TRCustomLayoutCollectionViewController遵守集合视图协议,并且实现协议方法给集合视图加载数据,代码如下所示:
- //遵守集合视图的数据源协议和委托协议
- @interface TRCustomLayoutCollectionViewController () <UICollectionViewDataSource, UICollectionViewDelegate>
- @end
- - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
- {
- return 10;
- }
- -(NSInteger)collectionView:(UICollectionView *)collectionView
- numberOfItemsInSection:(NSInteger)section
- {
- return 6;
- }
- -(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
- cellForItemAtIndexPath:(NSIndexPath *)indexPath
- {
- UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
- cell.backgroundColor = [UIColor grayColor];
- return cell;
- }
2.4 完整代码
本案例中,TRAppDelegate.m文件中的完整代码如下所示:
- #import "TRAppDelegate.h"
- #import "TRViewController.h"
- @implementation TRAppDelegate
- -(BOOL)application:(UIApplication *)application
- didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
- {
- self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
- self.window.backgroundColor = [UIColor whiteColor];
- TRViewController *vc = [[TRViewController alloc]initWithNibName:@"TRViewController" bundle:nil];
- UINavigationController *navi = [[UINavigationController alloc]initWithRootViewController:vc];
- self.window.rootViewController = navi;
- [self.window makeKeyAndVisible];
- return YES;
- }
- @end
本案例中,TRCustomLayoutCollectionViewController.m文件中的完整代码如下所示:
- #import "TRCustomLayoutCollectionViewController.h"
- //遵守集合视图的数据源协议和委托协议
- @interface TRCustomLayoutCollectionViewController () <UICollectionViewDataSource, UICollectionViewDelegate>
- @end
- @implementation TRCustomLayoutCollectionViewController
- //在viewDidLoad方法外面定义cell的注册标识
- static NSString *cellIdentifier = @"MyCell";
- - (void)viewDidLoad
- {
- [super viewDidLoad];
- UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc]init];
- //设置每个cell的大小
- layout.itemSize = CGSizeMake(150, 150);
- //设置每个cell之间的间距
- layout.minimumInteritemSpacing = 10;
- //设置每个分局的边距
- layout.sectionInset = UIEdgeInsetsMake(150, 20, 150, 20);
- //设置滚动方向为水平方向
- layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
- //创建集合视图对象
- CGSize screenSize = [[UIScreen mainScreen] bounds].size;
- UICollectionView *collectionView = [[UICollectionView alloc]initWithFrame:CGRectMake(0, 0, screenSize.width, screenSize.height) collectionViewLayout:layout];
- //设置collectionView的委托对象
- collectionView.dataSource = self;
- collectionView.delegate = self;
- //将集合视图添加到父视图中
- [self.view addSubview:collectionView];
- //由于直接使用的系统的UICollectionViewCell,注册cell使用registerClass:方法
- [collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:cellIdentifier];
- }
- - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
- {
- return 10;
- }
- -(NSInteger)collectionView:(UICollectionView *)collectionView
- numberOfItemsInSection:(NSInteger)section
- {
- return 6;
- }
- -(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
- cellForItemAtIndexPath:(NSIndexPath *)indexPath
- {
- UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:cellIdentifier forIndexPath:indexPath];
- cell.backgroundColor = [UIColor grayColor];
- return cell;
- }
- @end
3 使用TabBar管理多个VC及Navi
3.1 问题
UITabbarController同导航控制器一样是一个控制器的控制器,标签栏位于屏幕下方,占有49个像素,本案例将学习如何使用标签控制器来管理视图控制器,如图-8所示:
![](http://pdf7.tarena.com.cn/tts8_source/ttsPage/IOS/ISD_V01/CONTROLLERS2/DAY04/CASE/01/index.files/image008.png)
图-8
3.2 方案
首先同样创建一个SingleViewApplication项目,然后创建三个带有xib的视图控制器类TRFirstViewController、TRSecondViewController,TRThirdViewController,作为标签控制器所管理的子控制器。
然后在TRAppDelegate的程序入口方法中分别创建三个带有导航子视图控制器对象,再创建一个UITabbarController对象tabbar,将三个视图控制器对象设置为tabbar的子视图控制器,屏幕下方的标签栏就回有三个按钮对应三个子视图控制。
通常为了点击方便一般管理的子视图控制器不超过五个,如果超过五个则最后一个标签栏按钮显示为更多,点击更多标签按钮会出现一个更多列表。
最后将tabbar设置为根视图控制器,分别在三个子视图控制器类中设置title和tabBarItem的显示内容。
3.3 步骤
实现此案例需要按照如下步骤进行。
步骤一:创建TRTableViewController视图控制器
首先在Xcode项中创建三个带有xib的视图控制器类TRFirstViewController、TRSecondViewController,TRThirdViewController,全都继承至UIViewController,并在xib中给三个控制器的视图设置不同的背景颜色。
这三个视图控制器将作为标签控制器所管理的子控制器,如图-9所示:
![](http://pdf7.tarena.com.cn/tts8_source/ttsPage/IOS/ISD_V01/CONTROLLERS2/DAY04/CASE/01/index.files/image009.png)
图-9
步骤二:创建UITabbarController对象
在TRAppDelegate的程序入口方法中分别创建三个带有导航子视图控制器对象,代码如下所示:
- TRFirstViewController *firstVC = [[TRFirstViewController alloc]initWithNibName:@"TRFirstViewController" bundle:nil];
- UINavigationController *navi1 = [[UINavigationController alloc]initWithRootViewController:firstVC];
- TRSecondViewController *secondVC = [[TRSecondViewController alloc]initWithNibName:@"TRSecondViewController" bundle:nil];
- UINavigationController *navi2 = [[UINavigationController alloc]initWithRootViewController:secondVC];
- TRThirdViewController *thirdVC = [[TRThirdViewController alloc]initWithNibName:@"TRThirdViewController" bundle:nil];
- UINavigationController *navi3 = [[UINavigationController alloc]initWithRootViewController:thirdVC];
然后再创建一个UITabbarController对象tabbar,将三个视图控制器对象设置为tabbar的子视图控制器,屏幕下方的标签栏就回有三个按钮对应三个子视图控制,代码如下所示:
- //创建UITabBarController对象
- UITabBarController *tabbar = [[UITabBarController alloc]init];
- //设置tabbar的子控制器
- tabbar.viewControllers = @[navi1, navi2, navi3];
最后将tabbar设置为根视图控制器,运行程序显示的第一个界面为标签控制器所管理的第一个子控制器的视图,代码如下所示:
- self.window.rootViewController = tabbar;
步骤三:设置title和tabBarItem
分别在三个子视图控制器类中的initWithNibName:bundle:初始化方法中设置title和tabBarItem的显示内容,代码如下所示:
- //TRFirstViewController类中
- - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
- {
- self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
- if (self) {
- self.title = @"FirstVC";
- self.tabBarItem.image = [UIImage imageNamed:@"tabbar_item_selected.png"];
- }
- return self;
- }
- //TRSecondViewController类中
- - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
- {
- self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
- if (self) {
- self.title = @"@"SecondVC"";
- self.tabBarItem.image = [UIImage imageNamed:@"tabbar_item_music.png"];
- }
- return self;
- }
- //TRThirdViewController类中
- - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
- {
- self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
- if (self) {
- self.title = @"ThirdVC"";
- self.tabBarItem.image = [UIImage imageNamed:@"tabbar_item_store.png"];
- }
- return self;
- }
运行程序可见标签按钮都添加了标题和图片,如图-10所示:
![](http://pdf7.tarena.com.cn/tts8_source/ttsPage/IOS/ISD_V01/CONTROLLERS2/DAY04/CASE/01/index.files/image010.png)
图-10
3.4 完整代码
本案例中,TRAppDelegate.m文件中的完整代码如下所示:
- #import "TRAppDelegate.h"
- #import "TRFirstViewController.h"
- #import "TRSecondViewController.h"
- #import "TRThirdViewController.h"
- @implementation TRAppDelegate
- -(BOOL)application:(UIApplication *)application
- didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
- {
- self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
- self.window.backgroundColor = [UIColor whiteColor];
- //创建tabbar所管理的子控制器,每个子控制器都带有一个导航
- TRFirstViewController *firstVC = [[TRFirstViewController alloc]initWithNibName:@"TRFirstViewController" bundle:nil];
- UINavigationController *navi1 = [[UINavigationController alloc]initWithRootViewController:firstVC];
- TRSecondViewController *secondVC = [[TRSecondViewController alloc]initWithNibName:@"TRSecondViewController" bundle:nil];
- UINavigationController *navi2 = [[UINavigationController alloc]initWithRootViewController:secondVC];
- TRThirdViewController *thirdVC = [[TRThirdViewController alloc]initWithNibName:@"TRThirdViewController" bundle:nil];
- UINavigationController *navi3 = [[UINavigationController alloc]initWithRootViewController:thirdVC];
- //创建UITabBarController对象
- UITabBarController *tabbar = [[UITabBarController alloc]init];
- //设置tabbar的子控制器
- tabbar.viewControllers = @[navi1, navi2, navi3];
- //将标签控制器设置为根视图控制器,程序的第一个界面默认为标签控制器所管理的第一个子控制器的视图
- self.window.rootViewController = tabbar;
- [self.window makeKeyAndVisible];
- return YES;
- }
- @end
本案例中,TRFirstViewController.m文件中的完整代码如下所示:
- #import "TRFirstViewController.h"
- @implementation TRFirstViewController
- - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
- {
- self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
- if (self) {
- self.title = @"FirstVC";
- self.tabBarItem.image = [UIImage imageNamed:@"tabbar_item_selected.png"];
- }
- return self;
- }
- @end
本案例中,TRSecondViewController.m文件中的完整代码如下所示:
- #import "TRSecondViewController.h"
- @implementation TRFirstViewController
- - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
- {
- self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
- if (self) {
- self.title = @"SecondVC";
- self.tabBarItem.image = [UIImage imageNamed:@"tabbar_item_music.png"];
- }
- return self;
- }
- @end
本案例中,TRThirdViewController.m文件中的完整代码如下所示:
- #import "TRFirstViewController.h"
- @implementation TRFirstViewController
- - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
- {
- self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
- if (self) {
- self.title = @"ThirdVC";
- self.tabBarItem.image = [UIImage imageNamed:@"tabbar_item_store.png"];
- }
- return self;
- }
- @end
4 分段选择展示
4.1 问题
IOS提供了分段选择控件,分段控件由两段或更多段构成,每一段都相当于一个独立的按钮。分段控件通常只能激活其中一个按钮。本案例将学习如何使用分段选择控件,根据不同的选择改变label的显示内容,如图-11所示:
![](http://pdf7.tarena.com.cn/tts8_source/ttsPage/IOS/ISD_V01/CONTROLLERS2/DAY04/CASE/01/index.files/image011.png)
图-11
4.2 方案
首先同样创建一个SingleViewApplication项目,然后创建一个带有xib的视图控制器类TRViewController,作为本案例的根视图控制器。
其次在xib文件中拖放一个SegmentedControl控件和一个标签控件。
然后在右边栏的第四个检查器中设置SegmentedControl控件的各属性,包括样式、每个分段按钮的显示标题、背景样色以及渲染颜色。
最后将xib中的label关联成属性,将SegmentedControl关联成方法,在TRViewController.m文件中实现SegmentedControl的事件响应方法。
4.3 步骤
实现此案例需要按照如下步骤进行。
步骤一:创建TRViewController视图控制器
首先在Xcode项中创建一个带有xib的视图控制器类TRViewController,继承至UIViewController,并在TRAppDelegate的程序入口方法中创建根视图控制器对象,代码如下所示:
- -(BOOL)application:(UIApplication *)application
- didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
- self.window = [[UIWindow alloc]initWithFrame:[[UIScreen mainScreen]bounds]];
- TRViewController *vc = [[TRViewController alloc]initWithNibName:@"TRViewController" bundle:nil];
- self.window.rootViewController = vc;
- [self.window makeKeyAndVisible];
- return YES;
- }
步骤二:在xib文件中拖放控件
在xib文件中拖放一个SegmentedControl控件和一个标签控件,如图-12所示:
![](http://pdf7.tarena.com.cn/tts8_source/ttsPage/IOS/ISD_V01/CONTROLLERS2/DAY04/CASE/01/index.files/image012.png)
图-12
然后在右边栏的第四个检查器中设置日期检查器的相关属性,将分段数设置为3个,并以此设置每个分段的标题,如图-13所示:
![](http://pdf7.tarena.com.cn/tts8_source/ttsPage/IOS/ISD_V01/CONTROLLERS2/DAY04/CASE/01/index.files/image013.png)
图-13
步骤三:关联代码,实现方法
首先将xib中的label关联成私用属性label,代码如下所示:
- @interface TRDatePickerViewController ()
- @property (weak, nonatomic) IBOutlet UILabel *label;
- @end
然后将SegmentedControl关联成事件方法segmentedControlAction:,此时SegmentedControl的事件应选择valueChanged,segmentedControlAction:方法的功能是根据不同的选择修改label的显示内容,代码如下所示:
- -(IBAction)segmentedControlAction:(UISegmentedControl *)sender {
- NSInteger *index = [sender selectedSegmentIndex];
- NSString *title = [sender titleForSegmentAtIndex:index];
- self.label.text = [NSString stringWithFormat:@"用户选中%@",title];
- }
4.4 完整代码
本案例中,TRAppDelegate.m文件中的完整代码如下所示:
- #import "TRAppDelegate.h"
- #import "TRViewController.h"
- @implementation TRAppDelegate
- -(BOOL)application:(UIApplication *)application
- didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
- self.window = [[UIWindow alloc]initWithFrame:[UIScreen mainScreen].bounds];
- TRViewController *vc = [[TRViewController alloc]initWithNibName:@"TRViewController" bundle:nil];
- self.window.rootViewController = vc;
- [self.window makeKeyAndVisible];
- return YES;
- }
- @end
本案例中,TRViewController.m文件中的完整代码如下所示:
- #import "TRViewController.h"
- @interface TRViewController ()
- @property (weak, nonatomic) IBOutlet UILabel *label;
- @end
- @implementation TRViewController
- - (IBAction)segmentedControlAction:(UISegmentedControl *)sender {
- NSInteger *index = [sender selectedSegmentIndex];
- NSString *title = [sender titleForSegmentAtIndex:index];
- self.label.text = [NSString stringWithFormat:@"用户选中%@",title];
- }
- @end
5 下载进度指示
5.1 问题
活动指示器UIActivityIndicatorView是UIKit框架提供的一个用于提示用户等待的指示图,是一个标准的旋转进度轮。本案例使用活动指示器和进度条模拟实现下载进度指示,如图-14所示:
![](http://pdf7.tarena.com.cn/tts8_source/ttsPage/IOS/ISD_V01/CONTROLLERS2/DAY04/CASE/01/index.files/image014.png)
图-14
5.2 方案
首先同样创建一个SingleViewApplication项目,然后创建一个带有xib的视图控制器类TRViewController,作为本案例的根视图控制器。
其次在xib文件中拖放一个ActivityIndicatorView控件和一个ProgressView控件。
然后在右边栏的第四个检查器中设置ActivityIndicatorView和ProgressView各属性。
最后将xib中的ActivityIndicatorView和ProgressView关联成私用属性,在viewDidLoad方法里面创建一个计时器,模拟下载进度。
5.3 步骤
实现此案例需要按照如下步骤进行。
步骤一:创建TRViewController视图控制器
首先在Xcode项中创建一个带有xib的视图控制器类TRViewController,继承至UIViewController,并在TRAppDelegate的程序入口方法中创建根视图控制器对象,代码如下所示:
- -(BOOL)application:(UIApplication *)application
- didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
- self.window = [[UIWindow alloc]initWithFrame:[[UIScreen mainScreen]bounds]];
- TRViewController *vc = [[TRViewController alloc]initWithNibName:@"TRViewController" bundle:nil];
- self.window.rootViewController = vc;
- [self.window makeKeyAndVisible];
- return YES;
- }
步骤二:在xib文件中拖放控件
在xib文件中拖放一个ActivityIndicatorView控件和一个ProgressView控件,如图-15所示:
![](http://pdf7.tarena.com.cn/tts8_source/ttsPage/IOS/ISD_V01/CONTROLLERS2/DAY04/CASE/01/index.files/image015.png)
图-15
然后在右边栏的第四个检查器中设置ActivityIndicatorView控件的相关属性,将Hides When Stopped选项勾上,表示当ActivityIndicatorView停止旋转时隐藏,如图-16所示:
![](http://pdf7.tarena.com.cn/tts8_source/ttsPage/IOS/ISD_V01/CONTROLLERS2/DAY04/CASE/01/index.files/image016.png)
图-16
最后在右边栏的第四个检查器中设置ProgressView控件的相关属性,将Progress的值设置为0,progress是UIProgressView的一个重要属性,是float类型,默认的取值范围为0~1,如图-17所示:
![](http://pdf7.tarena.com.cn/tts8_source/ttsPage/IOS/ISD_V01/CONTROLLERS2/DAY04/CASE/01/index.files/image017.png)
图-17
步骤三:关联代码,实现方法
首先将xib中的ActivityIndicatorView和ProgressView关联成私用属性activityIndicatorView和progressView,代码如下所示:
- @interface TRDatePickerViewController ()
- @property (weak, nonatomic) IBOutletUIActivityIndicatorView *activityIndicatorView;
- @property (weak, nonatomic) IBOutlet UIProgressView *progressView;
- @end
然后在viewDidLoad方法里面创建一个NSTimer类型的计时器对象,计时器可以设定固定的时间间隔反复调用某个方法,本案例使用计时器模拟实现一个下载进度状态,每隔一定的时间修改progressView的progress值,当progress的值为1时,activityIndicatorView停止旋转并隐藏,代码如下所示:
- - (void)viewDidLoad {
- [super viewDidLoad];
- //timeInterval参数是时间间隔,以秒为单位,target:参数是目标,selector参数是调用的方法,repeats参数表示是否重复调用该方法
- [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(download:) userInfo:nil repeats:YES];
- }
最后实现download:方法,该方法实现功能修改progressView的progress值,当progress的值为1时,activityIndicatorView停止旋转并隐藏,该方法传递过来的参数就是计时器对象,代码如下所示:
- //download方法的参数就是计时器对象
- -(void)download:(NSTimer*)timer {
- //活动指示器开始旋转
- [self.activityIndicatorView startAnimating];
- //每次调用进度条的progress都加0.1
- self.progressView.progress+=0.1;
- if (self.progressView.progress ==1) {
- //当进度条的progress==1时,表示下载完成,活动指示器停止旋转
- [self.activityIndicatorView stopAnimating];
- //弹出提示对话框
- UIAlertView *av = [[UIAlertView alloc]initWithTitle:@"提示" message:@"下载完成" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
- [av show];
- //计时器停止
- [timer invalidate];
- }
- }
5.4 完整代码
本案例中,TRAppDelegate.m文件中的完整代码如下所示:
- #import "TRAppDelegate.h"
- #import "TRViewController.h"
- @implementation TRAppDelegate
- -(BOOL)application:(UIApplication *)application
- didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
- self.window = [[UIWindow alloc]initWithFrame:[UIScreen mainScreen].bounds];
- TRViewController *vc = [[TRViewController alloc]initWithNibName:@"TRViewController" bundle:nil];
- self.window.rootViewController = vc;
- [self.window makeKeyAndVisible];
- return YES;
- }
- @end
本案例中,TRViewController.m文件中的完整代码如下所示:
- #import "TRViewController.h"
- @interface TRViewController ()
- @property (weak, nonatomic) IBOutlet
- UIActivityIndicatorView *activityIndicatorView;
- @property (weak, nonatomic) IBOutlet UIProgressView *progressView;
- @end
- @implementation TRViewController
- - (void)viewDidLoad {
- [super viewDidLoad];
- [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(download:) userInfo:nil repeats:YES];
- }
- //download方法的参数就是计时器对象
- -(void)download:(NSTimer*)timer {
- //活动指示器开始旋转
- [self.activityIndicatorView startAnimating];
- //每次调用进度条的progress都加0.1
- self.progressView.progress+=0.1;
- if (self.progressView.progress ==1) {
- //当进度条的progress==1时,表示下载完成,活动指示器停止旋转
- [self.activityIndicatorView stopAnimating];
- //弹出提示对话框
- UIAlertView *av = [[UIAlertView alloc]initWithTitle:@"提示" message:@"下载完成" delegate:nil cancelButtonTitle:@"确定" otherButtonTitles:nil, nil];
- [av show];
- //计时器停止
- [timer invalidate];
- }
- }
- @end
6 使用DatePicker控件选择日期
6.1 问题
IOS提供了日期选择器控件,可以提供对日期的选择,本案例将学习如何使用日期选择器来选择时间,如图-18所示:
![](http://pdf7.tarena.com.cn/tts8_source/ttsPage/IOS/ISD_V01/CONTROLLERS2/DAY04/CASE/01/index.files/image018.png)
图-18
6.2 方案
首先同样创建一个SingleViewApplication项目,然后创建一个带有xib的视图控制器类TRDatePickerViewController,作为本案例的根视图控制器。
其次在xib文件中拖放一个DatePicker控件、一个标签控件以及一个按钮控件。日期选择器提供四种模式:日期、日期和时间、时间以及倒计时,本案例使用日期和时间模式。
然后在右边栏的第四个检查器中设置日期选择器的各属性,包括Mode模式、Local设定本地化、Interval设定时间间隔、Date开始时间、Constraints显示的最大和最小日期。
最后将xib中的日期选择器和label关联成属性,将日期选择器和按钮关联成方法,在TRDatePickerViewController.m文件中实现日期选择器和按钮的事件响应方法。
6.3 步骤
实现此案例需要按照如下步骤进行。
步骤一:创建TRDatePickerViewController视图控制器
首先在Xcode项中创建一个带有xib的视图控制器类TRDatePickerViewController,继承至UIViewController,并在TRAppDelegate的程序入口方法中创建根视图控制器对象,代码如下所示:
- -(BOOL)application:(UIApplication *)application
- didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
- self.window = [[UIWindow alloc]initWithFrame:[[UIScreen mainScreen]bounds]];
- TRDatePickerViewController *dpVC = [[TRDatePickerViewController alloc]initWithNibName:@"TRDatePickerViewController" bundle:nil];
- UINavigationController *navi = [[UINavigationController alloc]initWithRootViewController:dpVC];
- self.window.rootViewController = navi;
- [self.window makeKeyAndVisible];
- return YES;
- }
步骤二:在xib文件中拖放控件
在xib文件中拖放一个DatePicker控件、一个标签控件以及一个按钮控件,如图-19所示:
![](http://pdf7.tarena.com.cn/tts8_source/ttsPage/IOS/ISD_V01/CONTROLLERS2/DAY04/CASE/01/index.files/image019.png)
图-19
然后在右边栏的第四个检查器中设置日期检查器的相关属性,将模式选择为Date and Time,如图-20所示:
![](http://pdf7.tarena.com.cn/tts8_source/ttsPage/IOS/ISD_V01/CONTROLLERS2/DAY04/CASE/01/index.files/image020.png)
图-20
步骤三:关联代码,实现方法
首先将xib中的日期选择器和label关联成私用属性datePicker和dateLabel,代码如下所示:
- @interface TRDatePickerViewController ()
- @property (weak, nonatomic) IBOutlet UIDatePicker *datePicker;
- @property (weak, nonatomic) IBOutlet UILabel *dateLabel;
- @end
然后将日期选择器关联成事件方法datePickerValueChanged:,此时日期选择器的的事件应选择valueChanged,datePickerValueChanged:方法的功能是将日期选择器所表示的时间显示到dateLabel上,代码如下所示:
- - (IBAction)datePickerValueChanged:(UIDatePicker *)sender
- {
- NSDateFormatter *df = [[NSDateFormatter alloc]init];
- [df setDateFormat:@"YYYY-MM-dd HH:mm:ss"];
- self.dateLabel.text = [df stringFromDate:sender.date];
- }
最后将按钮关联成事件方法launch:,该方法的功能是让日期选择器获取当前日期,代码如下所示:
- - (IBAction)launch:(id)sender
- {
- NSDate *date = self.datePicker.date;
- NSDateFormatter *df = [[NSDateFormatter alloc]init];
- [df setDateFormat:@"YYYY-MM-dd HH:mm:ss"];
- self.dateLabel.text = [df stringFromDate:self.datePicker.date];
- date = [NSDate date];
- [self.datePicker setDate:date animated:YES]
- }
6.4 完整代码
本案例中,TRAppDelegate.m文件中的完整代码如下所示:
- #import "TRAppDelegate.h"
- #import "TRDatePickerViewController.h"
- @implementation TRAppDelegate
- -(BOOL)application:(UIApplication *)application
- didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
- self.window = [[UIWindow alloc]initWithFrame:[[UIScreen mainScreen]bounds]];
- TRDatePickerViewController *dpVC = [[TRDatePickerViewController alloc]initWithNibName:@"TRDatePickerViewController" bundle:nil];
- UINavigationController *navi = [[UINavigationController alloc]initWithRootViewController:dpVC];
- self.window.rootViewController = navi;
- [self.window makeKeyAndVisible];
- return YES;
- }
- @end
本案例中,TRDatePickerViewController.m文件中的完整代码如下所示:
- #import "TRDatePickerViewController.h"
- @interface TRDatePickerViewController ()
- @property (weak, nonatomic) IBOutlet UIDatePicker *datePicker;
- @property (weak, nonatomic) IBOutlet UILabel *dateLabel;
- @end
- @implementation TRDatePickerViewController
- - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
- {
- self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
- if (self) {
- self.title = @"Date";
- }
- return self;
- }
- - (IBAction)launch:(id)sender
- {
- NSDate *date = self.datePicker.date;
- NSDateFormatter *df = [[NSDateFormatter alloc]init];
- [df setDateFormat:@"YYYY-MM-dd HH:mm:ss"];
- self.dateLabel.text = [df stringFromDate:self.datePicker.date];
- date = [NSDate date];
- [self.datePicker setDate:date animated:YES];
- }
- - (IBAction)datePickerValueChanged:(UIDatePicker *)sender
- {
- NSDateFormatter *df = [[NSDateFormatter alloc]init];
- [df setDateFormat:@"YYYY-MM-dd HH:mm:ss"];
- self.dateLabel.text = [df stringFromDate:sender.date];
- }
- @end
7 使用PickerView控件实现火车起始地点选择
7.1 问题
有时候我们还需要选择日期以外的内容,IOS提供了普通的视图选择器控件,可以满足用户的需要,本案例将学习如何使用PickerView控件实现火车起始地点选择,如图-21所示:
![](http://pdf7.tarena.com.cn/tts8_source/ttsPage/IOS/ISD_V01/CONTROLLERS2/DAY04/CASE/01/index.files/image021.png)
图-21
7.2 方案
首先同样创建一个SingleViewApplication项目,然后创建一个带有xib的视图控制器类TRPickerViewViewController,作为本案例的根视图控制器。
其次在xib文件中拖放一个PickerView控件、一个标签控件以及一个按钮控件,并在右边栏的第四个检查器中设置各个控件的相关属性。
然后将xib中的PickerView控件和label关联成属性,将按钮关联成方法。并以拉线的形式设置PickerView的委托对象为TRPickerViewViewController,TRPickerViewViewController类需要遵守协议UIPickerViewDataSource和 UIPickerViewDelegate。
最后在TRPickerViewViewController类中定义两个NSArray的属性formCity和toCity,用来存放PickerView显示的数据。
在TRPickerViewViewController类中实现按钮的事件响应方法和PickerView的协议方法,完成数据加载。
7.3 步骤
实现此案例需要按照如下步骤进行。
步骤一:创建TRPickerViewViewController视图控制器
首先在Xcode项中创建一个带有xib的视图控制器类TRPickerViewViewController,继承至UIViewController,并在TRAppDelegate的程序入口方法中创建根视图控制器对象,代码如下所示:
- -(BOOL)application:(UIApplication *)application
- didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
- self.window = [[UIWindow alloc]initWithFrame:[[UIScreen mainScreen]bounds]];
- TRPickerViewViewController *pvVC = [[TRPickerViewViewController alloc]initWithNibName:@"TRPickerViewViewController" bundle:nil];
- UINavigationController *navi = [[UINavigationController alloc]initWithRootViewController:pvVC]; self.window.rootViewController = navi;
- [self.window makeKeyAndVisible];
- return YES;
- }
步骤二:在xib文件中拖放控件
在xib文件中拖放一个PickerView控件、一个标签控件以及一个按钮控件,并在右边栏的第四个检查器中设置各个控件的相关属性,如图-22所示:
![](http://pdf7.tarena.com.cn/tts8_source/ttsPage/IOS/ISD_V01/CONTROLLERS2/DAY04/CASE/01/index.files/image022.png)
图-22
然后将xib中的PickerView控件和label关联成私有属性pickerView和label,将按钮关联成方法luanch:,代码如下所示:
- @interface TRPickerViewViewController ()
- @property (weak, nonatomic) IBOutlet UIPickerView *pickerView;
- @property (weak, nonatomic) IBOutlet UILabel *label;
- @end
最后以拉线的形式设置PickerView的dataSource和delegate两个委托对象为File‘s Owner,即TRPickerViewViewController,如图-23所示:
![](http://pdf7.tarena.com.cn/tts8_source/ttsPage/IOS/ISD_V01/CONTROLLERS2/DAY04/CASE/01/index.files/image023.png)
图-23
步骤三:遵守协议,实现方法
在TRPickerViewViewController类中定义两个NSArray类型的公开属性formCity和toCity,用来存放PickerView显示的数据,并重写setter方法初始化数据,代码如下所示:
- @interface TRPickerViewViewController : UIViewController
- @property (nonatomic, strong)NSArray *fromCitys;
- @property (nonatomic, strong)NSArray *toCitys;
- @end
- //重写setter方法,初始化数据
- - (NSArray *)fromCitys
- {
- if(!_fromCitys)_fromCitys = @[@"北京",@"上海",@"广州",@"深圳",@"成都"];
- return _fromCitys;
- }
- - (NSArray *)toCitys
- {
- if(!_toCitys)_toCitys = @[@"上海",@"广州",@"深圳",@"成都", @"杭州"];
- return _toCitys;
- }
然后TRPickerViewViewController类需要遵守协议UIPickerViewDataSource和 UIPickerViewDelegate,并且实现相关的协议方法,完成数据加载,代码如下所示:
- //遵守协议
- @interface TRPickerViewViewController () <UIPickerViewDataSource, UIPickerViewDelegate>
- //告诉pickerView显示多少组
- - (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
- {
- return 2;
- }
- //告诉pickerView每组显示多少行
- -(NSInteger)pickerView:(UIPickerView *)pickerView
- numberOfRowsInComponent:(NSInteger)component
- {
- if (component==0) {
- return self.fromCitys.count;
- }else if(component==1){
- return self.toCitys.count;
- }
- return 0;
- }
- //告诉pickerView每行显示的标题
- -(NSString *)pickerView:(UIPickerView *)pickerView
- titleForRow:(NSInteger)row
- forComponent:(NSInteger)component
- {
- if(component==0){
- return self.fromCitys[row];
- }else{
- return self.toCitys[row];
- }
- }
最后在TRPickerViewViewController类中实现按钮的事件响应方法luanch:,当点击按钮时label上显示用户选择的起始地点信息,代码如下所示:
- - (IBAction)luanch:(id)sender
- {
- NSInteger fromIndex = [self.pickerView selectedRowInComponent:0];
- NSInteger toIndex = [self.pickerView selectedRowInComponent:1];
- self.label.text = [NSString stringWithFormat:@"用户想从%@到%@", self.fromCitys[fromIndex], self.toCitys[toIndex]];
- }
7.4 完整代码
本案例中,TRAppDelegate.m文件中的完整代码如下所示:
- #import "TRAppDelegate.h"
- #import "TRDatePickerViewController.h"
- @implementation TRAppDelegate
- -(BOOL)application:(UIApplication *)application
- didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
- self.window = [[UIWindow alloc]initWithFrame:[[UIScreen mainScreen]bounds]];
- TRPickerViewViewController *pvVC = [[TRPickerViewViewController alloc]initWithNibName:@"TRPickerViewViewController" bundle:nil];
- UINavigationController *navi = [[UINavigationController alloc]initWithRootViewController:pvVC];
- self.window.rootViewController = navi;
- [self.window makeKeyAndVisible];
- return YES;
- }
- @end
本案例中,TRPickerViewViewController.h文件中的完整代码如下所示:
本案例中,TRPickerViewViewController.m文件中的完整代码如下所示:
- #import "TRPickerViewViewController.h"
- @interface TRPickerViewViewController () <UIPickerViewDataSource, UIPickerViewDelegate>
- @property (weak, nonatomic) IBOutlet UIPickerView *pickerView;
- @property (weak, nonatomic) IBOutlet UILabel *label;
- @end
- @implementation TRPickerViewViewController
- - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
- {
- self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
- if (self) {
- self.title = @"起始地点";
- }
- return self;
- }
- - (NSArray *)fromCitys
- {
- if(!_fromCitys)_fromCitys = @[@"北京",@"上海",@"广州",@"深圳",@"成都"];
- return _fromCitys;
- }
- - (NSArray *)toCitys
- {
- if(!_toCitys)_toCitys = @[@"上海",@"广州",@"深圳",@"成都", @"杭州"];
- return _toCitys;
- }
- //告诉pickerView显示多少组
- - (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
- {
- return 2;
- }
- //告诉pickerView每组显示多少行
- - (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
- {
- if (component==0) {
- return self.fromCitys.count;
- }else if(component==1){
- return self.toCitys.count;
- }
- return 0;
- }
- //告诉pickerView每行显示的标题
- - (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
- {
- if(component==0){
- return self.fromCitys[row];
- }else{
- return self.toCitys[row];
- }
- }
- - (IBAction)luanch:(id)sender
- {
- NSInteger fromIndex = [self.pickerView selectedRowInComponent:0];
- NSInteger toIndex = [self.pickerView selectedRowInComponent:1];
- self.label.text = [NSString stringWithFormat:@"用户想从%@到%@", self.fromCitys[fromIndex], self.toCitys[toIndex]];
- }
- @end
8 网页浏览
8.1 问题
网页控件UIWebView是UIKit框架提供的用于访问网页的视图控件,它有一个内置的浏览器。本案例将学习如何使用UIWebView控件实现一个简易的浏览器,并且具有网页的前进、后退和刷新功能,如图-24所示:
![](http://pdf7.tarena.com.cn/tts8_source/ttsPage/IOS/ISD_V01/CONTROLLERS2/DAY04/CASE/01/index.files/image024.png)
图-24
8.2 方案
首先同样创建一个SingleViewApplication项目,然后创建一个带有xib的视图控制器类TRViewController,作为本案例的根视图控制器。
其次在xib文件中拖放一个UIWebView控件用于加载网页、一个ActivityIndicatorView控件用于加载等待、一个TextField控件用于用户输入网址以及三个Button控件用于控制前进、后退和刷新。
然后在右边栏的第四个检查器中设置各控件的相关属性。
最后将xib中的UIWebView控件、ActivityIndicatorView控件和TextField关联成私有属性。
再分别将三个Button控件和TextField控件关联成方法,在TRViewController.m文件中实现TextField控件和按钮事件的响应方法。
8.3 步骤
实现此案例需要按照如下步骤进行。
步骤一:创建TRViewController视图控制器
首先在Xcode项中创建一个带有xib的视图控制器类TRViewController,继承至UIViewController,并在TRAppDelegate的程序入口方法中创建根视图控制器对象,代码如下所示:
- -(BOOL)application:(UIApplication *)application
- didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
- self.window = [[UIWindow alloc]initWithFrame:[[UIScreen mainScreen]bounds]];
- TRViewController *vc = [[TRViewController alloc]initWithNibName:@"TRViewController" bundle:nil];
- self.window.rootViewController = vc;
- [self.window makeKeyAndVisible];
- return YES;
- }
步骤二:在xib文件中拖放控件
在xib文件中拖放一个UIWebView控件、一个ActivityIndicatorView控件、一个TextField控件以及三个Button控件,如图-25所示:
![](http://pdf7.tarena.com.cn/tts8_source/ttsPage/IOS/ISD_V01/CONTROLLERS2/DAY04/CASE/01/index.files/image025.png)
图-25
然后在右边栏的第四个检查器中设置个控件的相关属性,将WebView控件的Scales Page To Fit选项勾上,表示会根据WebView的大小显示所访问的网页,如图-26所示:
![](http://pdf7.tarena.com.cn/tts8_source/ttsPage/IOS/ISD_V01/CONTROLLERS2/DAY04/CASE/01/index.files/image026.png)
图-26
步骤三:关联代码,实现方法
首先将xib中UIWebView控件、ActivityIndicatorView控件和TextField关联成私有属性webView、tf和activityIndicatorView,代码如下所示:
- @interface TRDatePickerViewController ()
- @property (weak, nonatomic) IBOutlet UIWebView *webView;
- @property (weak, nonatomic) IBOutlet UITextField *tf;
- @property (weak, nonatomic) IBOutlet UIActivityIndicatorView *activityIndicatorView;
- @end
其次将TextField控件的Did End On Exit事件关联方法go:,当点击键盘右下角的按钮时就访问所输入的网址,代码如下所示:
- - (IBAction)go:(UITextField *)sender
- {
- //tf退出第一响应
- [sender resignFirstResponder];
- //创建一个url请求
- NSString *urlString = [NSString stringWithFormat:@"http://%@",sender.text];
- sender.text = urlString;
- NSURL *url = [NSURL URLWithString:urlString];
- NSURLRequest *request = [NSURLRequest requestWithURL:url];
- //webView发送请求
- [self.webView loadRequest:request];
- }
然后分别将三个按钮关联成事件方法goBack:、goForward以及reload:,三个方法分别实现网页的后退、前进和刷新,代码如下所示:
- - (IBAction)goBack:(UIButton *)sender {
- [self.webView goBack];
- }
- - (IBAction)gouForward:(UIButton *)sender {
- [self.webView goForward];
- }
- - (IBAction)reLoad:(UIButton *)sender {
- [self.webView reload];
- }
最后根据webView的属性loading的值,控制activityIndicatorView的旋转和显示,代码如下所示:
- -(void)viewDidLoad {
- [super viewDidLoad];
- [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(isActivity) userInfo:nil repeats:YES];
- }
- -(void)isActivity {
- if (self.webView.isLoading==YES) {
- //当网页正在加载时,活动指示器开始旋转
- [self.activityIndicatorView startAnimating];
- }else {
- //当网页加载完成,活动指示器停止旋转
- [self.activityIndicatorView stopAnimating];
- }
- }
8.4 完整代码
本案例中,TRAppDelegate.m文件中的完整代码如下所示:
- #import "TRAppDelegate.h"
- #import "TRViewController.h"
- @implementation TRAppDelegate
- -(BOOL)application:(UIApplication *)application
- didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
- self.window = [[UIWindow alloc]initWithFrame:[[UIScreen mainScreen]bounds]];
- TRViewController *vc = [[TRViewController alloc]initWithNibName:@"TRViewController" bundle:nil];
- self.window.rootViewController = vc;
- [self.window makeKeyAndVisible];
- return YES;
- }
- @end
本案例中,TRViewController.m文件中的完整代码如下所示:
- #import "TRViewController.h"
- @interface TRViewController ()
- @property (weak, nonatomic) IBOutlet UIWebView *webView;
- @property (weak, nonatomic) IBOutlet UITextField *tf;
- @property (weak, nonatomic) IBOutlet UIActivityIndicatorView *activityIndicatorView;
- @end
- @implementation TRViewController
- -(void)viewDidLoad {
- [super viewDidLoad];
- [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(isActivity) userInfo:nil repeats:YES];
- }
- -(void)isActivity {
- if (self.webView.isLoading==YES) {
- [self.activityIndicatorView startAnimating];
- }else {
- [self.activityIndicatorView stopAnimating];
- }
- }
- - (IBAction)go:(UITextField *)sender
- {
- [sender resignFirstResponder];
- NSString *urlString = [NSString stringWithFormat:@"http://%@",sender.text];
- sender.text = urlString;
- NSURL *url = [NSURL URLWithString:urlString];
- NSURLRequest *request = [NSURLRequest requestWithURL:url];
- [self.webView loadRequest:request];
- }
- - (IBAction)goBack:(UIButton *)sender {
- [self.webView goBack];
- }
- - (IBAction)gouForward:(UIButton *)sender {
- [self.webView goForward];
- }
- - (IBAction)reLoad:(UIButton *)sender {
- [self.webView reload];
- }
- @end