//给window钦赐根视图调控器,那样只要求三个Ce

2019-09-13 11:20栏目:大奖888官网登录
TAG:

1.ODRefreshControl qq使用的下拉刷新库

思路分析

一般的思路就是先把本地的emoji图片加载到内存,然后把emoji图片按照特定排列方式显示到自定义的view中,并且能响应点击事件(即点击到自定义view上时能知道点击的是哪个emoji),同时自定义view能够进行翻页来支持大量的emoji。

图片 1

2.RFKeyboardToolbar 是iOS一款灵活的添加自定义按钮和工具栏的工具。它是UIView 和UIButton 的子集。你可以在你的 UITextFields/UITextViews自由的添加自定义的按钮和工具栏。

加载emoji图片

笔者是采用Bundle的方式去管理项目中要用到的一百多个emoji表情,所以是要从Bundele中加载完所有的emoji图片(gif格式)。这里我是采用了YYImageDecoder去解码gif图片并且把它的第一帧图片放到表情图片数组中。为什么要使用YYImageDecoder去解码图片而不是直接用imageNamed:方法去加载请参考这篇文章: iOS 处理图片的一些小 Tip)

         NSMutableArray *emotionArry = [NSMutableArray new];
          NSString *path = [[[NSBundle mainBundle] resourcePath] stringByAppendingString:@"/myEmotion.bundle/"];
          for (int i = 1; i < 135; i++) {
              NSString *imgPath = [path stringByAppendingString:[NSString stringWithFormat:@"%d.gif",i]];
              NSData *data = [NSData dataWithContentsOfFile:imgPath];
              YYImageDecoder *decoder = [YYImageDecoder decoderWithData:data scale:0];
              UIImage *image = [decoder frameAtIndex:0 decodeForDisplay:YES].image;
              [emotionArry addObject:image];
          }

3.YLGIFImage 是异步加载GIF图片的类,支持GIF图片的播放与暂停。它用的内存很少,完全解码GIF通常会消耗600MB的内存(800x600x389x4 Bytes).

emoji图片显示到自定义view上

上一步已经把emoji加载了,这时候要考虑怎么把emoji图片显示到自定义view上。因为emoji键盘中的每一页表情明显是流水布局,不少人第一反应就是用UICollectionView去实现,其中每一页就是一个Cell,每个Cell里面就是放若干个背景是emoji的UIButton,这样只需要两个Cell就能完成复用了,同时点击emoji表情Button时候也能知道点击的那个Button。
其实用UICollectionView完成表情翻页的功能是正确的,但是错误的是Cell里面不应该用大量的UIButton去完成emoji的布局和点击功能,因为这样会消耗大量的资源去创建UIButton和处理其布局信息(如果用AutoLayout的话),翻页的时候会感受到明显的卡顿。
正确的方法应该把每一页的emoji画成一张图片,这样翻页的时候其实就是显示不同的图片。

            CGSize containerSize = CGSizeMake(ScreenWidth - 20, 92);  //表情键盘大小
            CGFloat horizonSpacing = (ScreenWidth - 20 - 9 * 24)/8;  //表情水平间隔
            CGFloat width = 24;
            CGFloat height = 24;
            NSMutableArray *containerArray = [NSMutableArray new];
            for (int i = 0; i < 5; i ++) {
                UIGraphicsBeginImageContext(CGSizeMake(ScreenWidth - 20, 92));//左右边距10 中间边距10
                CGContextRef context = UIGraphicsGetCurrentContext();
                [[UIColor whiteColor] setFill];
                CGContextFillRect(context, CGRectMake(0, 0, containerSize.width, containerSize.height));
                for (int j = 0; j < 27; j++) {
                    if (i == 4 && j == 26) {
                        continue;
                    }
                    UIImage *emotion = emotionArry[i * 27 + j];
                    CGRect emotionRect = CGRectMake((j % 9) * (width + horizonSpacing), floor(j/9) * (height + 10), width, height); // 计算出图片frame
                    [emotion drawInRect:emotionRect];   //把emoji绘制到画布上
                }
                UIImage *emotionContainerView = UIGraphicsGetImageFromCurrentImageContext();  //取出每一页的图片
                [containerArray addObject:emotionContainerView];
                UIGraphicsEndImageContext();
            }
            self.emotionsContainerViewArray = containerArray;

4.SVWebViewController 实现完整的网页显示功能,包括后退、前进、刷新、邮件分享等。

emoji的点击事件

emoji已经画成一张张的图片,但是但用户点击的时候如何知道他点击了哪个emoji?
因为UICollectionCell中只是简单的添加了一个UIImageView去显示图片,我们可以对UICollectionCell中添加tap手势,当触发手势时候,根据当前的Cell index和点击手势的x和y信息就可以算出用户点击的是哪个emoji。

- (void)touchEmotionsView:(UITapGestureRecognizer *)gesture {
  CGPoint point = [gesture locationInView:gesture.view];
  CGFloat horizonSpacing = (ScreenWidth - 20 - 9 * 24)/8;
  CGFloat width = 24;
  CGFloat height = 24;
  CGFloat verticalSpacing = 10;
  CGFloat x = point.x;
  CGFloat y = point.y;
  int indexX = floor(x/(horizonSpacing + width));
  int indexY = floor(y/(verticalSpacing + height));
  int index = (int)_indexPath.row * 27 + indexY * 9 + indexX;
  if (index > 133) {
      return;
  } else {
      NSString *emotion = [NSString stringWithFormat:@"[%d.gif]",index];
      if ([self.parent.delegate respondsToSelector:@selector(selectedEmotion:)]) {
          [self.parent.delegate selectedEmotion:emotion];
      }
  }
}

