1 在界面上以各种模式显示图片
1.1 问题
在ios开发中经常需要展示图片以满足需求和美化界面,本案例将学习如何以代码的方式使用UIImageView视图控件来展示图片,如图-1所示:
图-1
1.2 方案
UIImageView是UIView的子类,主要功能是用来展示图片,首先创建一个带有xib的SingleViewApplication项目,根视图控制器命名为TRImageViewController并添加图片素材到项目。
其次使用代码创建对象,在TRImageViewController.m文件中viewDidLoad方法里面创建一个UIImage对象image和UIImageView对象imageView,将image赋值给imageView的image属性。
然后设置UIImageView的frame属性,在父视图上添加imageView对象。
最后设置展示图片的样式,查看不同的样式展现的图片效果。
1.3 步骤
实现此案例需要按照如下步骤进行。
步骤一:创建一个带有xib的SingleViewApplication项目
首先创建一个带有xib的SingleViewApplication项目,根视图控制器命名为TRImageViewController。
然后选中一张图片素材,拖进导航栏,会弹出一个对话框,如图-2所示:
图-2
在Copy items if needed选择框打钩,表示将图片复制一份到项目中,然后点击Finish按钮。
步骤二:创建UIImageView对象
首先在TRImageViewController.m文件中viewDidLoad方法里面使用工厂方法imageNamed:创建一个UIImage对象image,该方法需要传递的参数就是图片的名字,代码如下所示:
- //创建UIImage对象,就是即将展示的图片
- UIImage *image = [UIImageimageNamed:@"Elephant.jpg"];
然后创建一个UIImageView对象imageView,初始化方法使用initWithImage:,此方法需要传递一个UIImage类型的参数,该参数就是imageView需要显示的图片,这里将刚创建的image传过来即可,并将imageView的frame设置成父视图的frame,填充满父视图,代码如下所示:
- //创建UIImageView对象
- UIImageView *imageView = [[UIImageViewalloc]initWithImage:image];
- //这里使用self.view.frame来赋值是暂时的,并不够准确
- imageView.frame = self.view.frame;
- //将imageView添加到父视图中
最后将imageView添加到父视图中,代码如下所示:
- [self.viewaddSubView:imageView];
步骤三:选择imageView展示图片的样式
UIImageView提供了多种展示图片的样式,由UIViewContentMode类型的属性contentMode来控制,UIViewContentMode是一个枚举类型,提供了13种样式,如图-3所示:
图-3
本案例中分别使用三种常用的显示模式UIViewContentModeScaleToFill,UIViewContentModeScaleAspectFit,UIViewContentModeScaleAspectFill,来看看不同的图片显示效果,先将UIViewContentModeScaleToFill赋值给imageView的contentMode属性。代码如下所示:
- [imageViewsetContentMode:UIViewContentModeScaleAspectFill];
运行程序可见图片将会填充满整个imageView,并且整张图片会被完整显示,但是由于原图片的宽高比和imageView的宽高比不一致,所以图片会变形,如图-4所示:
图4
然后将UIViewContentModeScaleAspectFit赋值给imageView的contentMode属性,代码如下所示:
- [imageViewsetContentMode:UIViewContentModeScaleAspectFit];
运行程序可见图片会被完整显示,并且整张图片会保持宽高比,但是图片会被缩小显示,所以imageView不会被图片填充满,如图-5所示:
图-5
最后将UIViewContentModeScaleAspectFill赋值给imageView的contentMode属性,代码如下所示:
- [imageViewsetContentMode:UIViewContentModeScaleAspectFill];
运行程序可见图片会保持宽高比和原始大小,但是不会被imageView完整显示,如图-6所示:
图-6
本案例只展示了常用的三种图片模式,根据实际需求也可以选择其他的样式,这里不再阐述。
1.4 完整代码
本案例中,TRImageViewController.m文件中viewDidLoad方法中的完整代码如下所示:
2 使用UIScrollView展示一张超出屏幕的图片
2.1 问题
很多ios的应用软件都会滚动显示单个或多个图片,UIScrollView控件主要就是用来满足这种需求的,本案例将使用UIScrollView来展示一张超出屏幕大小的图片,并且可以两指缩放图片大小,如图-7所示:
图-7
2.2 方案
首先使用Xcode创建一个SingleViewApplication项目,新建一个带有导航的视图控制器为根视图,命名为TRViewController。
其次用代码创建一个UIScrollView对象scrollView和一个UIImageView对象imageView,并且给imageView设置一张图片。
然后将imageView添加到scrollView中,设置scrollView的frame、contentSize等相关属性,并将scrollView添加到父视图中。
最后通过UIScrollView的delegate实现两指缩放图片功能。
2.3 步骤
实现此案例需要按照如下步骤进行。
步骤一:创建UIScrollView对象
首先在已经创建好的Xcode项目中选择TRViewController.m文件,定义一个UIScrollView类型的私用属性scrollView和一个UIImageView类型的私有属性imageView,在viewDidLoad:方法里面创建一个UIScrollView对象,赋值给属性scrollView,代码如下所示:
- @interface TRViewController ()
- @property (nonatomic, strong)UIScrollView *scrollView;
- @property (nonatomic, strong)UIImageView *imageView;
- @end
- //viewDidLoad方法中
- - (void)viewDidLoad
- {
- [superviewDidLoad];
- UIScrollView *scrollView = [[UIScrollViewalloc]init];
- self.scrollView = scrollView;
- }
步骤二:给scrollView添加内容视图
在viewDidLoad:方法里面创建一个UIImageView对象,赋值给属性imageView,并设置好imageView显示的图片,imageView就是scrollView的内容视图,然后将imageView添加到scrollView中,注意此时并没有设置imageView的frame,则imageView的原点坐标就是{0,0},宽高直接就是原图片的宽高,代码如下所示:
- UIImageView *imageView = [[UIImageViewalloc]initWithImage:[UIImageimageNamed:@"Galaxy.jpg"]];
- self.imageView = imageView;
- [self.scrollViewaddSubview:imageView];
步骤三:设置scrollView的相关属性
将self.scrollView的frame设置为父视图的frame,使其填充满父视图,将self.scrollView添加到父视图,代码如下所示:
- self.scrollView.frame = self.view.frame;
- [self.viewaddSubview:self.scrollView];
然后设置self.scrollView的显示属性,UIScorllView控件有三个与显示相关的重要属性:contentSize、contentInset和contentOffSet。
属性contentSize表示UIScrollView中内容视图的大小,返回的是一个CGSize结构体类型,该结构体包含width和height两个成员,本案例scrollView显示的视图大小就是self.imageView的大小,代码如下所示:
- self.scrollView.contentSize = imageView.frame.size;
此时运行程序,可见只能显示图片的一部分,然后选中图片可以任意移动图片,实现滚动屏幕的效果。
属性contentInset用于在UIScrollView控件中的内容视图周围添加边距,返回的是一个UIEdgeInsets结构体类型,该结构体包含top、left、bottom和right四个成员,表示四个边距,这里设置上边距和左边距20个像素,代码如下所示:
- self.scrollView.contentInset = UIEdgeInsetsMake(20, 20, 0, 0);
运行程序,滚动图片可见内容视图离上边和左边都有一个空白的边距,效果如图-8所示:
图-8
属性contentOffSet是内容视图坐标原点和UIScrollView坐标原点的偏移量,可以改变显示内容的显示区域,该属性返回一个CGPoint结构体类型,本案例中添加一个导航栏按钮,当点击按钮通过改变contentOffSet属性的值实现内容视图显示位置的改变,代码如下所示:
- self.navigationItem.rightBarButtonItem = [[UIBarButtonItemalloc]initWithTitle:@"move" style:UIBarButtonItemStyleBorderedtarget:self action:@selector(move)];
- //move方法的实现
- - (void)move
- {
- [self.scrollViewsetContentOffset:CGPointMake(3000, 1600) animated:YES];
- }
运行程序,点击按钮可见内容视图的坐标发生了偏移,显示图片的区域发生了改变,如图-9所示:
图-9
UIScrollView一些其他属性的设置,代码如下所示:
- //设置反弹
- self.scrollView.bounces = NO;
- //设置滚动条的样式
- [self.scrollViewsetIndicatorStyle:UIScrollViewIndicatorStyleBlack];
- //设置是否显示平行滚动条
- self.scrollView.showsHorizontalScrollIndicator = NO;
- //设置是否显示垂直滚动条
- self.scrollView.showsVerticalScrollIndicator = NO;
步骤四:通过delegate实现两指缩放功能
首先TRViewController需要遵守<UIScrollViewDelegate>协议,然后在viewDidLoad:方法里面给self.delegate赋值,代码如下所示:
- //遵守协议
- @interface TRViewController () <UIScrollViewDelegate>
- //viewDidLoad方法里面进行赋值
- self.scrollView.delegate = self;
然后设置放大缩小的最小比例和最大比例,由UIScrollView的属性minimumZoomScale和属性maximumZoomScale来控制,代码如下所示:
- //设置可以缩放的比例
- floathorizontalScale=self.scrollView.frame.size.width / imageView.frame.size.width;
- floatverticalScale = self.scrollView.frame.size.height / imageView.frame.size.height;
- self.scrollView.minimumZoomScale = MIN(horizontalScale, verticalScale);
- self.scrollView.maximumZoomScale = 1.0;
然后通过协议方法viewForZoomingInScrollView:确定需要进行方法缩小的视图,本案例中需要放大缩小的视图是self.imageView,代码如下所示:
- - (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
- {
- returnself.imageView;
- }
最后运行程序就能对显示的图片进行放大缩小的操作。
2.4 完整代码
本案例中,TRFirstViewController.m文件中的完整代码如下所示:
- #import "TRViewController.h"
- @interface TRViewController () <UIScrollViewDelegate>
- @property (nonatomic, strong)UIImageView *imageView;
- @property (nonatomic, strong)UIScrollView *scrollView;
- @end
- - (void)viewDidLoad
- {
- [superviewDidLoad];
- UIScrollView *scrollView = [[UIScrollViewalloc]init];
- self.scrollView = scrollView;
- //添加显示内容
- UIImageView *imageView = [[UIImageViewalloc]initWithImage:[UIImageimageNamed:@"Galaxy.jpg"]];
- self.imageView = imageView;
- [self.scrollViewaddSubview:imageView];
- //将self.scrollView添加到父视图
- self.scrollView.frame = self.view.frame;
- [self.viewaddSubview:self.scrollView];
- //设置scrollView显示内容的大小
- self.scrollView.contentSize = imageView.frame.size;
- //设置显示内容的边距
- self.scrollView.contentInset = UIEdgeInsetsMake(20, 20, 0,0);
- self.navigationItem.rightBarButtonItem = [[UIBarButtonItemalloc]initWithTitle:@"move" style:UIBarButtonItemStyleBorderedtarget:self action:@selector(move)];
- //scrollView的其他属性
- //设置反弹
- self.scrollView.bounces = NO;
- //设置滚动条的样式
- [self.scrollViewsetIndicatorStyle:UIScrollViewIndicatorStyleBlack];
- //设置是否显示平行滚动条
- self.scrollView.showsHorizontalScrollIndicator = NO;
- //设置是否显示垂直滚动条
- self.scrollView.showsVerticalScrollIndicator = NO;
- //给scrollView的委托赋值
- self.scrollView.delegate = self;
- //设置可以缩放的比例
- floathorizontalScale = self.scrollView.frame.size.width / imageView.frame.size.width;
- floatverticalScale = self.scrollView.frame.size.height / imageView.frame.size.height;
- self.scrollView.minimumZoomScale = MIN(horizontalScale, verticalScale);
- self.scrollView.maximumZoomScale = 1.0;
- }
- - (void)move
- {
- [self.scrollViewsetContentOffset:CGPointMake(3000, 1600) animated:YES];
- }
- //scrollViewDelegate方法
- - (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
- {
- returnself.imageView;
- }
- @end
3 乐库应用的欢迎界面
3.1 问题
本案例通过UIScrollView和UIPageController的配合使用,实现一个音乐播放器的欢迎界面,效果如图-10所示:
图-10
3.2 方案
首先创建项目,将根视图控制器命名为TRWelcomeViewController,然后将欢迎界面的五张图片添加到项目中,在TRWelcomeViewController.h文件中定义一个NSArray类型的属性imageNames,用来存储这五张欢迎图片的名称。
其次在TRWelcomeViewController.m文件的viewDidLoad方法里面创建一个UIScrollView对象,用来滚动显示欢迎图片。
然后给scrollView添加内容视图,本案例内容视图是五个UIImageView对象,分别用来显示五张欢迎图片,并且设置显示的相关属性。
最后添加一个UIPageController对象,配合scrollView滚动显示图片,实现分页功能。
3.3 步骤
实现此案例需要按照如下步骤进行。
步骤一:定义和实现图片名数组
项目创建完成后,首先在TRWelcomeViewController.h文件中定义个NSArray类型的数组imageNames,并在TRWelcomeViewController.m文件中使用懒汉模式进行初始化,将五张欢迎图片的图片名放进数组,代码如下所示:
- //TRWelcomeViewController.h文件中
- @interfaceTRWelcomeViewController : UIViewController
- @property (nonatomic, strong) NSArray *imageNames;
- @end
- //TRWelcomeViewController.m文件中
- - (NSArray *)imageNames
- {
- if(!_imageNames) _imageNames = @[@"Welcome1.jpg", @"Welcome2.jpg", @"Welcome3.jpg", @"Welcome4.jpg", @"Welcome5.jpg"];
- return _imageNames;
- }
步骤二:创建UIScrollView对象,并添加内容视图
首先在TRWelcomeViewController.m文件中viewDidLoad:中创建一个UIScrollView对象scrollView,设置frame使其填充满父视图,添加到父视图,代码如下所示:
- //创建ScrollView
- UIScrollView *scrollView = [[UIScrollViewalloc]initWithFrame:self.view.frame];
- [self.viewaddSubView:scrollView];
其次使用循环语句创建五个UIImageView对象分别显示五张欢迎图片,依次并排添加到scrollView中,这里要注意imageView的frame的设置,代码如下所示:
- //加入多个子视图(ImageView)
- for(inti=0; i<self.imageNames.count; i++){
- UIImage *image = [UIImageimageNamed:self.imageNames[i]];
- UIImageView *imageView = [[UIImageViewalloc]initWithImage:image];
- CGRect frame = CGRectZero;
- frame.origin.x = i * scrollView.frame.size.width;
- frame.size = scrollView.frame.size;
- imageView.frame = frame;
- [scrollViewaddSubview:imageView];
- }
最后设置scrollView显示的相关属性,这里需要注意contentSize的值是五张图片连接起来的大小,代码如下所示:
- //设置内容视图大小
- CGSize size = CGSizeMake(scrollView.frame.size.width * self.imageNames.count, scrollView.frame.size.height );
- scrollView.contentSize = size;
- //垂直滚动条隐藏
- scrollView.showsVerticalScrollIndicator = NO;
在这里还需要设置一个pageEnable属性,该属性用来控制翻页的效果,代码如下所示:
- //整页滚动
- scrollView.pagingEnabled = YES;
步骤三:创建UIPageController对象
UIPageController控件主要用来实现视图分页,通常会和UIScrollView配合使用,首先在TRWelcomeViewController.m文件中定义个UIPageController类型的属性pageController。然后在viewDidLoad:方法给该属性赋值,代码如下所示:
- @interface TRWelcomeViewController () <UIScrollViewDelegate>
- @property (nonatomic, strong)UIPageControl *pageControl;
- @end
- //viewDidLoad方法里面赋值,创建UIPageController对象
- UIPageControl *pageControl = [[UIPageControlalloc]init];
- self.pageControl = pageControl;
其次设置pageController的相关属性,并添加到父视图,注意父视图是self.view,而不是scrollView,代码如下所示:
- //加入页面指示控件PageControl
- UIPageControl *pageControl = [[UIPageControlalloc]init];
- self.pageControl = pageControl;
- //设置frame
- pageControl.frame = CGRectMake(0, self.view.frame.size.height - 40, self.view.frame.size.width, 20);
- //分页面的数量
- pageControl.numberOfPages = self.imageNames.count;
- //设置翻页标渲染颜色
- pageControl.pageIndicatorTintColor = [UIColorblackColor];
- //设置当前翻页标的渲染颜色
- pageControl.currentPageIndicatorTintColor = [UIColorredColor];
- //关闭用户交互
- pageControl.userInteractionEnabled = NO;
- //添加到父视图
- [self.viewaddSubview:pageControl];
最后实现pageController的指示标配合scrollView的滚动显示功能,此功能需要通过scrollView的delegate来实现。
所以首先需要遵守<UIScrollViewDelegate>协议,然后在viewDidLoad:方法里面给delegate赋值,最后实现协议中的scrollViewDidScroll:方法,该方法在每次完成滚动的时候都会被调用,即在该方法里面计算出当前显示第几页并赋值给self.pageControl.currentPage即可,代码如下所示:
- //遵守协议
- @interface TRWelcomeViewController () <UIScrollViewDelegate>
- //viewDidLoad方法里面给delegate赋值
- scrollView.delegate = self;
- //实现UIScrollViewDelegate协议方法
- - (void)scrollViewDidScroll:(UIScrollView *)scrollView
- {
- //计算当前显示第几页
- CGPoint offset = scrollView.contentOffset;
- if(offset.x<=0){
- offset.x = 0;
- scrollView.contentOffset = offset;
- }
- NSUInteger index = round(offset.x / scrollView.frame.size.width);
- self.pageControl.currentPage = index;
- }
步骤四:添加跳转按钮
在第五张欢迎图片上面覆盖一个一样大小的透明按钮,模拟实现一个进入音乐播放器的功能,在这里控制台输出一句话"进入音乐应用"即可,代码如下所示:
- //viewDidLoad方法里面添加按钮
- UIButton *button = [UIButtonbuttonWithType:UIButtonTypeSystem];
- CGRect frame = self.view.frame;
- frame.origin.x = scrollView.frame.size.width * (self.imageNames.count - 1);
- button.frame = frame;
- [scrollViewaddSubview:button];
- [buttonaddTarget:self
- action:@selector(enter)
- orControlEvents:UIControlEventTouchUpInside];
- //实现enter方法
- - (void)enter
- {
- NSLog(@"进入音乐应用");
- }
3.4 完整代码
本案例中,TRWelcomeViewController.h文件中的完整代码如下所示:
本案例中,TRWelcomeViewController.m文件中的完整代码如下所示:
- #import "TRWelcomeViewController.h"
- @interface TRWelcomeViewController () <UIScrollViewDelegate>
- @property (nonatomic, strong)UIPageControl *pageControl;
- @end
- @implementation TRWelcomeViewController
- - (NSArray *)imageNames
- {
- if(!_imageNames) _imageNames = @[@"Welcome1.jpg", @"Welcome2.jpg", @"Welcome3.jpg", @"Welcome4.jpg", @"Welcome5.jpg"];
- return _imageNames;
- }
- - (void)viewDidLoad
- {
- [superviewDidLoad];
- //创建ScrollView
- UIScrollView *scrollView = [[UIScrollViewalloc]initWithFrame:self.view.frame];
- //加入多个子视图(ImageView)
- for(inti=0; i<self.imageNames.count; i++){
- UIImage *image = [UIImageimageNamed:self.imageNames[i]];
- UIImageView *imageView = [[UIImageViewalloc]initWithImage:image];
- CGRect frame = CGRectZero;
- frame.origin.x = i * scrollView.frame.size.width;
- frame.size = scrollView.frame.size;
- imageView.frame = frame;
- [scrollViewaddSubview:imageView];
- }
- //设置相关属性
- CGSize size = CGSizeMake(scrollView.frame.size.width * self.imageNames.count, scrollView.frame.size.height );
- scrollView.contentSize = size;
- scrollView.showsVerticalScrollIndicator = NO;
- //整页滚动
- scrollView.pagingEnabled = YES;
- //加入到当前视图self.view
- [self.viewaddSubview:scrollView];
- //加入页面指示控件PageControl
- UIPageControl *pageControl = [[UIPageControlalloc]init];
- self.pageControl = pageControl;
- //设置frame
- pageControl.frame = CGRectMake(0, self.view.frame.size.height - 40, self.view.frame.size.width, 20);
- //分页面的数量
- pageControl.numberOfPages = self.imageNames.count;
- //设置翻页标渲染颜色
- pageControl.pageIndicatorTintColor = [UIColorblackColor];
- //设置当前翻页标的渲染颜色
- pageControl.currentPageIndicatorTintColor = [UIColorredColor];
- //关闭用户交互
- pageControl.userInteractionEnabled = NO;
- //添加到父视图
- [self.viewaddSubview:pageControl];
- scrollView.delegate = self;
- //加个按钮
- UIButton *button = [UIButtonbuttonWithType:UIButtonTypeSystem];
- CGRect frame = self.view.frame;
- frame.origin.x = scrollView.frame.size.width * (self.imageNames.count - 1);
- button.frame = frame;
- [scrollViewaddSubview:button];
- [buttonaddTarget:self action:@selector(enter) forControlEvents:UIControlEventTouchUpInside];
- }
- - (void)enter
- {
- NSLog(@"进入音乐应用");
- }
- //UIScrollViewDelegate方法
- - (void)scrollViewDidScroll:(UIScrollView *)scrollView
- {
- CGPoint offset = scrollView.contentOffset;
- if(offset.x<=0){
- offset.x = 0;
- scrollView.contentOffset = offset;
- }
- NSUInteger index = round(offset.x / scrollView.frame.size.width);
- self.pageControl.currentPage = index;
- }
- @end
4 使用断点进行程序调试
4.1 问题
使用Xcode编程时,经常会出现bug,有时候找出这些bug会耗费大量的时间和精力,掌握有效的调试方法可以快速找出程序中的bug,本案例将学习如何使用断点(BreakPoint)调试错误。
4.2 方案
断点是指在条件满足的情况下程序会挂起在那里,可以在这里查看变量、单步运行等操作内容。首先设置断点,等程序挂起之后可以在调试工具栏里面一步步进行查看。
4.3 步骤
实现此案例需要按照如下步骤进行。
步骤一:首先设置断点
设置断点很简单,直接点击文件中的行号即可,如图-11所示就是在第31行打断点:
图-11
断点也可以删除、禁止使用和编辑,在断点上点击鼠标右键,弹出的快捷菜单如图-12所示:
图-12
选择DisableBreakPoint菜单项时,会禁止使用断点,这时断点会处于灰色状态,如图-13所示:
图-13
选择DeleteBreakPoint菜单项可以删除按钮,或者直接用鼠标选中断点往外拖,当出现一个小云朵时释放鼠标,也可以删除断点。
选择EditBreakPoint菜单项时,会弹出一个断点编辑对话框,可以在断点编辑对话框中为断点设置触发条件和动作,如图-14所示:
图-14
步骤二:调试工具栏的使用
在Xcode编辑区的下方有一个调试工具栏和变量查看窗口,如图-15所示:
图-15
在调试工具栏的控制按钮中有4个是常用的按钮,如图-16所示依次为继续执行按钮,单步跳过按钮,单步进入按钮,单步跳出按钮:
图-16
点击执行按钮程序会接着运行,直到运行到下一个断点或者程序结束,如果点击单步跳过按钮,程序会一步一步的执行,以图-11的代码为例会执行第32行代码,如果点击单步进去,会进去到调用的方法中。
步骤三:输出窗口中查看
输出窗口的左边窗口为变量输出窗口,用于查看变量和寄存器内容,通过点击窗口左上角的小三角,可以选择变量的范围,各选项的含义如下:
Auto:查看经常使用的变量。
LocalVariables:查看本地变量。
Variables,Registers,Globals and Static:查看全部变量。
可以通过各种变量的输出结果来排查错误和调试代码。