代码创建UIWindow对象

5.NJKWebViewProgress 作者非常巧妙地通过计算需要加载的请求的个数,通过请求个数来现实加载进度,不得不佩服他的想法

缓存绘制好的emoji图片

其实功能已经实现的差不多了,一般来说这个自定义emoji键盘都是实现成单例的,需要用的时候把这个emoji键盘view赋值给UITextView/UITextField的inputview就能把它显示到键盘的位置中去。
但是没必要每次重新启动程序时需要用到这个单例都要在初始化单例时候去重新画emoji图片,我们可以把画好的emoji图片缓存在本地,后面每次初始化时候就可以直接加载缓存的图片而不用重新绘制。

(void)initEmotionsContainer {
  dispatch_async(dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0), ^{
      NSFileManager *fileManager = [[NSFileManager alloc] init];
      NSString *pathDocuments = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
      NSString *folderPath = [pathDocuments stringByAppendingPathComponent:@"emotion"];
      // 判断文件夹是否存在,如果不存在,则创建
      if (![[NSFileManager defaultManager] fileExistsAtPath:folderPath]) {
          JZLog(@"创建文件夹成功 %@", folderPath);
          [fileManager createDirectoryAtPath:folderPath withIntermediateDirectories:YES attributes:nil error:nil];
                /****
                  绘制emoji图片
                ***/
              UIImage *emotionContainerView = UIGraphicsGetImageFromCurrentImageContext();
              [containerArray addObject:emotionContainerView];
              NSData *data = [emotionContainerView yy_imageDataRepresentation];
              NSString *dataPath = [folderPath stringByAppendingPathComponent:[NSString stringWithFormat:@"emotion%d", i]];
              [data writeToFile:dataPath atomically:YES];
          }
          self.emotionsContainerViewArray = containerArray;
          dispatch_async(dispatch_get_main_queue(), ^{
              [self.collectionView reloadData];
          });
      } else {
          JZLog(@"从磁盘加载表情");
          NSMutableArray *containerArray = [NSMutableArray new];
          for (int i = 0; i < 5; i++) {
              NSString *dataPath = [folderPath stringByAppendingPathComponent:[NSString stringWithFormat:@"emotion%d", i]];
              NSData *data = [NSData dataWithContentsOfFile:dataPath];
              UIImage *emotionContainer = [UIImage imageWithData:data];
              [containerArray addObject:emotionContainer];
          }
          self.emotionsContainerViewArray = containerArray;
          dispatch_async(dispatch_get_main_queue(), ^{
              [self.collectionView reloadData];
          });
      }
  });
}

Xcode7之后使用代码创建UIWindow对象:

6.Font awesome 是一个形象字体库。通过扩展 NSString 来轻松使用 FontAwesome 字体。

结尾

自定义Emoji键盘的就完成的差不多,其主要思路同时通过绘制控件而不是添加控件去减少对象的创建,并且加载缓存数据实现一次绘制多次使用。

//创建UIWindow对象

7.PPiAwesomeButton 是 UIButton 的分类,实现了扁平化设计和额外的方法用来设置图标+文本的样式。

self.window =[[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];

8.SWTableViewCell 一个使用起来很简单的UITableViewCell子类,可以通过左右滑动调出view,view上有工具按钮(和iOS 7的系统Mail类似)。

//给window设置背景颜色(白色)

9.ASProgressPopUpView 在直接在进度栏上显示进度的百分比,并提供颜色和不同效果的定制。

self.window.backgroundColor = [UIColorwhiteColor];

10.SMPageControl自定义UIPageControl的外观,包括形状、大小、间距等,也可以用图片代替UIPageControl上的小圆点。

//使window显示

11.AGEmojiKeyboard 是 iOS 上一个实现了对 emoji 表情支持的键盘控件。

[self.window makeKeyAndVisible];

12.TPKeyboardAvoiding:有文字输入时,能根据键盘是否弹出来调整自身显示内容的位置

//创建一个视图控制器

13.JDStatusBarNotification:状态栏提示框

UIViewController *VC = [[UIViewController alloc] init];

14.BlocksKit:block工具包。将很多需要用delegate实现的方法整合成了block的形式

//给window指定根视图控制器

15.ReactiveCocoa:基于响应式编程思想的oc实践

self.window.rootViewController = VC;

16.QBImagePickerController 扩展了 UIImagePickerController 类用于支持图像的多选操作。

自动创建UIWindow对象

17.MJPhotoBrowser 实现了一个照片浏览器类似 iOS 自带的相册应用,可显示来自手机的图片或者是网络图片,可自动从网络下载图片并进行缓存。可对图片进行缩放等操作。 MWPhotoBrowser

l1)先执行Main函数,执行UIApplicationMain()创建代理

l2)看项目配置文件info.plist里面的StoryBoard的name

l3)根据这个name找到对应的StoryBoard,加载StoryBoard

l4)在加载的时候创建一个window。

UIView功能

•1)管理矩形区域里的内容

•2)处理矩形区域中的事件

•3)子视图的管理

•4)实现UIView动画

•5)UIView作为父类,子类也具有这些功能

如何确定一个矩形

1.首先确定这个矩形的位置。(iOS中以左上角为坐标原点)

2.其次确定这个矩形的大小。

iOS中通过确定一个矩形的左上角的点(x,y)以及矩形的 宽(width)和高(height)来确定一个矩形。

坐标系相关数据类型

坐标:

struct CGPoint {CGFloat x;

CGFloat y;

};

typedef struct CGPoint CGPoint;

大小:

struct CGSize {CGFloat width;

CGFloat height;

};

typedef struct CGSize CGSize;

矩形:

struct CGRect {CGPoint origin;

CGSize size;

};

typedef structCGRect CGRect;

iOS中使用CGRect类型确定矩形位置以及大小

创建UIView

代码:

//开辟空间创建UIView对象

//设置frame确定UIView对象的位置及大小

UIView *view =[[UIView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];

//设置UIView对象的属性:设置背景颜色

view.backgroundColor = [UIColor redColor];

//将创建好的UIView对象添加到window上显示

[self.windowaddSubview:view];

第二节:

UILabel:

•UILabel(标签):是显⽰示⽂文本的控件。在App中UILabel是出现频率最⾼高的控件

•UILabel是UIView⼦子类,作为⼦子类⼀一般是为了扩充⽗父类的 功能UILabel扩展了⽂文字显⽰示的功能,UILabel是能显⽰示⽂文 字的视图。

创建UILabel与创建UIView的步骤很相似。

1、开辟空间并初始化(如果本类有初始化⽅方法,则使⽤用⾃自⼰己的初 始化⽅方法;否则使⽤用⽗父类的)。

2、设置⽂文本控制相关的属性

3、添加到⽗父视图上,⽤用以显⽰示

4、 释放所有权(只是做了引⽤用计数-1)

UILabel *userNameLabel = [[UILabel alloc]

initWithFrame:CGRectMake(30, 100, 100, 30)]; userNameLabel.text = @“⽤用户名”;

[containerView addSubview:userNameLabel];

[userNameLabel release];

注:containerView已经添加到根视图上

•UITextField(输入框):是控制⽂本输入和显示的控件。在App中UITextField出现频率也比较高。

•iOS系统借助虚拟键盘实现输入,当点击输入框,系统会自动调出键盘, ⽅便你进一步操作。在你不需要输入的时候,可以使用收回键盘的⽅法,收回弹出的键盘。

•UITextField和UILabel相比,UILabel主要用于文字显示,不能编辑,UITextField允许用户编辑文字(输⼊)

创建UITextField与创建UILabel的步骤很相似。

1、开辟空间并初始化(如果本类有初始化⽅方法,则使⽤用⾃自⼰己的初始化⽅方法;否则使⽤用⽗父类的)。

2、设置⽂文本显⽰示、输⼊入等相关的属性

3、添加到⽗父视图上,⽤用以显⽰示

4、释放对象所有权

//使用初始化方法创建对象

UITextField *userNameTextField = [[UITextFieldalloc] initWithFrame:CGRectMake(100, 100, 190, 30)];

//设置边框⻛风格

userNameTextField.borderStyle= UITextBorderStyleRoundedRect;

//设置占位符

userNameTextField.placeholder

= @“手机号/邮箱";[containerViewaddSubview:userNameTextField];[userNameTextField release];

•UIButton(按钮):是响应用户点击的控件。在App中UIButton是 出现频率很高的控件。

•UIButton与UILabel、UITextField侧重点不同,侧重于处理用户交互 事件。当然UIButton类也提供了一些方法控制按钮外观。

创建UIButton与创建UILabel、UITextField、UIView的步骤很相似。

1、创建button对象(如果本类有初始化方法,则使用自己的初始化方法;否则使用父类的)。

2、设置按钮相关的属性

3、为按钮添加点击事件

4、添加按钮到父视图上,用以显示

5、按钮无需释放(一般情况创建UIButton都使用自己的便利构造器方法,无需释放对象的所有权)

//便利构造器⽅方法创建对象

UIButton*loginButton = [UIButton buttonWithType:UIButtonTypeSystem];loginButton.frame = CGRectMake(30, 200, 60,30);

//设置button的标题

[loginButton setTitle:@"登录" forState:UIControlStateNormal];

//添加点击事件

[loginButtonaddTarget:self action:@selector(login:)forControlEvents:UIControlEventTouchUpInside];[containerView addSubview:loginButton];

UIImageView是iOS中用于显示图片的类,iOS中几乎所有看到的 图片,都是由这个类来显示的。

//图⽚片⽂文件路径

NSString *path= [[NSBundle mainBundle] pathForResource:@"1"ofType:@"jpg"];

//创建⼀一个UIImage对象,使用initWithContentOfFile:方法

UIImage *image= [UIImage imageWithContentsOfFile:path];//创建一个UIImageView对象,使用initWithImage:方法

UIImageView*imageView = [[UIImageView alloc] initWithImage:image];

imageView.frame= CGRectMake(100, 100, 100, 100);[self.view addSubview:imageView];

•animationImages//设置⼀一组动态图⽚片

•animationDuration//设置播放⼀一组动态图⽚片的时间

•animationRepeatCount//设置重复次数

•startAnimating//开始动画

•stopAnimating//结束动画

第三节:

LTView的具体使用

//创建LTView对象

LTView*usernameView = [[LTView alloc] initWithFrame:CGRectMake(40,100, 300,50)];usernameView.leftLabel.text =@"⽤用户名:";usernameView.rightField.placeholder = @"请输入用户名";[usernameView.rightField becomeFirstResponder];[backViewaddSubview:usernameView];//backView是LTView添加到的父视图

[usernameViewrelease];

视图控制器指定自定义View

如何设置

-(void)loadView{

[superloadView];

self.myView =[[MyView alloc] initWithFrame:self.view.frame];

self.view =self.myView;

[self.myViewrelease];

}

#pragma mark视图加载完毕

- (void)viewDidLoad {

[superviewDidLoad];

self.view.backgroundColor= [UIColor grayColor];NSLog(@"%s%d",__FUNCTION__, __LINE__);

//为自定义视图里面的按钮添加点击事件[self.myView.buttonaddTarget:self action:@selector(buttonAction)forControlEvents:UIControlEventTouchUpInside];

}

#pragma mark点击⽅方法

-(void)buttonAction{

NSLog(@"点击了⾃自定义视图⾥里⾯面的按钮");

}

#pragma mark内存警告⽅方法

-(void)didReceiveMemoryWarning {

//即使没有显⽰示在window上,也不会⾃自动的将self.view释放。

[super didReceiveMemoryWarning];

NSLog(@"%s%d", __FUNCTION__, __LINE__);

// Dispose ofany resources that can be recreated.

}

第四节:

触摸事件的处理方法:

在给定的触摸阶段中,如果发生新的触摸动作或已有的触摸动作发生变化,应用程序就会发送这些消息;

当一个手指或多个手指触碰屏幕时,发送touchesBegan:withEvent:消息。

当一个手指或多个手指在屏幕上移动时,发送touchesMoved:withEvent:消息。

当一个手指或多个手指离开屏幕时,发送touchesBegan:withEvent:消息。

手势识别器

1 . UIapGestureRecognizer是轻拍⼿势识别器,能识别轻拍操作

2.U I L o n g P r e s s G e s t u r e R e c o

g n i z e r是长按⼿势识别器,能识别长按操作

3 . U I R o t a t i o n G e s t u r e R e c o g n i z

e r是旋转⼿势识别器,能识别旋转操作

4 .U I P i n c h G e s t u r e R e c o g n i z e r是捏合⼿势识别器,能识别捏合操作

5 .U I P a n G e s t u r e R e c o g n i z e r是平移⼿势识别器,能识别拖拽操作

6 . U I S w i p e G e s t u r e R e c o g n i z e r是轻扫⼿势识别器,能识别拖拽操作

7 . U I S c r e e n E d g e P a n G e s t u r e R e c

o g n i z e r是屏幕边缘轻扫识别器

View的transform属性:

transform是view的一个重要属性,他在矩阵层面上改变view的显示状态,能实现view的缩放、旋转、平移、等功能。

平移:CGAffineTransformMakeTranslation;

缩放:CGAffineTransformMakeScale;

旋转:CGAffineTransformMakeRottion;

第五节

UIControl常用方法:

1.添加一个事件:

参数说明:target为目标对象;action为方法选择器;controlEvents为触发事件。

(void)addTarget:(id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents;

2.移除一个事件:

参数说明:target为目标对象;action为方法选择器;

controlEvents为触发事件。

- (void)removeTarget:(id)target action: (SEL)action

forControlEvents: (UIControlEvents)controlEvents;

UISlider⽰示例代码:

创建一个UISlider对象,并且添加到self.view上

UISlider *slider = [[UISlider alloc] initWithFrame:CGRectMake(self.view.center.x- 100, imageView.frame.origin.y + imageView.frame.size.height + 50, 200,50)];

[self.view addSubview:slider];

[sliderrelease];

2.UISlider相关属性设置

//设置slider的最⼩小值

slider.minimumValue = 0.0;

//设置slider的最⼤大值

slider.maximumValue = 2;

//设置划过区域的颜⾊色

slider.minimumTrackTintColor = [UIColor redColor];

3.为UISlider添加事件:

//添加slider的事件

[slider addTarget:self action:@selector(sliderAction:)forControlEvents:UIControlEventValueChanged];

UISegmentedControl添加事件

1.为UISegmentedControl添加事件

[segmented addTarget:self action:@selector(segmentedAction:) forControlEvents:UIControlEventValueChanged];

2.UISegmentedControl事件的响应(通常我们和swich...case分⽀支语

句组合使用)

#pragma mark segmentedControl点击事件

-(void)segmentedAction:(UISegmentedControl *)segmented

{

switch (segmented.selectedSegmentIndex) {

case 0:

[self.view insertSubview:self.redbelowSubview:segmented];

break;

case 1:

[self.view insertSubview:self.bluebelowSubview:segmented];

break;

case 2:

[self.view insertSubview:self.yellowbelowSubview:segmented];

break;

default:

break;

}

}

UIPageControl常用属性和方法

•numberOfPages //指定页面个数(即点的个数)

•currentPage //指定pageControl的值(即选中的点)

•addTarget:action:forControlEvents: //给slider添加

事件

注意:controlEvent为UIControlEventValueChanged

原因:分页本质是通过数据管理分页,所以使⽤用valueChanged

属性来触发事件,即数组下标变化

总结

1.UIControl是所有控制视图的⽗父类。

2.UISwitch的状态监测。

3.UISlider为滑块控件,通过控制value来设置当前的值,通过⽤用来控制视

频、⾳音频等播放进度。

4.UISegmentedControl为分段控件,相当于⼀一组按钮,不同的Item可以

设置不同的点击事件。

5.UIPageControl的currentPage属性的使用。

需要注意:添加的点击事件通过UIControlEventValueChanged来触发事件

第六节

UIScrollView的创建

#define WIDTH self.view.frame.size.width

#define HEIGHTself.view.frame.size.height

// 1.创建⼀一个和屏幕等尺⼨寸的UIScrollView

UIScrollView*scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0,WIDTH,HEIGHT)];

// 2.设置背景颜⾊色

scrollView.backgroundColor= [UIColoryellowColor];

// 3.把scrollView放到self.view上显示

[self.viewaddSubview:scrollView];

// 4.内存管理

[scrollViewrelease];

UIScrollView协议方法

•当我们签好协议,设置好代理人之后,我们就可以使用

UIScrollView的协议方法了,它的协议方法分为两部分:

•一是监控滚动时候的状态。

•二是控制视图的缩放。

总结

•本节主要是为了让大家了解滚动视图的创建和基本的使用

方法,并且配合UIPageControl实现关联使用。

•UIScrollView主要的属性contentSize用来控制视图的滚动

范围,视图的变化显示主要由contentOffset偏移量来控

制。

•UIPageControl一般会和UIScrollView一同使用。

第七节

UINavigationController

UINavigationController:导航控制器,,是iOS中最常⽤用的多视图控制器之一,用它来管理多个视图控制器。

导航控制器可以称为是,管理控制器的控制器,主要管理有层

次递进关系的控制器。

创建

//创建根视图

RootViewController *rootVC =

[[RootViewController alloc] init];

//创建导航控制器 把rootVC作为导航控制器的根视图控制器

UINavigationController *navi =

[[UINavigationController alloc]

initWithRootViewController:rootVC];

//设置导航为window的根视图

self.window.rootViewController = navi;

//内存管理

[rootVC release];

[navi release];

导航栏半透明效果

//导航栏半透明效果(iOS7以后 默认为YES)

//当半透明效果开启时 屏幕左上⾓角为坐标原点

//关闭时 导航栏左下⾓角为坐标原点

self.navigationController.navigation

Bar.translucent = YES;

//创建⼀一个View

UIView *view = [[UIView alloc]

initWithFrame:CGRectMake(0, 0, 100,100)];

view.backgroundColor = [UIColor blueColor];

[self.view addSubview:view];

[view release];

页面跳转工作原理:

UINavigationController通过栈的方式管理控制器的切换,控制入栈和出栈来展示各个视图控制器。

•UINavigationController的ContentView里始终显示栈顶控制器的view。

•viewControllers属性是一个可变数组(NSMutableArray)存储了栈中的所有被管理的控制器,入栈的时候,使用addObject把新的视图控制器对象添加到数组末尾,出栈时removeLastObject移除数组末尾的试图控制器对象。

•navigationController属性,父类中的属性,每个在栈中的控制器,都能通过此属性,获取自己所在UINavigationController对象。

工作原理

• 栈的特点:先进后出,后进先出。

• 栈顶为当前显⽰示的视图控制器。

模态进入下一页

- (void)next

{

//⻚页⾯面跳转

//模态(modal)

// 1.创建第二页对象

SecondViewController *secVC = [[SecondViewControlleralloc]init];

// 2.设置过渡动画(有默认值,可以不设置)

secVC.modalTransitionStyle =UIModalTransitionStyleCoverVertical;

// 3.模态控制器

//参数1:第二页对象

//参数2:是否使用动画

//参数3:模态完成后执行的block

[self presentViewController:secVC animated:YEScompletion:^{

}];

// 4.内存管理

[secVC release];

}

总结

1.UINavigationController的创建

2.通过导航跳转页⾯面

3.自定义NavigationBar

4.模态

第八节:

回顾协议六步

第一步:声明协议

第二步:声明代理人

第三步:执行协议方法

第四步:签订协议

第五步:指定代理人

第六步:实现协议方法

代码演示

#warning第1步

//在SecondViewController.h⾥里声明协议

@protocol SecondViewControllerDelegate

-(void)changeValue:(NSString *)name;

@end

@interface SecondViewController : UIViewController

#warning第2步

//声明代理人

@property(nonatomic,assign)id

elegate>secondDelegate;

@end

#warning第3步

-(void)buttonAction:(UIButton *)button

{

//执⾏行协议方法

[self.secondDelegate

changeValue:self.textField.text];

[self.navigationController

popViewControllerAnimated:YES];

}

#warning第4步

//FirstViewController签订协议

@interface FirstViewController :

UIViewController

#warning第5步

-(void)buttonAction:(UIButton *)button

{

SecondViewController *secondVC =

[[SecondViewController alloc] init];

//指定当前对象为代理⼈人

secondVC.secondDelegate = self;

secondVC.contents = self.label.text;

[self.navigationController

pushViewController:secondVC animated:YES];

[secondVC release];

}

#warning第6步

//实现协议方法,并接收传过来的值

-(void)changeValue:(NSString *)name

{

self.label.text = name;

}

注意

@protocol SecondViewControllerDelegate

@required //必须要实现的⽅方法,默认是必须实现

-(void)changeValue:(NSString *)name;

@optional //可选实现的协议方法

-(void)changeColor:(UIColor *)color;

@end

block传值两种方式

• 方式一:使用block属性实现回调传值

• 方式二:在方法中定义block实现回调传值

方法中定义block

• 创建一个RootViewController并添加一个button和一个label

• 封装一个NSObject类

• 实现点击button将一个NSInteger类型的10086数字传入NSObject中,

• 将其转换为NSString类型

• 用block将转换完的字符串回传给RootViewController并显示在label上

提示:使用在方法中封装一个block来回调传值更方便

#warning第一步

//在AppTool.h中重定义void(^)(NSString *string)类型

的别名为AppToolBlock

typedef void(^AppToolBlock)(NSString *string);

#warning第二步

//声明方法,在方法中封装block

-(void)sendNumber:(NSInteger )number andBlock:

(AppToolBlock)block;

#warning第三步

//在AppTool.m实现方法,并执行block

-(void)sendNumber:(NSInteger )number andBlock:

(AppToolBlock)block;

{

NSString *string = [NSString

stringWithFormat:@"%ld",number];

block(string);

}

-(void)buttonAction:(UIButton *)button

{

#warning第四步

AppTool *appTool = [[AppTool alloc] init];

//执行方法,实现block并接收回传过来的string值

[appTool sendNumber:10086 andBlock:^(NSString

*string) {

self.label.text = string;

}];

}

总结

使用属性传值解决从前往后传值的问题

使用协议/代理解决从后往前传值的问题

使用__block修饰变量来解决block循环引用问题

注意:关于block内存管理上的三个区域,在arc和⾮非arc下还是有区别的,请学员自行打印验证结果

第九节

代码创建UITabBarController

代码:

// 1.创建UITabBarController对象

UITabBarController *tabBarController =

[[UITabBarController alloc] init];

// 2.将TabBarController管理的视图控制器放到⼀一个数组中

NSArray *viewControllers = [NSArray

arrayWithObjects:firstNav, secondNav,thirdNav,fourthNav, nil];

// 3.设置TabBarController的⼦子视图控制器数组

mainTabBarVC.viewControllers = viewControllers;

// 4.将根视图控制器设置成TabBarController

[self.window setRootViewController:mainTabBarVC]

程序的添加过程

UITabBarController创建完成后有一句关键代码

//将根视图控制器设置成TabBarController

[self.window setRootViewController:mainTabBarVC];

程序的添加过程:

UIWindow—>UITabBarcontroller—>UINavigationController—>UIViewController

UITabBar

•UITabBar包含多个UITabBarItem,每一个UITabBarItem对

应一个UIViewController。UITabBar的高度是49。

• 系统最多只显示5个UITabBarItem,当UITabBarItem超过5个时系统会自动增加一个更多按钮,点击更多按钮没有在

底部出现的按钮会以列表的形式显示出来

•UITabBar的属性:tintColor、barTintColor、图像设置

等。

UITabBarItem的图⽚片处理

代码:

//未选中的图片

UIImage *secondNormalImage = [UIImage

imageNamed:@“carGary”];

//图片不被渲染,保持图片本⾝身的样子

secondNormalImage = [secondNormalImage

imageWithRenderingMode:UIImageRenderingModeAlwaysO

riginal];

//选中时的图片

UIImage *secondSelectedImage = [UIImage

imageNamed:@"carRed"];

secondSelectedImage = [secondSelectedImage

imageWithRenderingMode:UIImageRenderingModeAlways

Original];

UIAppearance

代码:

//设置全局外观

//通过[UITabBar appearance]得到当前应用的UITabBar对象来设置tabBar的外观

//注意:设置全局外观最好在appDelegate里,否则会无效

[[UITabBar appearance] setBarTintColor:[UIColorcyanColor]];

[[UITabBar appearance] setTintColor:[UIColorbrownColor]];

//改变导航栏外观颜色

[[UINavigationBar appearance] setBarTintColor:[UIColor

lightGrayColor]];

//改变导航栏字体颜色

[[UINavigationBar appearance] setTitleTextAttributes:

[NSDictionary dictionaryWithObjectsAndKeys:[UIColor

redColor],NSForegroundColorAttributeName,[UIFontsystemFontOfSize:17],NSFontAttributeName, nil]];

总结

•UITabBarController是项目开发中常见的布局样式,与

UINavigationController不同,它的viewControllers都是并列

的;⽽而UINavigationController的则是层次性的。

•UITabBar通常都会定义外观以适应程序风格,必要时会完全自定义

第十节

UITableView

•UITableView继承于UIScrollView,可以滚动。

•UITableView的每一条数据对应的单元格叫做Cell,是UITableViewCell的一个对象,继承于UIView。

•UITableView可以分区显示, 每一个分区称为section,每一行称为row, 编号都从0开始。

• 系统提供了一个专门的类来整合section和row,叫做NSIndexPath。

UITableViewDataSource协议方法的实现代码

// tableView每个分区要显示的行数

- (NSInteger)tableView:(UITableView *)tableView

numberOfRowsInSection:(NSInteger)section{

return 100;

}

// tableView每次要显示一个cell都会调用这个方法获取

- (UITableViewCell *)tableView:(UITableView*)tableView

cellForRowAtIndexPath:(NSIndexPath *)indexPath{

UITableViewCell *cell = [[[UITableViewCell alloc]

initWithStyle:UITableViewCellStyleDefault

reuseIdentifier:@"reuse"] autorelease];

cell.textLabel.text = @"标题";

return cell;

}

UITableView重用cell的流程

•1.当一个cell被滑出屏幕,这个cell会被系统放到相应的重⽤用池中。

•2.当tableView需要显⽰示一个cell,会先去重⽤用池中尝试获取一个

cell(红色的cell)。

•3.如果重用池没有cell,就会创建一个cell(黄色的cell)。

•4.取得cell之后会重新赋值进行使用。

UITableView和数组

@interface ViewController ()

UITableViewDelegate>

//数组属性,用来和tableView结合使用

@property (nonatomic, retain) NSMutableArray*sourceArr;

@end

@implementation ViewController

- (void)viewDidLoad {

[super viewDidLoad];

//初始化数组

self.sourceArr = [NSMutableArray arrayWithObjects:

@"张三", @"李四", @"王五", @"赵六", nil];

}

总结

  1. UITableView的基本概念和创建方法

  2. UITableView的重用机制

3.常用的UITableView的协议方法的使用

第十一节

UITableView编辑步骤

UITableView编辑步骤如下:

一.让TableView处于编辑状态

二.协议设定

1.确定Cell是否处于编辑状态

2.设定Cell的编辑样式(删除、添加)

3.编辑状态进行提交

UITableView编辑步骤如下:

一.让TableView处于编辑状态

- (void)setEditing:(BOOL)editinganimated:(BOOL)animated

二.协议设定

1.确定Cell是否处于编辑状态

- (BOOL)tableView:(UITableView *)tableViewcanEditRowAtIndexPath:

(NSIndexPath *)indexPath

2.设定Cell的编辑样式(删除、添加)

- (UITableViewCellEditingStyle)tableView:(UITableView*)tableView

editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath

3.编辑状态进行提交

-(void) tableView:(UITableView *) tableViewcommitEditingStyle:

(UITableViewCellEditingStyle)editingStyleforRowAtIndexPath:

(NSIndexPath *)indexPath

UITableViewController

一:UITableViewController继承自UIViewController,自带

一个tableView

二:self.view不是UIView而是UITableView

三:datasource和delegate默认都是

self(UITableViewController)

四:开发中只需要建立UITableViewController子类

总结

1.UITableView编辑的写法

2.UITableViewController

第十二节

自定义Cell

为什么需要自定义Cell?

• 在前期我们学过自定义视图,即创建一个类继承于UIView

或者其他的视图,在自定义类中创建其子视图,这样就会

形成一个新的自定义视图。

• 系统提供的cell满足不了复杂的样式,因此:自定义Cell

和自定义视图⼀一样,自己创建一种符合我们需求的Cell并

使用这个Cell

⾃自定义Cell步骤:

• 创建⼀一个类继承于UITableViewCell。

• 实现UITableViewCell的初始化⽅方法:

-(instancetype)initWithStyle:(UITableViewCellStyle)style

reuseIdentifier:(NSString *)reuseIdentifier。

• 确保所有的你想添加的子视图都在自定义Cell的初始化方法中创建,由于UITableView的重用机制,一个Cell在第一次创建成功并用于下一次显示的时候,不会再走初始化方法,这样

可以避免子视图的重复创建。

• 在Cell的子视图创建成功后,将子视图设置为属性,类似于

UITableViewCell所自带的textLabel和detailTextLabel属性。便于在UITableView的协议中给自定义视图赋值。

Model的使用

创建步骤:

• 创建一个类并继承于NSObject

• 添加和字典中对应的属性

• 在视图控制器中将字典通过KVC为Model赋值

• 将Model对象添加到数组中并刷新TableView

判断多种Cell一

Model *model = [self.tableArray

objectAtIndex:indexPath.row];

//根据model属性划分

if (model.type == 0) {

FirstTableViewCell *cell = [tableView

dequeueReusableCellWithIdentifier:firstIdentify];

return cell;

}

if (model.type == 1) {

SecondTableViewCell *cell = [tableView

dequeueReusableCellWithIdentifier:secondIdentify];

return cell;

}

判断多种Cell二

//第一行显示第一种Cell

if (indexPath.row == 0) {

FirstTableViewCell *cell = [tableView

dequeueReusableCellWithIdentifier:firstIdentify];

return cell;

}

//第二行显示第二种Cell

if (indexPath.row == 1) {

SecondTableViewCell *cell = [tableView

dequeueReusableCellWithIdentifier:secondIdentify];

return cell;

}

图片自适应高度

UIImage *aImage = [UIImageimageNamed:@"1.png"];

//获得图片真实高度和宽度

CGFloat height = aImage.size.height;

CGFloat width = aImage.size.width;

//缩放后宽度固定为200

CGFloat scale = width / 200;

CGFloat realHeight = height / scale;

[self.myImageView setFrame:CGRectMake(0, 0,

200,realHeight)];

总结

• 自定义Cell

•Model类的创建和使用

• 多种Cell混合使用

•Cell的自适应高度

第十三节

视图控制器独有初始化方法:

- (instancetype)initWithNibName:(NSString*)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil

•nibNameOrNil:当前控制器相关联的nib文件,如果写nil默认为同名文件

•nibBundleOrNil:当前应用程序包所在文件,如果写nil默认为mainBundle

•在我们使⽤用init初始化(或者new直接创建)控制器的时候,会自动执行

控制器的此方法,参数均以默认值执行,所以可不写。

自动布局

自动布局:autoLayout,不给View固定的位置,通过某些规则让View自己适应自己的位置。

iOS6.0之后推出,在iOS8.0自动布局被大幅度优化,iOS9中新增了许多功能。

总结

1.xib可视化编程方式。

2.基础控件的属性操作以及与代码的关联方式。

3.自定义单元格的创建和使用。

4.自动布局的使用。

第十四节

StoryBoard注意事项

• 在AppDelegate的

-application: didFinishLaunchingWithOptions:

方法中不要再用代码初始化一个window。

• 将创建好的Storyboard在应⽤用程序配置General中设置为MainInterface。

• 视图添加与控制和IB开发一样。

利用StoryBoard绘制⾃自定义单元格

StoryBoard绘制单元格的时候要注意以下几点:

1.创建⾃自定义cell时选中左侧TableViewCell。

2.绘制自定义UI界⾯面。

3.设置重用标识符。

4.将StoryBoard文件关联至对应的UITableViewController和

UITableViewCell子类(自己创建的类)。

5.在UITableViewController中完成代码书写:设置section和row数量,

设置cell,根据实际情况调整cell的高度。

注意:cell不再需要注册。

StoryBoard进行页面跳转

StoryBoard页面跳转分为两种。

•1、代码方式:使用代码通过控制器标识来跳转。比如在当前页

面的某一个事件中跳转到一个标识为“customVC”的控制器页面

中:[self performSegueWithIdentifier:@"customVC"sender:nil];

•2、连线方式:直接使用拖拽可以给按钮连线关联两个页面:选中按钮,按住control,从按钮向下一级页面连线。按钮不需要添加响应方法。

自定义segue

•步骤一:新建一个类继承自UIStoryboardSegue。

•步骤二:选中前一个控制器,按住control鼠标辅助完成连线,选择custom。

•步骤三:选中自定义segue,设置segue的identifier以及关联类。

•步骤四:在segue类里面重写perform方法(界面间跳转默认执行的方法),自定义跳转效果。

@implementation CustomSegue

//页面跳转时,自定义segue会自动触发此方法(重写的系统方法)

-(void)perform

{

//获取源控制器

UIViewController *v1 = (UIViewController

*)self.sourceViewController;

//获取目标控制器

UIViewController *v2 = (UIViewController

*)self.destinationViewController;

//自定义页面切换效果

[UIView transitionFromView:v1.view toView:v2.viewduration:

10 options:UIViewAnimationOptionTransitionCurlDown

completion:^(BOOL finished) {

//动画完成后执行的部分

}];

}

sizeClasses

•设备对应关系如下:

•iPhone4S,iPhone5/5s,iPhone6,iPhone6s

• 竖屏:(w:Compact h:Regular)

• 横屏:(w:Compact h:Compact)

•iPhone6 Plus/iPhone6s Plus

• 竖屏:(w:Compact h:Regular)

• 横屏:(w:Regular h:Compact)

•iPad

• 竖屏:(w:Regular h:Regular)

• 横屏:(w:Regular h:Regular)

总结

1.StoryBoard与xib在可视化编程中的对比。

2.可视化编程中页⾯面传值的方式。

3.自定义segue实现页面跳转动画。

4.sizeClass适配。

第十五节

创建UICollectionViewFlowLayout

UICollectionViewFlowLayout *flowLayout =[[UICollectionViewFlowLayout alloc] init];

//设置每个item的大小

flowLayout.itemSize = CGSizeMake(100, 100);

//设置每个item的最小列间距(默认是10)

flowLayout.minimumInteritemSpacing = 10;

//设置每个item的最小行间距(默认是10)

flowLayout.minimumLineSpacing = 10;

//设置分区间隔 (上,左,下,右)

flowLayout.sectionInset = UIEdgeInsetsMake(10, 10, 10,10);

//设置UICollectionView的滑动方向

flowLayout.scrollDirection =UICollectionViewScrollDirectionVertical;

//头部引用的尺寸

flowLayout.headerReferenceSize = CGSizeMake(100, 100);

//尾部引⽤用的尺寸

flowLayout.footerReferenceSize = CGSizeMake(100, 100);

设置代理

遵守代理协议:

@interface ViewController()

UICollectionViewDelegate>

@end

@implementation ViewController

指定代理人:

collectionView.delegate = self;

collectionView.dataSource = self;

创建item视图对象

//创建item视图对象

-(UICollectionViewCell *)collectionView: (UICollectionView*)collectionView

cellForItemAtIndexPath:(NSIndexPath *)indexPath

{

UICollectionViewCell *cell = [collectionView

dequeueReusableCellWithReuseIdentifier:@"collectionCELL"forIndexPath:indexPath];

cell.backgroundColor = [UIColor redColor];

return cell;

}

返回头部、尾部视图样式

UICollectionView不能像UITableView一样直接指定头部和尾部视

图,需要注册使用,最大的好处是添加了重用机制。

//注册头部视图

[collectionView registerClass:[UICollectionReusableViewclass]

forSupplementaryViewOfKind:UICollectionElementKindSectionHeaderwithReuseIdentifier:@"headerView"];

//注册尾部视图

[collectionViewregisterClass:[UICollectionReusableView class]

forSupplementaryViewOfKind:UICollectionElementKindSectionFooterwithReuseIdentifier:@"footerView"];

第十六节

单例模式

• 单例模式是一种设计模式

• 实现: 定义一个单例类,保证程序中这个类只能创建唯

一的实例对象,实现资源共享

单例代码展示

static DataHandle *handle = nil;

//单例类使用此方法,创建单例对象

+ (DataHandle *)shareInstance

{

if (nil == handle) {

//如果还没有创建过对象,使用handle指向新创建的对象

handle = [[DataHandle alloc] init];

}

//如果已经创建过对象,则直接返回已经创建的对象

return handle;

}

注意事项

•1)操作单例对象的变量存储在静态区程序关闭后由系统自动

回收。

•2)单例对象存储在堆区,不需要释放程序,关闭后由系统自

动回收。

•3)变量和单例对象的生命周期与程序同步。

优势

•1)在内存中只有一个对象,节省内存空间

•2)避免频繁的创建销毁对象,可以提高性能

•3)避免对共享资源的多重占用

•4)可以全局访问

•5)降低模块之间的耦合度,降低代码的复杂度

框架设置

项目页面框架步骤:

1、根据项目的页面个数创建相同个数的视图控制器

2、根据项目的页面逻辑创建每个视图控制器上的切换方法

3、根据项目的页面功能创建每个视图控制器上的功能方法

版权声明:本文由大奖888-www.88pt88.com-大奖888官网登录发布于大奖888官网登录,转载请注明出处://给window钦赐根视图调控器,那样只要求三个Ce