zoukankan      html  css  js  c++  java
  • UIView---汇总

    视图、绘图、贴图、手势、变形、布局、动画、动力、特效
    UIBezierPath、UIGestureRecognizer、CGAffineTransform、frame、bounds、center、transform、UITouch、UIEvent、Layout、Autoresizing、Auto Layout、Animation、UIImage、NSTimer、UIView、Core Animation、CALayer、CAAnimation、CABasicAnimation、CAKeyframeAnimation、CAAnimationGroup、CATransform3D、UIDynamicAnimator、UIGravityBehavior、UICollisionBehavior、UIAttachmentBehavior、 UISnapBehavior、UIPushBehavior、NSNotification
    =========================================================================================================
    知识点
    一、绘图
    
    今天:
    
    1.绘图
    
        1.1基本概念
                屏幕:很多个晶体组成的,分辨率1920X1080,一行有1920个晶体,一共有1080行,每一个晶体发三种颜色的光(red,green,blue)
    
                图片:
                    点阵图:一堆点,每一个点是一个颜色,图片的分辨率指的就是存储的图片的点的个数
                    图片中的每一个点是用4个整数来存储的,这四个整数分别对象该点的red(0-255)、green(0-255),blue(0-255),alpha。一个点就需要4个字节来存储,依据这个规律就可以计算图片的大小了。但为了压缩图片的大小,将一个点周围的四个点计算一个平均值,用一个点的值来代替这四个点,
    
                矢量图:
                        存储的是生成图形所需要经过计算的数学公式,所以放大后不会失真
    
    
                像素
    
    2.OC对象与图形的转换
            内存中的OC对象,会基于系统提供的默认规则,绘制成平面图后显示到屏幕上。
            绘制的过程本质是由底层的Core Graphics 这一组C语言的API实现
            系统为编程人员提供了一个可编程的接口,在指定的位置添加绘制的代码以后,就可以让系统在原有的绘制基础上增加自定义的绘制内容
    
    3.绘图的实现
            [Demo1_Graphics]
            实现步骤:
                a。重写UIView的drawRect方法。该方法由系统自动调用,不能自己手动调用。因为drawRect方法只是系统一整套绘制流程中的一个环节。
                b。获取绘制的上下文对象
                c。设置上下文对象的绘制起始点
                d。添加路径
                e。设置描边或填充的颜色
                f。绘制路径
    
    MyView.h 继承自UIView
    
    MyView.m
    #import "MyView.h"
    
    @implementation MyView
    
    - (void)drawRect:(CGRect)rect
    {
        // 获取系统的上下文对象
        CGContextRef context = UIGraphicsGetCurrentContext();
        
        CGContextMoveToPoint(context, 40, 40);
        CGContextAddLineToPoint(context, 40, 140);
        CGContextAddLineToPoint(context, 140, 40);
        CGContextAddLineToPoint(context
                                , 40, 40);
        //设置描边的颜色
        CGContextSetStrokeColorWithColor(context
                                         , [[UIColor redColor] CGColor]);
        CGContextSetFillColorWithColor(context, [[UIColor greenColor]CGColor]);
        //按照路径描边
        //CGContextStrokePath(context);
        //CGContextFillPath(context);
        CGContextDrawPath(context, kCGPathFillStroke);
        
    }
    
    @end
    MyViewController.h
    MyViewController.m
    #import "MyViewController.h"
    #import "MyView.h"
    
    @interface MyViewController ()
    
    @end
    
    @implementation MyViewController
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        MyView *view = [[MyView alloc]initWithFrame:self.view.frame]; 将自定义的view加到controller
        view.backgroundColor = [UIColor whiteColor];
        [self.view addSubview:view];
    }
    
    4. UIBezierPath贝塞尔曲线
                4.1 是OC语言对c语言绘图的一部分API的封装结果
    
                4.2 作用:更方便的绘制直线、曲线、矩形、圆弧、椭圆等
    
                4.3 绘制直线
                【Demo2_BezierPath_Line】
        
                path.lineWidth 设置线条宽度
                path.lineCapStyle = kCGLineCapButt;设置线头儿的样式
                path.lineJoinStyle = kCGLineJoinRound;设置交叉点的样式
                                [[UIColor redColor] setStroke];设置线条颜色
                [[UIColor greenColor] setFill];设置填充色
    
          1)在故事板中拉入一个view,并在第三个检查器class与自己创建的类关联起来
          2)创建贝塞尔路径实例
         UIBezierPath *path = [UIBezierPath bezierPath];
      3)绘制,填充颜色、线条显示出来
        [path stroke]; [path fill];
    MyView.h
    MyView.m
    #import "MyView.h"
    
    @implementation MyView
    
    
    - (void)drawRect:(CGRect)rect
    {
        //创建贝塞尔路径的实例
        UIBezierPath *path = [UIBezierPath bezierPath];
        
        [path addArcWithCenter:CGPointMake(120, 120) radius:50 startAngle:M_PI_2 endAngle:M_PI clockwise:YES];
        [path addLineToPoint:CGPointMake(50, 50)];
        //移动到起始点
        //[path moveToPoint:CGPointMake(50, 50)];
        //[path addLineToPoint:CGPointMake(50, 150)];
        //[path addLineToPoint:CGPointMake(200, 50)];
        //[path addLineToPoint:CGPointMake(50, 50)];
        
        //设置颜色
        [[UIColor redColor] setStroke];
        [[UIColor greenColor] setFill];
        
        //设置path的常用属性
        path.lineWidth = 10;
        //设置线头儿的样式
        //path.lineCapStyle = kCGLineCapButt;
        //设置交叉点的样式
        //path.lineJoinStyle = kCGLineJoinRound;
        
        //绘制
        
        [path stroke];
        //[path fill];   
    }
                
    
                4.4绘制圆弧
                【Demo2_BezierPath_Line】
                             M_PI_2   M_PI
    [path addArcWithCenter:CGPointMake(120, 120) radius:50 startAngle:M_PI_2 endAngle:M_PI clockwise:YES];
    
                练习:
                定制圆形的下载进度提示条
             【Demo3_Custom_DownloadView】
              // 重绘视图
              [self setNeedsDisplay];
    
    DownloadView.h
    DownloadView.m
    #import "ViewController.h"
    #import "DownloadView.h"
    
    @interface ViewController ()
    @property (weak, nonatomic) IBOutlet DownloadView *downloadView;
    @property (weak, nonatomic) IBOutlet UISlider *slider;
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        self.slider.value = 0;
    }
    
    - (IBAction)downloadNumber:(UISlider *)sender {
        self.downloadView.progressValue = sender.value;
    }
    DownloadView.h
    #import <UIKit/UIKit.h>
    
    @interface DownloadView : UIView
    
    @property(nonatomic,strong)UIColor *progressColor;
    @property(nonatomic)CGFloat progressValue;//0~1之间的浮点数
    
    @end
    
    DownloadView.m
    #import "DownloadView.h"
    
    @implementation DownloadView
    
    //重写setter方法
    - (void)setProgressValue:(CGFloat)progressValue{
        // 保留原有的set方法的操作
        _progressValue = progressValue;
        // 重绘视图
        [self setNeedsDisplay];
    }
    
    
    - (void)drawRect:(CGRect)rect
    {
        UIBezierPath *path = [UIBezierPath bezierPath];
        //圆显示在屏幕中心
        CGPoint center = CGPointMake(self.bounds.size.width/2, self.bounds.size.height/2);
        [path addArcWithCenter:center radius  :(self.bounds.size.width-20)/2 startAngle:M_PI_2*3 endAngle:self.progressValue*2*M_PI+M_PI_2*3 clockwise:YES];
        if (self.progressColor) {//设置了即为设置后的颜色,如果没设置就显示默认的蓝色
            [self.progressColor setStroke];
        }else{
            [[UIColor blueColor] setStroke];
        }
        path.lineWidth = 8;
        [path stroke];
        
            
    }
    @end
       
                4.5绘制曲线
                【Demo4_BezierPath_Curve】
    MyView.h
    MyView.m
    #import "MyView.h"
    
    @implementation MyView
    
    
    - (void)drawRect:(CGRect)rect
    {
        UIBezierPath *path = [UIBezierPath bezierPath];
        [path moveToPoint:CGPointMake(140, 40)];
                                  起始坐标                                  第一个拉伸的点
        [path addCurveToPoint:CGPointMake(40, 180) controlPoint1:CGPointMake(40, 40) controlPoint2:CGPointMake(140, 180)];
        [path addCurveToPoint:CGPointMake(140, 320) controlPoint1:CGPointMake(140, 180) controlPoint2:CGPointMake(40, 320)];
        [[UIColor redColor] setStroke];
        path.lineWidth = 6;
        [path stroke];
    }
    
    
    @end4.6绘制其他图形 (矩形,圆形,椭圆)
                【Demo5_BezierPath_Others】
    MyView.h
    MyView.m
    #import "MyView.h"
    
    @implementation MyView
    
    - (void)drawRect:(CGRect)rect
    {
        //绘制圆角矩形
       // UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(40, 40, 200, 150) cornerRadius:10];
        //圆形
        UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(40, 40, 200, 200)];
        
        [[UIColor redColor] setStroke];
        [[UIColor greenColor] setFill];
        path.lineWidth = 8;
        [path fill];
        [path stroke];
        
        
    }
    
    @end
    
    5.绘制字符串
                【Demo6_Draw_String】
                使用NSString带有的绘制方法完成:
                drawAtPoint:
                drawInRect:
    
                根据字符串的内容计算对应的高度:
                boundingRectWithSize:
    MyView.h
    MyView.m
    #import "MyView.h"
    
    @implementation MyView
    
    - (void)drawRect:(CGRect)rect
    {
        NSString *str = @"Hello World";
        //设置字符串的格式
        NSDictionary *strAttributes =
      @{
        NSFontAttributeName:[UIFont systemFontOfSize:24],
        NSForegroundColorAttributeName:[UIColor redColor]
        };
        [str drawAtPoint:CGPointMake(40, 40) withAttributes:strAttributes];
        
        //长字符串的绘制
        NSString *str2 = @"looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooog String";
        //计算出该字符串所占的空间大小
        
        //计算字符串的高
        CGRect strRect = [str2 boundingRectWithSize:CGSizeMake(250, 999) options:2 attributes:strAttributes context:nil];
        
        [str2 drawInRect:CGRectMake(40, 80,250,strRect.size.height) withAttributes:strAttributes];
    }
    
    
    @end6.绘制图片
                【Demo7_Draw_Image】
        UIImage *image = [UIImage imageNamed:@"icon80.png"];
        [image drawAtPoint:CGPointMake(50, 50)];//按图片原始大小显示
        [image drawInRect:imageRect];//根据设定的范围对图片进行缩放
    MyView.h
    MyView.m
    #import "MyView.h"
    
    @implementation MyView
    
    
    - (void)drawRect:(CGRect)rect
    {
        
        CGRect imageRect = CGRectMake(50, 50, 200, 200);
        UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:imageRect];
        //按照路径剪切
        [path addClip];
        
        UIImage *image = [UIImage imageNamed:@"icon80.png"];
        //[image drawAtPoint:CGPointMake(50, 50)];
        [image drawInRect:imageRect];
    }
    
    @end
    
    作业:
    1.参考资源1,绘制聊天气泡
            写一个视图类:MessageView
                                                    +message:NSString
    
            要求:
                a。只做保持在视图右上角的情况
                b。最宽不能超过200,高度根据消息的内容来计算
    ViewController.h
    #import <UIKit/UIKit.h>
    
    @interface ViewController : UIViewController
    
    
    @end
    ViewController.m
    #import "ViewController.h"
    #import "TRMessageView.h"
    
    @interface ViewController ()
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        TRMessageView *view = [[TRMessageView alloc]initWithMessage:@"中文测试一下整体到了屏幕的右侧会是什么样子呢?"];
        view.frame = CGRectMake(0, 20, 320, view.height);
        [self.view addSubview:view];
        
        TRMessageView *view2 = [[TRMessageView alloc]initWithMessage:@"你来我往的对话中,为什么会有一条灰色的这么难看的横线显示在哪里呢?"];
        view2.frame = CGRectMake(0, 20+view.height, 320, view2.height);
        [self.view addSubview:view2];
        
    }
    @end
    
    TRMessageView.h
    #import <UIKit/UIKit.h>
    
    @interface TRMessageView : UIView
    
    @property(nonatomic,readonly)CGFloat height;
    -(instancetype)initWithMessage:(NSString *)message;
    
    @end
    TRMessageView.m
    #import "TRMessageView.h"
    
    @interface TRMessageView()
    @property(nonatomic,strong)NSString *message;
    @property(nonatomic)CGFloat messageWidth;
    @property(nonatomic)CGFloat messageHeight;
    @property(nonatomic,readwrite)CGFloat height;
    @end
    
    
    @implementation TRMessageView
    
    -(instancetype)initWithMessage:(NSString *)message{
        self = [super init];
        if (self) {
            self.message = message;
            CGRect msgRect = [self.message boundingRectWithSize:CGSizeMake(200, 999)
                                                        options:NSStringDrawingUsesLineFragmentOrigin
                                                     attributes:@{
                                                                  NSFontAttributeName:[UIFont systemFontOfSize:15]
                                                                  }
                                                        context:nil];
            self.messageWidth = msgRect.size.width;
            self.messageHeight = msgRect.size.height;
            self.height = 40+self.messageHeight;
            self.backgroundColor = [UIColor whiteColor];
        }
        return self;
    }
    
    
    - (void)drawRect:(CGRect)rect {
        CGContextRef context = UIGraphicsGetCurrentContext();
        CGContextSaveGState(context);
        
        //绘制气泡
        UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(280-self.messageWidth, 10, self.messageWidth+20, self.messageHeight+20) cornerRadius:10];
        [path moveToPoint:CGPointMake(300, self.messageHeight+20)];
        [path addLineToPoint:CGPointMake(310, 30+self.messageHeight)];
        [path addLineToPoint:CGPointMake(290, 30+self.messageHeight)];
        [[UIColor lightGrayColor] setFill];
        [path fill];
        
        CGContextRestoreGState(context);
        CGContextSaveGState(context);
        
        //绘制字符串
        [self.message drawInRect:CGRectMake(290-self.messageWidth, 20, self.messageWidth, self.messageHeight) withAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:15],NSForegroundColorAttributeName:[UIColor whiteColor]}];
    }
    
    @end2.绘制饼图
            写一个视图类:
                PieChartView
                    +radius:CGFloat半径
                    +width:CGFloat 线宽
                    +data:NSArray数据
                            +[item]: PieChartViewItem
    
            PieChartViewItem
                    +color:UIColor   颜色
                    +value:CGFloat  0~1   占总体的百分比
    TRPieChartViewItem.h
    #import <Foundation/Foundation.h>
    #import <UIKit/UIKit.h>
    
    @interface TRPieChartViewItem : NSObject
    
    @property(nonatomic,strong)UIColor *color;
    @property(nonatomic)CGFloat value;
    
    -(instancetype)initWithColor:(UIColor *)color andValue:(CGFloat)value;
    
    @end
    
    TRPieChartViewItem.m
    #import "TRPieChartViewItem.h"
    
    @implementation TRPieChartViewItem
    
    - (instancetype)initWithColor:(UIColor *)color andValue:(CGFloat)value{
        self = [super init];
        if (self) {
            self.color = color;
            self.value = value;
        }
        return  self;
    }
    
    @end
    TRPieChartView.h
    #import <UIKit/UIKit.h>
    
    @interface TRPieChartView : UIView
    
    @property(nonatomic)CGFloat radius;
    @property(nonatomic)CGFloat lineWidth;
    @property(nonatomic,strong)NSArray *data;
    
    @end
    
    TRPieChartView.m
    #import "TRPieChartView.h"
    #import "TRPieChartViewItem.h"
    
    @implementation TRPieChartView
    
    
    -(NSArray *)data{
        if (!_data) {
            TRPieChartViewItem *item1 = [[TRPieChartViewItem alloc]initWithColor:[UIColor redColor] andValue:0.25];
            TRPieChartViewItem *item2 = [[TRPieChartViewItem alloc]initWithColor:[UIColor blueColor] andValue:0.5];
            TRPieChartViewItem *item3 = [[TRPieChartViewItem alloc]initWithColor:[UIColor blackColor] andValue:0.15];
            TRPieChartViewItem *item4 = [[TRPieChartViewItem alloc]initWithColor:[UIColor greenColor] andValue:0.1];
       
            _data = @[item1,item2,item3,item4];
        }
        return _data;
    }
    
    -(CGFloat)lineWidth{
        if (!_lineWidth) {
            _lineWidth = 10;
        }
        return _lineWidth;
    }
    
    -(CGFloat)radius{
        if (!_radius) {
            _radius = 100;
        }
        return _radius;
    }
    
    - (void)drawRect:(CGRect)rect {
        CGFloat startAngel = M_PI_2*3;
        for (TRPieChartViewItem *item in self.data) {
            CGContextRef context = UIGraphicsGetCurrentContext();
            CGContextSaveGState(context);
            UIBezierPath *path = [UIBezierPath bezierPath];
            // 画弧线
            [path addArcWithCenter:CGPointMake(self.frame.size.width/2, self.frame.size.height/2) radius:self.radius startAngle:startAngel endAngle:(item.value*2*M_PI+startAngel) clockwise:YES];
            startAngel +=item.value*2*M_PI;
            //画直线
            [path addLineToPoint:CGPointMake(self.frame.size.width/2, self.frame.size.height/2)];
            //线宽
            path.lineWidth = self.lineWidth;
            path.lineCapStyle = kCGLineCapButt;
            //填充色
            [item.color setFill];
            //线条颜色
            //[[UIColor grayColor] setStroke];
            //绘制填充边线
            [path fill];
            //[path stroke];
            CGContextRestoreGState(context);
            CGContextSaveGState(context);
        }
    }
    
    
    @end3.自定义Cell,图片是圆角的
             新闻客户端中的自定义Cell,里面的图片做成圆角的
    ===============================================================
    知识点
    二、贴图、美化
    
    1.  iOS的设备的种类
        1.1设备的分辨率和坐标系大小(2倍关系)
    
        1.2Retina屏设备对图片的处理
                a。程序中的图片:在不同尺寸的图片名称上添加@2x 或 @3x这样的标识即可。系统会根据当前设备的不同,来选择加载哪个版本的图片
                b。AppIcon应用程序图标:屏幕上有一个尺寸,设置界面上也有图标,搜索结果中也有图标,设定图片资源库中的AppIcon里面不同尺寸的图片后,完成设置
    
    2、9切片技术
        2.1 为什么需要9切片(9 Slice技术)
                 用代码来实现基于一个简单图片,产生不同尺寸的图片的一种手段
        
        2.2切片原则
                4个角不变,中间部分可以横向或纵向拉伸或复制
                两种模式:Tile 切片复制 (默认模式)
                             Stretch切片拉伸
    
        2.3 实现方法
                a。利用xcode工具中的图片资源库中的9切片功能
                b。编写代码实现切片
    
       如:
    #import "ViewController.h"
    
    @interface ViewController ()
    @property (weak, nonatomic) IBOutlet UIImageView *btnImageView; 和故事版中的image连线
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        UIImage *btnImage = [[UIImage imageNamed:@"delete_btn"] resizableImageWithCapInsets:UIEdgeInsetsMake(9, 12, 9, 12) resizingMode:UIImageResizingModeStretch]; 编代码实现九切片功能
        self.btnImageView.image = btnImage;
        
    }
    
    @end
    
    3. 对控件的贴图美化
        
        3.1 UIButton
            四种状态的设置:通过代码或故事板
            四种状态的切换:
                    Normal:正常
                    Highlighted:高亮,按下后不抬起的状态
                    Selected:通过修改selected属性设置 .selected=YES(按钮被选中)
    
                    Disabled:通过修改enabled属性设置 .enabled=NO(按钮不可用状态)
    
    - (IBAction)changeState:(UIButton *)sender { 将按钮连线,用代码修改
        [self.button setSelected:!sender.selected];//连续点击,持续变化
      //  [sender setSelected:YES];//是否改变,只变化一次
        //sender setEnabled:YES
        // 按钮摆在那不动:normal
        // 点下,不抬起:highLighted
        // 点下,松手:normal
        // 进入到seleted状态:用代码修改seleted属性
        // enabled状态:用代码改
    }
    
    
    如下:view+image+button+field,通过故事板实现即可,不需要编程
    
        3.2 UISlider
         setMaximumTrackImage:设置滑动过的区域的背景图
     setMinimumTrackImage:设置未滑动到的区域的背景图
     setThumbImage:设置滑块中拖动按钮部分的图片
    如:
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        [self.slider setMaximumTrackImage:[[UIImage imageNamed:@"playing_volumn_slide_foreground"] resizableImageWithCapInsets:UIEdgeInsetsMake(4, 4, 4, 4) resizingMode:UIImageResizingModeTile]forState:UIControlStateNormal];
        [self.slider setMinimumTrackImage:[UIImage imageNamed:@"playing_volumn_slide_bg"] forState:UIControlStateNormal];
        [self.slider setThumbImage:[UIImage imageNamed:@"playing_volumn_slide_sound_icon"] forState:UIControlStateNormal];
    }
    
    4. tintColor
            统一管理一个视图中所有子视图和子视图的子视图的颜色,批量修改一些视图的颜色
         1.颜色受控制的因素
     拥有 xxxTintColor属性,如UISwitch,可以使用属性修改
     没有xxxTintColor,受从UIView中继承来的tintColor影响
         2.self.window.tintColor影响整个应用的风格,除非某一个视图特别设置了自己的tintColor颜色
    
    5. UIAppearance
            遵守此协议的对象,可以批量设置某种控件的外观(颜色、贴图等)(只针对某一类控件)
       1.获取方式
     +(instancetype)appearance;
       2.使用方式
     拿到此对象后,通过这个对象设置背景、颜色等来批量设置某一类控件的外观
    [ [ UISlider appearance] setTintColor: [ UIColor redColor ] ]
    如:
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
        [[UISlider appearance]setTintColor:[UIColor purpleColor]];
        [[UIButton appearance]setBackgroundImage:[UIImage imageNamed:@"delete_btn"] forState:UIControlStateNormal];
       
        return YES;
    }
    
    
    6. UINavigationBar美化
    
        6.1 设置NavigationBar的颜色
    
                //设置导航栏的背景色
                naviBar.barTintColor = [UIColor blackColor];
                //设置是否透明
            naviBar.translucent = YES;
            
    
    
        6.2 给NavigationBar贴图
            //设置背景图(图片的高度,竖屏时一般设置为64个点,横屏时高度是52个点)
        [naviBar setBackgroundImage:[UIImage imageNamed:@"NavigationBarDefault"] forBarMetrics:UIBarMetricsDefault];竖屏显示
        [naviBar setBackgroundImage:[UIImage imageNamed:@"NavigationBarLandscapePhone"] forBarMetrics:UIBarMetricsLandscapePhone];横屏显示
    
    
        6.3 设置返回按钮的图片
            naviBar.backIndicatorImage = [UIImage imageNamed:@"back_btn"];
        naviBar.backIndicatorTransitionMaskImage =[UIImage imageNamed:@"back_btn"];
        naviBar.tintColor = [UIColor redColor];设置按钮颜色
    
        6.4 设置标题栏的文字字体
            naviBar.titleTextAttributes =
          @{
            NSFontAttributeName:[UIFont boldSystemFontOfSize:24],
           NSForegroundColorAttributeName:[UIColor redColor]
            };
    
    
        6.5 设置标题为任意视图
            UIStepper *stepper = [[UIStepper alloc]init];
        self.navigationItem.titleView = stepper;
    
        6.6 设置状态栏风格 (显示电池栏的风格)
        //重写方法,用于设置状态的风格
    - (UIStatusBarStyle)preferredStatusBarStyle
    {
        return UIStatusBarStyleLightContent;
    }
    
        6.7 是否显示状态栏
            //重写方法,设置状态栏隐藏
    - (BOOL)prefersStatusBarHidden
    {
        return YES;
    }
    
        6.8 隐藏NavigationBar
         [self.navigationController setNavigationBarHidden:!self.navigationController.navigationBarHidden animated:YES];
    
    ViewController.h
    ViewController.m
    #import "ViewController.h"
    
    @interface ViewController ()
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        UINavigationBar *naviBar = self.navigationController.navigationBar;
        naviBar.barTintColor = [UIColor blackColor];
        naviBar.translucent = YES;
        //设置背景图
        [naviBar setBackgroundImage:[UIImage imageNamed:@"NavigationBarDefault"] forBarMetrics:UIBarMetricsDefault];
        [naviBar setBackgroundImage:[UIImage imageNamed:@"NavigationBarLandscapePhone"] forBarMetrics:UIBarMetricsLandscapePhone];
        //设置返回按钮的的图片
        naviBar.backIndicatorImage = [UIImage imageNamed:@"back_btn"];
        naviBar.backIndicatorTransitionMaskImage =[UIImage imageNamed:@"back_btn"];
        naviBar.tintColor = [UIColor redColor];
        //设置标题栏的文字字体
        naviBar.titleTextAttributes =
      @{
        NSFontAttributeName:[UIFont boldSystemFontOfSize:24],
       NSForegroundColorAttributeName:[UIColor redColor]
        };
        //设置标题为其他视图
        //UITextField *textField = [[UITextField alloc]init];
        UIStepper *stepper = [[UIStepper alloc]init];
        self.navigationItem.titleView = stepper;
    }
    
    - (IBAction)hideNavigationBar:(UIButton *)sender {
        [self.navigationController setNavigationBarHidden:!self.navigationController.navigationBarHidden animated:YES];
        
    }
    
    @end
    GreenViewController.h
    GreenViewController.m
    #import "GreenViewController.h"
    
    @interface GreenViewController ()
    
    @end
    
    @implementation GreenViewController
    
    
    
    //重写方法,用于设置状态的风格
    - (UIStatusBarStyle)preferredStatusBarStyle
    {
        return UIStatusBarStyleLightContent;
    }
    
    //重写方法,设置状态栏隐藏
    - (BOOL)prefersStatusBarHidden
    {
        return YES;
    }
    
                 
                                                         点击item得到的界面
    
    7. UITableViewCell的背景贴图
    
        实现步骤:
        a。故事板中修改TableView的分割线(Separator)为None
        b。故事板中修改TableViewCell的背景色(Background)为clearColor
        c。cell.backgroundView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"list"]];
        cell.selectedBackgroundView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"listSeleted”]];选中后的背景图设置显示
    如:
    MyTableViewController.h
    MyTableViewController.m
    #import "MyTableViewController.h"
    
    @interface MyTableViewController ()
    
    @end
    
    @implementation MyTableViewController
    
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        
    }
    
    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
    {
        return 1;
    }
    
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
    {
        return 10;
    }
    
    
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
        cell.textLabel.text = @"Hello World";
        cell.backgroundView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"list"]];
        cell.selectedBackgroundView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"listSelected"]];
        return cell;
    }
     格显示的是虚线
    
    作业:
    
    聊天气泡:
    用9slicing实现
    
    类:MessageView
        +message:NSString
        +fromMe:BOOL
        +messageLabel:UILabel
        +messagePopImageView:UIImageView//图,切片
        
    效果:
        a。屏幕最上方添加一个文本框和一个发送按钮
        b。屏幕下方已经存在一些聊天的消息,其中自己说的内容在屏幕右侧,对方说的内容在屏幕的左侧
        c。在文本框中输入内容后,算作自己说的内容,然后点击发送按钮,在界面中追加一个气泡,在屏幕的右侧,里面显示文本框中输入的内容,并且键盘收起,文本框内容清空
    
    -(void)refresh{
        if(fromMe)
            显示蓝色的气泡在右上角
            大小根据message属性计算
        else
            显示灰色的气泡在左上角
            大小,计算
    }
    参考:H02资源包
    
    
    追加:看Apple官方的NavigationBar的demo
    =====================================================================
    知识点
    三、手势(UIGestureRecognizer)、变形
    1.手势(GestureRecognizer)
    
        1.1什么是手势
            用户在view上的一些触屏操作,诸如 点、滑动、捏合。。。
    
        1.2 手势的分类
            a。一次性手势
                    触屏动作发生以后,方法只会响应一次。如:点击以下屏幕、解锁动作
    
            b。连续性手势
                    触屏动作发生以后,方法会连续响应多次。如:长按、捏合、移动、旋转
    
        1.3 手势的本质
                本质是一个对象,当用户针对视图发生了一定的动作之后,系统会检测到该动作,并根据具体的动作创建不同种类的手势对象,该对象中会存储与动作有关的一些数据,如触屏动作的坐标点、滑动的快慢、移动的距离。
                如果发生的是一次性手势动作,那么就调用一次方法,如果发生的是连续性手势动作,那么就多次调用响应方法
    
        1.4 如何使用手势
                step1:创建手势对象
                step2:设置与该种手势相关的属性
                step3:将手势对象与需要检测的视图关联在一起
    
        1.5 具体的手势种类
                所有手势的父类:UIGestureRecognizer
                6种手势: UIXXXGestureRecognizer
                UITapGestureRecognizer    点击一下屏幕
                UISwipeGestureRecognizer  轻扫屏幕,如解锁
                UIPinchGestureRecognizer   捏合手势
                UIPanGestureRecognizer  移动手势
                UILongPressGestureRecognizer 长按手势
                UIRotationGestureRecognizer  旋转手势
                
    2.具体的手势使用
            
        2.1 UITapGestureRecognizer (一次性手势)
           【Demo1_TapGestureRecognizer】         常用属性:
                .numberOfTapsRequired 设置点击数    手指点几下
                .numberOfTouchesRequired 设置触点数  几个手指点击
                CGPoint location=[gr locationInView:self.view];获取点击动作时,出点的绝对坐标
    ViewController.m
    #import "ViewController.h"
    
    @interface ViewController ()
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        //step1 创建手势对象
        UITapGestureRecognizer *tapGR = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tap:)];
        //step2 设置手势的属性
        tapGR.numberOfTapsRequired = 1;
        tapGR.numberOfTouchesRequired = 1;
        //step3 将手势与视图关联起来
        [self.view addGestureRecognizer:tapGR];
        
    }
    
    -(void)tap:(UITapGestureRecognizer *)gr
    {
        CGPoint location = [gr locationInView:self.view];
        NSLog(@"(%.2f,%.2f)",location.x,location.y);
    }
    
    @end
    
        2.2 UISwipeGestureRecognizer(一次性手势)
                【Demo2_SwipeGestureRecognizer】
                常用属性:
                    .numberOfTouchesRequired触点的个数
                    .direction 轻扫的方向
            注意:direction属性为枚举值,并且是可以进行组合的枚举值,多个枚举值之间使用 “|”按位“或”进行运算。
                补充:1<<?    表达式的含义是:对于二进制的数字1进行向左移位,符号右侧是几,就向左移动几位。
    
    ViewController.m
    #import "ViewController.h"
    
    @interface ViewController ()
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        UISwipeGestureRecognizer *swipeGR = [[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(swipe:)];
        swipeGR.numberOfTouchesRequired = 1;
        //设置轻扫动作的方向
        swipeGR.direction = UISwipeGestureRecognizerDirectionLeft|UISwipeGestureRecognizerDirectionRight;
        [self.view addGestureRecognizer:swipeGR];
    }
    
    -(void)swipe:(UISwipeGestureRecognizer *)gr{
        NSLog(@"swipe... ...");
    }
    @end
    
        2.3 UILongPressGestureRecognizer(连续性手势)
                【Demo3_LongPressGestureRecognizer】
              常用属性:    
        longGR.minimumPressDuration = 1;//设置最少按下的持续时间
    
    ViewController.m
    #import "ViewController.h"
    
    @interface ViewController ()
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        UILongPressGestureRecognizer *longGR = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(longPress:)];
        //设置最少按下的持续时间
        longGR.minimumPressDuration = 1;
        [self.view addGestureRecognizer:longGR];
    }
    
    -(void)longPress:(UILongPressGestureRecognizer *)gr{
        NSLog(@"long press... ...");
    }
    
    
    @end
    
        2.4 UIPinchGestureRecognizer(连续性手势,捏合)
                【Demo4_PinchGestureRecognizer】
            CGFloat scale = gr.scale; //手势的变化比率,向外扩展时,为大于1的数,向内捏合时,为小与1的数
       CGFloat velocity = gr.velocity;//手势的变化速率,向外扩展时,为正数,向内捏合时,为负数
        
        以上两个属性不是用来设置的,而是在手势发生时用来读取的。
    
        练习:    
                界面上 有一个UITextView,看小说,增加手势识别,如果快速扩,小说出现,快速捏,小说隐藏,速度不快时,代表放大或缩小小说的文字大
    ViewController.m
    #import "ViewController.h"
    
    @interface ViewController ()
    @property (weak, nonatomic) IBOutlet UITextView *textView;//连线
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        self.textView.editable = NO;
        UIPinchGestureRecognizer *pinchGR = [[UIPinchGestureRecognizer alloc]initWithTarget:self action:@selector(pinch:)];
        [self.view addGestureRecognizer:pinchGR];
    }
    
    -(void)pinch:(UIPinchGestureRecognizer *)gr{
        CGFloat scale = gr.scale;比率
        CGFloat velocity = gr.velocity; 速率
        //NSLog(@"scale=%.2f,velocity=%.2f",scale,velocity);
        if (velocity > 6) {
            self.textView.hidden = NO;
        } else if (velocity < -6){
            self.textView.hidden = YES;
        } else{
          //  改变字体
            self.textView.font = [UIFont systemFontOfSize:17*scale];
        }
    }
    
    
    
        2.5 UIRotationGestureRecognizer (连续性手势,旋转)
                【Demo5_RotationGestureRecognizer】
                 常用属性:
                    CGFloat rotation = gr.rotation;
                    代表手势旋转的弧度。顺时针旋转时,为正数,逆时针旋转时为负数
    ViewController.m
    #import "ViewController.h"
    
    @interface ViewController ()
    @property (weak, nonatomic) IBOutlet UIImageView *imageView;//image上添加图片
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        UIRotationGestureRecognizer *rotationGR = [[UIRotationGestureRecognizer alloc]initWithTarget:self action:@selector(rotation:)];
        [self.view addGestureRecognizer:rotationGR];
    }
    
    -(void)rotation:(UIRotationGestureRecognizer *)gr{
        //CGFloat rotation = gr.rotation;
        //NSLog(@"%.2f",rotation);
        //实现图片的选转
        self.imageView.transform = CGAffineTransformMakeRotation(gr.rotation);
    }
    
    @end
        
        2.6 UIPanGestureRecognizer(连续性手势,拖动)
                【Demo6_PanGestureRecognizer】
                常用属性:
                //获取移动到的位置在视图坐标系中的绝对位置
        CGPoint location = [gr locationInView:self.view];
        //获取移动到的新位置相对于移动动作起始点的坐标的横纵向的偏移
        CGPoint translation = [gr translationInView:self.view];
    
    ViewController.m
    #import "ViewController.h"
    
    @interface ViewController ()
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        UIPanGestureRecognizer  *panGR = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(pan:)];
        [self.view addGestureRecognizer:panGR];
    }
    
    -(void)pan:(UIPanGestureRecognizer *)gr{
        //获取移动到的位置在视图坐标系中的绝对位置
        CGPoint location = [gr locationInView:self.view];
        //获取移动到的新位置相对于移动动作起始点的坐标的横纵向的偏移
        CGPoint translation = [gr translationInView:self.view];
        self.myImageView.transform=CGAffineTransformMakeTranslation(translation.x, translation.y);//相对
        NSLog(@"location:(%.2f,%.2f) translation:(%.2f,%.2f)",location.x,location.y,translation.x,translation.y);
    }
    @end
    
    3.变形(Transform)
         3.1什么是变形
                      视图发生了位移、缩放、旋转这样的变化叫做变形。
    
        3.2 如何实现变形?
                通过修改视图对象的.transform属性完成变化的效果
                位移:translation
                缩放:scale
                旋转:rotation
    
        3.3 transform属性
                类型:CGAffineTransform(仿射)类型的结构体
                结构体中包含了6个可变的值和3个定值组成的 3 X 3的矩阵,修改了6个数据中的某一个或某几个就可以实现变形,实际上这6个数很难计算,借助于一些系统的API实现数值的改变。
    
        3.4 修改transform属性的API
    
                位移变换:CGAffineTransformMakeTranslation()     相对最原始变化的
                                         CGAffineTransformTranslate()     相对修改后变化的
    
                缩放变换:CGAffineTransformMakeScale()
                                         CGAffineTransformScale()
    
    
                旋转变换:CGAffineTransformMakeRotation()
                                         CGAffineTransformRotate()
    
            回到原始状态: CGAffineTransformIdentity
    
        重点注意:变形与自动布局是冲突的,所以在使用变形时,一定要关闭AutoLayout,不关闭的话,产生的效果无法预计。
    
            【Demo7_Transform】
    
           界面创建后,没有做任何变形之前,系统会将每一个视图当前的transform记录到一个常量中CGAffineTransformIdentity,当使用Makexxx()方法进行仿射变换,计算新的矩阵,都是基于这个常量进行变形计算的。当使用没有Make的那组方法时,每次计算新的矩阵都是以传入的transform的值作为基准。
    
        3.5 transform属性的初始常量
                CGAffineTransformIdentity
    
    如:通过点击按钮实现图片变化
    ViewController.m
    #import "ViewController.h"
    
    @interface ViewController ()
    @property (weak, nonatomic) IBOutlet UIImageView *imageView;
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        
    }
    //位移
    - (IBAction)translation:(UIButton *)sender {
        //self.imageView.transform = CGAffineTransformMakeTranslation(0, 350);
        self.imageView.transform = CGAffineTransformTranslate(self.imageView.transform, 3, 3);
        //self.imageView.center = CGPointMake(self.imageView.center.x+2, self.imageView.center.y+2);
    }
    
    
    //缩放
    - (IBAction)scale:(UIButton *)sender {
        //self.imageView.transform = CGAffineTransformMakeScale(1.5, 1.5);
        self.imageView.transform = CGAffineTransformScale(self.imageView.transform, 1.2, 1.2);
    }
    
    //旋转
    - (IBAction)rotation:(UIButton *)sender {
        //self.imageView.transform = CGAffineTransformMakeRotation(M_PI_4);
        self.imageView.transform = CGAffineTransformRotate(self.imageView.transform, -M_PI_4);
    }
    //回到原始位置
    - (IBAction)identity:(UIButton *)sender {
        self.imageView.transform = CGAffineTransformIdentity;
    }
    
    
    @end4.手势+变形
             
        4.1 使用pan手势实现位移
            CGPoint translation = [gr translationInView:self.view];
        CGPoint center = CGPointMake(self.imageView.center.x+translation.x, self.imageView.center.y+translation.y);
        self.imageView.center = center;
        //将这一次移动的偏移量归零
        [gr setTranslation:CGPointZero inView:self.view];
    
        4.2 使用pinch手势实现缩放变形
           // 实现图片的缩放
         self.imageView.transform = CGAffineTransformScale(self.imageView.transform,gr.scale, gr.scale);
         gr.scale = 1;//
    
    
        4.3 使用rotation手势实现旋转变形            // 实现图片的旋转
        self.imageView.transform = CGAffineTransformRotate(self.imageView.transform, gr.rotation);
        gr.rotation = 0;
                           
        4.4 多手势共存的问题
                解决步骤:
                       a。遵守协议
                b。设置各个手势的代理
                c。实现一个方法 (遵守协议时点开发放寻找粘贴过来即可)
                        - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
        return YES;
    }
    
    5.在storyboard中实现手势
            【Demo8_GestureRecognizer_Storyboard】
          1.从资源库中拖拽某种类型的手势对象到视图中
          2.如果拖拽时就想与某视图关联起来,那么就把手势对象拖到视图中,如果不想关联,那么就拖拽到场景的资源条上 
          3.选中要关联的视图,按住control,连线到场景的资源条上的手势对象
          4.
    TransformViewController.m
    #import "TransformViewController.h"
    
    @interface TransformViewController ()<UIGestureRecognizerDelegate> //遵守协议
    @property (weak, nonatomic) IBOutlet UIImageView *imageView;
    
    @end
    
    @implementation TransformViewController
    
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        //pan手势
        UIPanGestureRecognizer *panGR = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(pan:)];
        [self.view addGestureRecognizer:panGR];
        //pinch手势
        UIPinchGestureRecognizer *pinchGR = [[UIPinchGestureRecognizer alloc]initWithTarget:self action:@selector(pinch:)];
        //设置pinch的代理
        pinchGR.delegate = self;
        [self.view addGestureRecognizer:pinchGR];
        //rotation手势
        UIRotationGestureRecognizer *rotationGR = [[ UIRotationGestureRecognizer alloc]initWithTarget:self action:@selector(rotation:)];
        //设置rotation的代理
        rotationGR.delegate = self;
        [self.view addGestureRecognizer:rotationGR];
    }
    
    -(void)pan:(UIPanGestureRecognizer *)gr{
        //实现图片的位移
        //CGPoint location = [gr locationInView:self.view];
        CGPoint translation = [gr translationInView:self.view];
        CGPoint center = CGPointMake(self.imageView.center.x+translation.x, self.imageView.center.y+translation.y);
        self.imageView.center = center;
        //将这一次移动的偏移量归零
        [gr setTranslation:CGPointZero inView:self.view];
    }
    
    -(void)pinch:(UIPinchGestureRecognizer *)gr{
        // 实现图片的缩放
        self.imageView.transform = CGAffineTransformScale(self.imageView.transform,gr.scale, gr.scale);
        gr.scale = 1;
    }
    
    -(void)rotation:(UIRotationGestureRecognizer *)gr{
        // 实现图片的旋转
        self.imageView.transform = CGAffineTransformRotate(self.imageView.transform, gr.rotation);
        gr.rotation = 0;
    }
    
    - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
        return YES;
    }
    
    @end
    
    
    
    【综合练习】:
    图片查看器:
    1)使用代码想view中添加一个UIImageView对象,UIImageView的大小和图片大小一致,找一张大图(用大象)
    
    2)使用center属性将ImageView移动到屏幕的中央
    3)使用transform属性将imageView缩放到屏幕刚好能显示的下正常图片的内容,且保持宽高比
    4)对imageView增加rotation手势,支持图片旋转
    5)对imageView增加pinch手势,支持图片的缩放
    6)对imageView增加pan手势,支持图片的移动
    7)对imageView增加tap手势,床架回到到第3步
    注意:手势不要添加到self.view,要添加到图片上,记得打开imageView的用户交互(.userInteractionEnable=YES)
    
    作业:
    ViewController.m
    
    #import "ViewController.h"
    
    @interface ViewController ()<UIGestureRecognizerDelegate>//遵守协议
    
    @property(nonatomic,strong)UIImageView *imageView;
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        //创建ImageView
        UIImageView *imageView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"Elephant.jpg"]];
        self.imageView = imageView;
        //设置初始的状态
        [self loadImageView];
        //添加
        [self.view addSubview:imageView];
        //开启交互
        imageView.userInteractionEnabled = YES;
        
        //设置手势
        UITapGestureRecognizer *tapGR = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tap:)];
        tapGR.numberOfTapsRequired = 2;
        [self.imageView addGestureRecognizer:tapGR];
        
        UIPinchGestureRecognizer *pinchGR = [[UIPinchGestureRecognizer alloc]initWithTarget:self action:@selector(pinch:)];
        pinchGR.delegate = self;
        [self.imageView addGestureRecognizer:pinchGR];
        
        UIPanGestureRecognizer *panGR = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(pan:)];
        [self.imageView addGestureRecognizer:panGR];
        
        UIRotationGestureRecognizer *rotationGR = [[UIRotationGestureRecognizer alloc]initWithTarget:self action:@selector(rotation:)];
        rotationGR.delegate =self;
        [self.imageView addGestureRecognizer:rotationGR];
    }
    
    -(void)loadImageView{
        //设置中心点
        self.imageView.center = self.view.center;
        CGFloat scaleX = self.view.bounds.size.width/self.imageView.bounds.size.width;
        CGFloat scaleY = self.view.bounds.size.height/self.imageView.bounds.size.width;
        self.imageView.transform = CGAffineTransformMakeScale(MIN(scaleX, scaleY), MIN(scaleX, scaleY));
    }
    //移动
    -(void)pan:(UIPanGestureRecognizer *)panGR{
        CGPoint translation = [panGR translationInView:self.view];
        CGPoint center = CGPointMake(self.imageView.center.x+translation.x, self.imageView.center.y+translation.y);
        self.imageView.center = center;
        [panGR setTranslation:CGPointZero inView:self.view];
    
    }
    
    //缩放
    -(void)pinch:(UIPinchGestureRecognizer *)pinchGR{
        self.imageView.transform = CGAffineTransformScale(self.imageView.transform, pinchGR.scale, pinchGR.scale);
        pinchGR.scale = 1;
        
    }
    
    //旋转
    -(void)rotation:(UIRotationGestureRecognizer *)rotationGR{
        self.imageView.transform = CGAffineTransformRotate(self.imageView.transform, rotationGR.rotation);
        rotationGR.rotation = 0;
    }
    
    //回到起始点中心点
    -(void)tap:(UITapGestureRecognizer *)gr{
        [self loadImageView];
    }
    
    //实现旋转和缩放同时实现的方法
    - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
        return YES;
    }
    
    @end
    
    
    www.raywenderlich.com
    
    2.根据文档,把一个TableCell实现移动。
    长按Cell后,拖到哪里就放在哪里
    ====================================================================
    知识点
     五、坐标系、触控
    
    1.坐标系(frame、bounds、center、transform)
         1.1  frame属性
    
            【Demo1_Frame_Bounds_Center_Transform】
    
            a。什么是frame?
                    类型:CGRect结构体类型
                    作用:该视图左顶点在父视图的坐标系中的位置,以及,该视图在父视图中占据的宽和高
            
            b。直接修改了frame属性时,其他属性如何变化?
                    bounds:会被改变
                    center:会被改变
                    transform:不会被改变
    
            c。什么时候使用到frame?
                    当把一个视图添加到父视图中时,一定要重设定frame属性
    
        1.2  bounds属性 (相对与自己的)
                
            a。什么是bounds属性?
                    类型:CGRect结构体类型
                    作用:描述的是该视图的坐标系顶点的值,以及该视图自身的大小
    
            b。直接修改了bounds属性时,其他属性如何变化?
                    frame: 会被改变
                    center:不会被改变
                    transform:不会被改变
    
            c。什么时候使用bounds属性?
                    当需要定位视图时,要读取父视图的大小,那么就是用父视图的bounds
                    当修改视图内的子视图的位置时,可以修改视图的bounds的坐标起点,从而让子视图的位置发生偏移,实现移动的效果
    #import "OtherViewController.h"
    
    @interface OtherViewController ()
    
    @end
    
    @implementation OtherViewController
    
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        UIView *view1=[[UIView alloc]initWithFrame:CGRectMake(100, 200, 80, 100)];
        view1.backgroundColor=[UIColor redColor];
        [self.view addSubview:view1];
        
    }
    - (IBAction)button:(UIButton *)sender {
        [self.view setBounds:CGRectMake(self.view.bounds.origin.x, self.view.bounds.origin.y+10, self.view.bounds.size.width, self.view.bounds.size.height)];
    }
    
    @end
    点击按钮,图片垂直向上移动
            
        1.3  center属性
            
            a。什么是center属性?
                    类型:CGPoint结构体类型
                    作用:描述的是该视图的中心点,在父视图坐标中的位置
    
            b。直接修改了center属性时,其他属性如何变化?
                    frame:会被改变
                    bounds:不会被改变
                    transform:不会被改变
    
            c。什么时候用center?
                    需要修改视图的位置,也就是位移时,需要修改center
    
        1.4 transform属性
    
            a。什么是transform属性?
                    类型:CGAffineTransform结构体类型
                    作用:描述该视图的变形状态
    
            b。直接修改了transform属性时,其他属性如何变化?
                    frame:会
                    bounds:不会  
                    center:不会
            
            c。结论:
                    变形前,frame和bounds保持变化的一致性,变形后,frame代表的是在视图中表现出来的外观,所以会随着变形而记录不同的外观状态,但bounds不是用来表现的,只是记录大小的,所以不会改变,bounds的坐标系也不会改变
    ViewController.m
    #import "ViewController.h"
    
    @interface ViewController ()
    @property (weak, nonatomic) IBOutlet UIImageView *imageView;
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        [self print];
    }
    //直接修改frame
    - (IBAction)changFrame:(UIButton *)sender {
        CGRect frame=self.imageView.frame;
        frame.origin.x+=4;
        frame.origin.y+=4;
        frame.size.width+=4;
        frame.size.height+=4;
        self.imageView.frame=frame;
        [self print];
    }
    //直接修改bounds
    - (IBAction)changeBounds:(UIButton *)sender {
        CGRect bounds=self.imageView.bounds;
        //bounds.origin.x+=4;
       // bounds.origin.y+=4;
        bounds.size.width+=4;
        bounds.size.height+=4;
        self.imageView.bounds=bounds;
        [self print];
    
    }
    //直接修改center
    - (IBAction)changeCenter:(UIButton *)sender {
        CGPoint center=self.imageView.center;
        center.x+=4;
        center.y+=4;
        self.imageView.center=center;
        [self print];
    }
    //直接修改transform
    - (IBAction)changeTransform:(UIButton *)sender {
        self.imageView.transform=CGAffineTransformTranslate(self.imageView.transform, 4, 4);
        self.imageView.transform=CGAffineTransformScale(self.imageView.transform, 1.3, 1.3);
        self.imageView.transform=CGAffineTransformRotate(self.imageView.transform, M_1_PI);
        [self print];
    }
    
    -(void)print{
        NSLog(@"
    frame:%@
    bounds:%@
    center:%@
    transform:%@",
              NSStringFromCGRect(self.imageView.frame),
              NSStringFromCGRect(self.imageView.bounds),
              NSStringFromCGPoint(self.imageView.center),
              NSStringFromCGAffineTransform(self.imageView.transform));
        
    }
    @end
    
    点击了bounds按钮
    原始:
    frame:{{91, 33}, {112, 100}}
    bounds:{{0, 0}, {112, 100}}
    center:{147, 83}
    transform:[1, 0, 0, 1, 0, 0]
    点击后:
    frame:{{89, 31}, {116, 104}}
    bounds:{{0, 0}, {116, 104}}
    center:{147, 83}
    transform:[1, 0, 0, 1, 0, 0]
    
    2.触控(UITouch)
          2.1  是什么?
                是一个UITouch类型的对象,当用户touch视图时,会自动产生UITouch对象
    
        2.2 如何获取Touch
                需要自定义视图类,覆盖类中的指定的方法,在方法中才能获取到这个Touch对象
    
        2.3 有什么用?
                可以跟踪用户在视图上手指移动的轨迹,判断用户的意图,以此进行绘图、涂鸦、手写等操作
    
        2.4 怎么用?
                step1:自定义一个视图类
                step2:重写类中的方法即可
                            touchesBegan:withEvent://手指接触视图时调用
                            touchesMoved:withEvent://手指在视图上移动时调用
                            touchesEnded:withEvent://手指离开视图时调用
    
    
        注意:手势是对触控的一个封装
        
        【Demo3_UITouch】
    MyView.h(自己创建的类,关联到VC)
     #import "MyView.h"
    @implementation MyView
    
    //手指接触调用
    -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
        UITouch*touch=[touches anyObject];
        CGPoint location=[touch locationInView:self];
        NSLog(@"手指接触屏幕:(%.2f,%.2f)",location.x,location.y);
        
    }
    //手指在视图移动时
    -(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
        UITouch*touch=[touches anyObject];
        CGPoint location=[touch locationInView:self];
        NSLog(@"手指在视图上移动:(%.2f,%.2f)",location.x,location.y);
    }
    
    //离开时
    -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
        NSLog(@"手指离开视图");
    }
    
    @end
    手指接触屏幕:(147.00,87.00)
    手指在视图上移动:(146.50,89.00)
    手指在视图上移动:(148.50,92.00)
    手指离开视图
        
            练习:简易画板
        【Demo4_Touch_Paint】
    PaintView.h
    PaintView.m
    #import "PaintView.h"
    
    @interface PaintView ()
    
    //记录所有路径的可变数组
    @property(nonatomic,strong)NSMutableArray *paths;
    
    @end
    
    @implementation PaintView
    
    - (NSMutableArray *)paths{
        if (!_paths) {
            _paths = [NSMutableArray array];
        }
        return _paths;
    }
    
    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
        //获取UITouch对象
        UITouch *touch = [touches anyObject];
        CGPoint startPoint = [touch locationInView:self];
        
        // 创建路径
        UIBezierPath *path = [UIBezierPath bezierPath];
        [path setLineWidth:3];
        [path moveToPoint:startPoint];
        
        // 将路径对象记录到数组属性中
        [self.paths addObject:path];
    }
    
    -(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
        UITouch *touch = [touches anyObject];
        CGPoint currentPoint = [touch locationInView:self];
        //将刚刚创建的路径添加一个直线到该点
        //从数组中取出最后一个元素,就是刚刚手指落下时
        //创建的路径
        UIBezierPath *currentPath = [self.paths lastObject];
        [currentPath addLineToPoint:currentPoint];
        //重绘
        [self setNeedsDisplay];
    }
    
    
    - (void)drawRect:(CGRect)rect
    {
        //绘制所有路径
        for (UIBezierPath *path in self.paths) {
            [path stroke];
        }
    }
    
    @end
    
    
    作业:
    
    1. 做一个界面上画矩形的效果
        
            按下手指后开始画,拖动时大小变化,松手后定在屏幕上,支持绘制多个矩形
    
    2. 在作业1的基础上,支持选择绘制的颜色,支持线条的粗细设置
    
    3. 在作业1或2的基础上,增加橡皮功能
    
    4. 支持各种形状—矩形,圆角矩形,椭圆。。。。
    =======================================================================================================
    知识点 
    六、布局
    1.布局 (Layout)控制器中的view
    
        1.1 什么是布局?
            是指在一个视图中如何摆放它的子视图(安排子视图的位置和大小)
    
        1.2 为什么要布局?
            屏幕的尺寸会经常发生变化或者随着设备不同,屏幕尺寸也会不同,只要屏幕大小发生了变化,坐标系也会随之变化,于是变化前设置的frame在新的坐标系中定位就会与期待的不符,所以就需要在屏幕发生变化时重新布局指定frame
            【Demo5_Layout】
    
        1.3 可能导致屏幕大小发生变化的原因
            a。设备不同(3.5寸 4存。。。。)
            b。屏幕方向不同
            c。状态栏
                        隐藏
                        特殊的状态栏:来电时,绿色状态栏
                                                          录音时,红色状态栏
                                                          开启个人热点,蓝色状态栏
            d。各种Bar
                        NavigationBar: 44/32  如果设置了prompt,bar会更高
                        TabBar:49个点高
                        ToolBar:44/32 个点
                        iOS7中,导航栏挤占了状态栏,高度是64/52
    
            e。键盘
                        弹出时挤占屏幕,高度不确定,因为中英文键盘的高度不同
    
        1.4 如何布局
    
                方法一:纯代码布局,古老的方法
                        理念:当屏幕发生变化时,自动执行一段我们写好的代码,代码中重新计算了视图的frame,从而达到在新坐标系下重新定位的目的
                        特点:功能强大,非常繁琐
    
                方法二:Auto Resizing 以前的一种自动布局技巧
                        理念:记录视图与父视图的边缘为可调整或固定值,然后屏幕发生变化时,依据这段相对的距离,重新布局视图
                        特点:操作简单,功能有限
    
                方法三:Auto Layout 最新的自动布局方法
                        理念:将视图与视图之间的位置以及视图自身的大小,用多个约束来记录,当屏幕发生变化时,系统根据定好的约束,自动计算满足该约束情况下的新的坐标值,然后调整位置
                        特点:简单易用
    
                注意:以上的布局方式,选择其一使用。
    
    4. 纯代码布局
            
                4.1 理念:在屏幕大小发生变化时,通过代码的方式改变视图的frame
    
                4.2 重写控制器中方法:viewDidLayoutSubviews:即可
                            该方法,在屏幕发生变化时,由系统自动调用,所以,改变frame的代码写在这个方法中就会被自动执行了。
        
                  注意:使用纯代码布局时,一定要关闭AutoLayout,否则代码可能会无效
    
                【Demo5_Layout】
    
        【练习】        
        1.两个等宽的按钮,高40,有背景色
                    ———————————————
                |               20                    20             |
                |-20-[button1]-10-[button2]-20-|
        2.在1的基础上,加一个大小会变化的ImagView(内有图片)
                    imageView离屏幕上、下、左、右保持70,502020
        3.在2的基础上,增加三个按钮,大小是20X20,永远排列在屏幕的右下角
                         【b1】-10-【b2】-10-【b3】-20-|
                                 20                20                20          |
                            ———————————————|
                        b1,2,3离下边缘都是20个点
     时间:半个小时
                
    
     补充:
    
            关掉AutoLayout以后,drawRect方法中针对视图绘制的图形在屏幕旋转时会被拉伸,解决该问题的话,需要设置视图的“contentMode”设置为“redraw”即可
        
     解决方法:设置视图的的contentMode为redraw即可
    
    ViewController.h
    ViewController.m
    #import "ViewController.h"
    
    @interface ViewController ()
    @property (weak, nonatomic) IBOutlet UIButton *button1;
    @property (weak, nonatomic) IBOutlet UIButton *button2;
    @property (weak, nonatomic) IBOutlet UIImageView *imageView;
    @property (weak, nonatomic) IBOutlet UIButton *b1;
    @property (weak, nonatomic) IBOutlet UIButton *b2;
    @property (weak, nonatomic) IBOutlet UIButton *b3;
    
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
    }
    
    -(void)viewDidLayoutSubviews{
        [super viewDidLayoutSubviews];
        
        CGFloat buttonWidth = (self.view.bounds.size.width - 20 - 20 - 10)/2;
        
        CGRect frame = CGRectMake(20, 20, buttonWidth, 40);
        self.button1.frame = frame;
        
        frame.origin.x += buttonWidth + 10;
        self.button2.frame = frame;
        
        frame.size = CGSizeMake(self.view.bounds.size.width-20-20, self.view.bounds.size.height-70-50);
        frame.origin = CGPointMake(20, 70);
        self.imageView.frame = frame;
        
        frame.size = CGSizeMake(20, 20);
        frame.origin = CGPointMake(self.view.bounds.size.width-20-20, self.view.bounds.size.height-20-20);
        self.b3.frame =frame;
        
        frame.origin.x -= (10+20);
        self.b2.frame = frame;
        
        frame.origin.x -= (10+20);
        self.b1.frame = frame;
    
    }
    
    @end
    故事板中的界面随意布局就好,做一个控件的创建就好了
    
    2.UIView对内部的子视图的布局(典型应用:TableViewCell对内部子视图的布局)
            1.1 如何实现?
                step1:自定义视图,继承自UIView
                step2:重写自定义视图的方法
                                a。  viewWillLayoutSubViews
                                b。  layoutSubViews
                                c。  viewDidLayoutSubView
                方法执行的顺序:a->b->c
                一般重写  layoutSubViews方法即可。
    
             练习:音乐列表
            【Demo1_TableViewCell_Layout】
    Mondel
    TRMusic.h
    #import <Foundation/Foundation.h>
    
    @interface TRMusic : NSObject
    
    @property (nonatomic, copy) NSString * name;//歌曲名
    @property (nonatomic, copy) NSString * album;//专辑
    @property (nonatomic, copy) NSString * artist;//艺术家
    
    @property (nonatomic) NSTimeInterval duration;//时长
    
    @property (nonatomic) BOOL highQuality;//高品质
    @property (nonatomic) BOOL downloaded;//下载
    
    @end
    TRMusic.m
    #import "TRMusic.h"
    
    @implementation TRMusic
    
    @end
    
    TRMusicGroup.h
    #import <Foundation/Foundation.h>
    #import "TRMusic.h"
    
    
    typedef NS_ENUM(NSInteger, TRMusicGroupState) {
        TRMusicGroupStateNormal,    //音乐组的状态
        TRMusicGroupStateDownloading,        
        TRMusicGroupStateDownloaded
    };
    
    @interface TRMusicGroup : NSObject
    
    @property (nonatomic, copy) NSString * name;//组名字
    
    @property (nonatomic, strong) NSArray * musics;//多个音乐
    
    @property (nonatomic) TRMusicGroupState state;//状态
    
    + (NSArray *) fakeData;
    
    @end
    
    TRMusicGroup.m
    #import "TRMusicGroup.h"
    
    @implementation TRMusicGroup
    
    + (NSArray *) fakeData
    {
        NSMutableArray * musics = nil;
        TRMusic * music = nil;
        
        musics = [NSMutableArray array];
        
        music = [[TRMusic alloc] init];
        music.name          = @"Burn";
        music.album         = @"Burn - Single";
        music.artist        = @"Ellie Goulding";
        music.duration      = [self durationWithMinutes:3 andSeconds:51];
        music.downloaded    = YES;
        music.highQuality   = NO;
        [musics addObject:music];
        
        music = [[TRMusic alloc] init];
        music.name          = @"Summertime Sadness (Cedric Gervais Remix)";
        music.album         = @"Summertime Sadness (Cedric Gervais Remix) - Single";
        music.artist        = @"Lana Del Rey";
        music.duration      = [self durationWithMinutes:6 andSeconds:52];
        music.downloaded    = YES;
        music.highQuality   = YES;
        [musics addObject:music];
        
        music = [[TRMusic alloc] init];
        music.name          = @"Spectrum";
        music.album         = @"Clarity";
        music.artist        = @"Zedd";
        music.duration      = [self durationWithMinutes:4 andSeconds:3];
        music.downloaded    = YES;
        music.highQuality   = YES;
        [musics addObject:music];
        
        music = [[TRMusic alloc] init];
        music.name          = @"It's Time";
        music.album         = @"It’s Time";
        music.artist        = @"Imagine Dragons";
        music.duration      = [self durationWithMinutes:4 andSeconds:0];
        music.downloaded    = NO;
        music.highQuality   = YES;
        [musics addObject:music];
        
        music = [[TRMusic alloc] init];
        music.name          = @"Dancing in The Moonlight";
        music.album         = @"Dancing In The Moonlight: The Best Of Toploader";
        music.artist        = @"Toploader";
        music.duration      = [self durationWithMinutes:3 andSeconds:53];
        music.downloaded    = YES;
        music.highQuality   = YES;
        [musics addObject:music];
        
        
        TRMusicGroup * g1 = [[TRMusicGroup alloc] init];
        g1.name = @"国外单曲";
        g1.musics = [musics copy];
        g1.state = TRMusicGroupStateDownloaded;
        
        
        
        musics = [NSMutableArray array];
        
        music = [[TRMusic alloc] init];
        music.name          = @"你有本事抢男人";
        music.album         = @"好大的胆子";
        music.artist        = @"雪姨";
        music.duration      = [self durationWithMinutes:3 andSeconds:18];
        music.downloaded    = NO;
        music.highQuality   = NO;
        [musics addObject:music];
        
        music = [[TRMusic alloc] init];
        music.name          = @"喂鸡";
        music.album         = @"六十年代生人";
        music.artist        = @"刘欢";
        music.duration      = [self durationWithMinutes:3 andSeconds:41];
        music.downloaded    = NO;
        music.highQuality   = YES;
        [musics addObject:music];
        
        music = [[TRMusic alloc] init];
        music.name          = @"忐忑";
        music.album         = @"自由鸟";
        music.artist        = @"龚琳娜";
        music.duration      = [self durationWithMinutes:4 andSeconds:03];
        music.downloaded    = NO;
        music.highQuality   = YES;
        [musics addObject:music];
        
       
        
        TRMusicGroup * g2 = [[TRMusicGroup alloc] init];
        g2.name = @"国内神曲";
        g2.musics = [musics copy];
        g2.state = TRMusicGroupStateNormal;
        
        TRMusicGroup * g3 = [[TRMusicGroup alloc] init];
        g3.name = @"Calvin Harris 专辑";
        g3.musics = @[];
        g3.state = TRMusicGroupStateNormal;
        
        TRMusicGroup * g4 = [[TRMusicGroup alloc] init];
        g4.name = @"Ellie Gounding 专辑";
        g4.musics = @[];
        g4.state = TRMusicGroupStateNormal;
        
        return @[g1, g2, g3, g4];
    }
    
    + (NSTimeInterval) durationWithMinutes:(int)minutes andSeconds:(int)seconds
    {
        return minutes * 60 + seconds;
    }
    
    @end
    
    MusilcTableViewController.h
    #import <UIKit/UIKit.h>
    #import "TRMusicGroup.h"
    @interface MusilcTableViewController : UITableViewController
    @property(nonatomic,strong)TRMusicGroup*musicGroup;
    @end
    
    MusilcTableViewController.m
    #import "MusilcTableViewController.h"
    #import "MusicTableViewCell.h"
    #import "TRMusic.h"
    @interface MusilcTableViewController ()
    
    @end
    
    @implementation MusilcTableViewController
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        
    }
    //获取列表内容
    -(TRMusicGroup *)musicGroup{
        if (!_musicGroup) {
            _musicGroup=[TRMusicGroup fakeData][0];
            
        }
        return _musicGroup;
    }
    
    #pragma mark - Table view data source
    
    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
    {
        return 1;
    }
    
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
    {
    
        return self.musicGroup.musics.count;
    }
    
    /**/
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        MusicTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MusicCell" forIndexPath:indexPath];
        //找出音乐,获取数据
        TRMusic* music=self.musicGroup.musics[indexPath.row];
        //将音乐赋给cell
        cell.music=music;
        
        
        return cell;
    }
    
    
    @end
    MusicTableViewCell.h
    #import <UIKit/UIKit.h>
    #import "TRMusic.h"
    
    @interface MusicTableViewCell : UITableViewCell
    @property(nonatomic,strong)TRMusic*music;
    @end
    MusicTableViewCell.m
    #import "MusicTableViewCell.h"
    @interface MusicTableViewCell () //扩展属性
    @property (weak, nonatomic) IBOutlet UILabel *nameLabel;
    @property (weak, nonatomic) IBOutlet UILabel *durationLabel;
    @property (weak, nonatomic) IBOutlet UILabel *artistLabel;
    @property (weak, nonatomic) IBOutlet UIImageView *downloadedImageView;
    @property (weak, nonatomic) IBOutlet UIImageView *highQualityImageView;
    
    @end
    
    @implementation MusicTableViewCell
    
    //重写set方法
    -(void)setMusic:(TRMusic *)music{
        _music = music;
        //将music的各个属性放到对应的控件上
        self.nameLabel.text = self.music.name;
        self.durationLabel.text=[NSString stringWithFormat:@"%d:%02d",(int)self.music.duration/60,(int)self.music.duration%60];
        self.artistLabel.text=[[self.music.artist stringByAppendingString:@"-"]stringByAppendingString:self.music.album];
        
        self.downloadedImageView.hidden = !self.music.downloaded;
        self.highQualityImageView.hidden = !self.music.highQuality;
       
    }
    //重写 cell对自己内部子视图的布局
    -(void)layoutSubviews{
        [super layoutSubviews];
        CGFloat x=self.downloadedImageView.frame.origin.x;
        if (self.music.downloaded) {
            x+=20;
        }
        if (self.music.highQuality) {
            CGRect rect=self.highQualityImageView.frame;
            rect.origin.x=x;
            self.highQualityImageView.frame=rect;
            x+=20;
        }
        CGRect fram=self.artistLabel.frame;
        fram.origin.x=x;
        self.artistLabel.frame=fram;
    }
    @end1.2. 布局对状态栏和各种Bar的处理
                
                使用属性:topLayoutGuide.length//屏幕上方当前被占据的区域的长度                
                             bottomLayoutGuide.length//屏幕下方当前被占据的长度
    
            【Demo2_Layout_Bar】
    #import "ViewController.h"
    
    @interface ViewController ()
    @property (weak, nonatomic) IBOutlet UIButton *button;
    @property (weak, nonatomic) IBOutlet UILabel *label;
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        
    }
    
    - (void)viewDidLayoutSubviews{
        CGRect frame = self.button.frame;
        frame.origin.x = self.view.bounds.size.width-20-frame.size.width;
        frame.origin.y = self.topLayoutGuide.length+10;
        self.button.frame = frame;
        
        frame = self.label.frame;
        frame.origin.x = self.view.bounds.size.width -20 - frame.size.width;
        frame.origin.y = self.view.bounds.size.height - self.bottomLayoutGuide.length - frame.size.height;
        self.label.frame = frame;
        
    }
    //点击屏幕隐藏工具栏
    - (IBAction)changeBar:(UITapGestureRecognizer *)sender {
        [self.navigationController setNavigationBarHidden:!self.navigationController.navigationBarHidden animated:YES];
        [self.navigationController setToolbarHidden:!self.navigationController.toolbarHidden animated:YES];
    }
    
    
    - (BOOL)prefersStatusBarHidden{
        return YES;
    }
    
    @end3. 手动设置Autoresizing 布局
            
            3.1 是什么?
                是旧版本(iOS5之前)的自动布局奇数。操作简单,API简单,功能也简单,有局限性,很久以前叫 struts/spring(架构/弹性)技术
            
            3.2 核心理念
                当界面大小发生变化时,根据变化的比例,对子视图进行同比例的变化
    
            3.3 怎么样
                step1:关闭AutoLayout
                step2:选中需要布局的子视图
                step3:打开检查器5
                step4:点亮需要的红线
                                外框(4个)红线负责子视图到父视图的边缘
                                内框(2个)红线负责子视图内部是否可以拉伸
                
            【Demo3_Autoresizing】
    4.编写代码实现Autoresizing 布局
                      Autoresizing和代码布局可以同时使用,用代码补齐Autoresizing的不足
                    button.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleBottomMargin;
                代码设置时,规则描述与在检查器中描述相反,只需要设置可变的边距
    如:
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        
        /**/
         UIButton* button=[UIButton buttonWithType:UIButtonTypeSystem];
        [button setTitle:@"button1" forState:UIControlStateNormal];
        [button setBackgroundColor:[UIColor redColor]];
        button.frame=CGRectMake(self.view.bounds.size.width-120, 20, 100, 40);
        [self.view addSubview:button];
        //点亮红线
        button.autoresizingMask=UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleBottomMargin;
    
    }
    
    5.Autolayout(自动布局)
                5.1 是什么?
                 是从iOS6开始的一个新的布局技术,功能强大,操作复杂。从xcode5开始,慢慢好用了。在xcode6中,功能更强大了。
                核心理念:使用约束(constraint)来描述控件在视图中的位置,当屏幕大小发生变化时,系统会根据你设定的约束自动计算出frame的值,然后将该值赋给控件,实现控件的排布
    
            5.2 使用故事板为控件添加约束
               【Demo4_AutoLayout】
    
            5.3  操作要点
                    a。选中控件,分析6点,上下左右及控件的宽高需要哪些约束才能确定
                    b。约束的添加可以通过屏幕下方的选项,或者是,选中控件后,按住control,连线到屏幕边缘或其他视图
                    c。可以添加的约束有:对齐方式(与中心点对齐或与其他控件对齐)、与边缘或其他视图的间距(前导间距和尾部边距)、视图的宽高是给定值还是以其他视图做参照标准
                    d。添加约束后,正确的结果出现时,屏幕中只有蓝色的线,存在红色虚线框框时,代表视图占据的区域,有橘色线条时,代表当前摆放位置与定义的位置有距离,可以通过底部的第三个选项菜单,选择更新某个视图的frame或更新所有视图的frame
                    e。选中一个视图,查看第5个检查器可以看到该视图已经添加了的约束,可以选中约束修改约束的内容
                    f。选中一个视图,通过查看场景的文档结构图,观察该场景下的约束是否有错误或警告,如果有,可以点击该场景的右上角的红色点点,进入说明界面,红色的提示为一场,必须修改为正确,方可代表系统认可约束,可以进行布局,橘色的提示,一般是实际位置与约束位置有偏差,只要更新frame,就可以让橘色的警告消失
    
    6.Auto Layout 代码创建约束
            
            1.1 什么时候用?
                    当子视图对象时代码创建时,并且需要给子视图布局时,只能用代码来进行自动布局
    
            1.2 如何添加约束?
                    step1:创建约束对象
                                    NSLayoutConstraint (API)
                    step2:将约束添加到父视图
    
            1.3 创建约束对象
                    方法一:使用万能公式
                        + (instancetype)constraintWithItem:(id)view1
                 attribute:(NSLayoutAttribute)attr1
                 relatedBy:(NSLayoutRelation)relation
                        toItem:(id)view2
                 attribute:(NSLayoutAttribute)attr2
                  multiplier:(CGFloat)multiplier
                  constant:(CGFloat)c
                        公式:view1.attr1<relation>view2.attr2*multiplier +contant
                        如:
                            button.left = self.view.left*0 + 20
                            button.right = self.view.width*1 + (-20)
                        注意:translateAutoresizingToConstraints这个属性默认是YES,这个属性代表:将视图默认自带的Auto resizing特性是否自动转换为对应的约束。既然使用代码来创建约束,那么就不要让系统自带的转换过来的约束影响添加的自定义约束,所以该属性要设置为NO,为了保证效果,可以将视图以及视图的父视图的该属性都设置为NO
        //关闭视图自身的翻译
        button1.translatesAutoresizingMaskIntoConstraints = NO;
        self.view.translatesAutoresizingMaskIntoConstraints = NO;
                    【Demo1_Autolayou_Code】
            
    
    如:
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        UIButton *button1 = [UIButton buttonWithType:UIButtonTypeSystem];
        [button1 setTitle:@"button1" forState:UIControlStateNormal];
        button1.backgroundColor = [UIColor lightGrayColor];
        [self.view addSubview:button1];
        //关闭视图自身的翻译
        button1.translatesAutoresizingMaskIntoConstraints = NO;
        self.view.translatesAutoresizingMaskIntoConstraints = NO;
        
        //创建约束
        NSLayoutConstraint *c1 = [NSLayoutConstraint constraintWithItem:button1 attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeLeft multiplier:0 constant:20];
        [self.view addConstraint:c1];
        
        NSLayoutConstraint *c2 = [NSLayoutConstraint constraintWithItem:button1 attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeTop multiplier:0 constant:20];
        [self.view addConstraint:c2];
        //
        NSLayoutConstraint *c3 = [NSLayoutConstraint constraintWithItem:button1 attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:nil attribute:0 multiplier:0 constant:150];
        [self.view addConstraint:c3];
    }
    
    
                方法二:一次创建多个约束,使用VFL(Visual Format Language)
    
                        + (NSArray *)constraintsWithVisualFormat:(NSString *)format
            options:(NSLayoutFormatOptions)opts 参数2:对齐方式
            metrics:(NSDictionary *)metrics
                   views:(NSDictionary *)views 参数4:创建添加的对象
    
                        特点:功能强大
                    【Demo2_Autolayout_Code_VFL】
    
            1.4 VFL(Visual Format Language)
                    a。是什么?
                            一个字符串,具有一定的格式,代表一些约束的含义
                    
                    b。如何写VFL字符串?
                            |                 代表父视图的边
                            V:|           代表垂直方向的父视图的上边
                            [ ]         代表一个子视图(或控件)
                            ( )          代表一个条件(== 、 >=、<=)==可以省略
                             -           代表间距,默认的8个点
                             -xxx-         代表间距是多少
                                         [button2(button1)] :button1与button2的高度相同
    
                        如:    |-20-[button1]-10-[button2(button1)]-10-[button3(button1)]-20-|
                                    V:|-20-[button1]
    
                    c。metrics参数 (用于替换参数3)
                            用于指定VFL字符串中可以替换的值,是一个字典类型
                            如:NSDictionary *metrics = @{@"left":@20,@"space":@10,@"right":@20};
    
                    d。NSDictionaryOfVariableBinding()函数   (用于替换参数4)
                        NSDictionary *dictionary = NSDictionaryOfVariableBindings(b1,b2,b3);
                        生成的字典如下:
                            @{@"b1":b1,@"b2":b2,@"b3":b3}
    如:
    #import "ViewController.h"
    
    @interface ViewController ()
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        //需求:屏幕上方 添加三个等宽的按钮
        UIButton *b1 = [UIButton buttonWithType:UIButtonTypeSystem];
        [b1 setTitle:@"button1" forState:UIControlStateNormal];
        b1.backgroundColor = [UIColor lightGrayColor];
        [self.view addSubview:b1];
        
        UIButton *b2 = [UIButton buttonWithType:UIButtonTypeSystem];
        [b2 setTitle:@"button2" forState:UIControlStateNormal];
        b2.backgroundColor = [UIColor lightGrayColor];
        [self.view addSubview:b2];
        
        UIButton *b3 = [UIButton buttonWithType:UIButtonTypeSystem];
        [b3 setTitle:@"button3" forState:UIControlStateNormal];
        b3.backgroundColor = [UIColor lightGrayColor];
        [self.view addSubview:b3];
        
        //1.添加约束的第一步:关闭自动翻译
        b1.translatesAutoresizingMaskIntoConstraints = NO;
        b2.translatesAutoresizingMaskIntoConstraints = NO;
        b3.translatesAutoresizingMaskIntoConstraints = NO;
        self.view.translatesAutoresizingMaskIntoConstraints = NO;
        
        //下面的函数会将传入的多个引用构建成如下的字典形式:
        //@{@"b1":b1,@"b2":b2,@"b3":b3}
        NSDictionary *dictionary = NSDictionaryOfVariableBindings(b1,b2,b3);
        
        
        NSDictionary *metrics = @{@"left":@20,@"space":@10,@"right":@20};
    
        //2.第二步:创建约束
        //2.1准备一个VFL
         //NSString*hVFL=@"|-20-[button1]-10-[button2(==button1)]-10-[button3(==button1)]-20-|";
         NSString *hVFL = @"|-left-[b1]-space-[b2(b1)]-space-[b3(b1)]-right-|";
        //2.2创建约束
        NSArray *cs = [NSLayoutConstraint constraintsWithVisualFormat:hVFL options:NSLayoutFormatAlignAllCenterY metrics:metrics views:dictionary];
        //3.将约束添加到父视图中
        [self.view  addConstraints:cs];
       
        NSString *vVFL = @"V:|-left-[button1]";
        cs = [NSLayoutConstraint constraintsWithVisualFormat:vVFL options:0 metrics:metrics views:@{@"button1":b1}];
        [self.view addConstraints:cs];
    }
    
    @end=======================================================================
    知识点
    七、动画
    1.动画 (Animation)
    
            1.1 是什么?
        
                “帧动画”:一帧 是一张静态的图片,一般情况下,1秒钟达到24,5帧的时候,人眼就分辨不出图片的切换过程,就有连续的效果产生
        
                    帧率(FPS)Frame Per Second
    
            1.2 iOS中的动画
    
                    UIImage 类,自带一些方法,可以做简单动画
                    NSTimer 类,间隔指定时间,产生切换效果
                    UIView类 本来提供了动画的功能
                    底层的Core Animation 提供了动画的支持
                    
                    在iOS7中增加一些动画功能:
                        UIKit Dynamic 动力
                        Motion Effects 特效
                        Sprite Kit (2D引擎)
    
    2. UIImage动画
    
                【Demo3_UIImage_Animation】
                    //duration:播放一组图片用的时间
        UIImage *image = [UIImage animatedImageNamed:@"ship-anim" duration:1*5/30]; 1秒播放30帧,播放一张图片需要1/30,5张照片
        self.imageView.image = image;
    
    3. NSTimer 动画
    
        4.1 是什么?
            一个计时器类,用于定时向指定对象发消息
    
        4.2 如何使用?
        【Demo4_NSTimer】
            
             1.//创建计时器
        //使用schedule。。开头的方法时,定时器创建完毕就会启动
        self.timer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(doSomething:) userInfo:nil repeats:YES];
        //使用timerWith。。。开头的方法创建timer
        //定时器不会在创建完毕后启动
        //需要使用代码将定时器添加到时间循环中才能启动
        self.timer = [NSTimer timerWithTimeInterval:2 target:self selector:@selector(doSomething:) userInfo:nil repeats:YES];
         2.//启动定时器
        [[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSDefaultRunLoopMode];
         3.//关闭定时器
        [self.timer invalidate];
    
        练习:【Demo5_NSTimer_Alpha】
            使用NSTimer做一个图片淡入的效果(通过修改alpha透明度值来完成)
    #import "ViewController.h"
    
    @interface ViewController ()
    @property (weak, nonatomic) IBOutlet UIImageView *imageView;
    @property(nonatomic,strong)NSTimer *timer;
    @property(nonatomic)NSInteger count;
    @end
    
    @implementation ViewController
    
    #define FPS 30.0
    #define DURATION 5.0
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        self.imageView.alpha = 0;
        self.timer = [NSTimer scheduledTimerWithTimeInterval:1/FPS target:self selector:@selector(changeAlpha:) userInfo:nil repeats:YES];
    }
    //匀速动画的公式
    //当前值 = 开始值+当前帧数*(结束值-开始值)/(帧率*动画时长)
    -(void)changeAlpha:(NSTimer *)timer{
        //count代表当前帧数
        self.count++;
        
        self.imageView.alpha = 0 + self.count*(1-0)/(FPS*DURATION);
        
        if (self.count>=FPS*DURATION) {
            [timer invalidate];
        }
        
    }
    
    @end
    
        4.3 匀速动画
        
        公式:当前值= 开始值+当前帧数*(结束值-开始值)/(帧率*动画时长)
        
        这个值可以是:center  transform   frame    alpha    
    
        【Demo6_NSTimer_Animation】
    
        4.4 变速动画
        
        由快到慢、由慢到快、由慢到快再到慢
        
        公式: 当前值 = 上一次的值+(目标值-上一次值)*渐进因子
            渐进因子根据情况调节
                    【Demo7_NSTimer_Animation】
    #import "ViewController.h"
    
    @interface ViewController ()
    @property (weak, nonatomic) IBOutlet UIImageView *airCraft;
    
    @end
    
    @implementation ViewController
    #define FPS 30.0
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        
    }
    
    - (IBAction)start:(id)sender {
        [NSTimer scheduledTimerWithTimeInterval:1/FPS target:self selector:@selector(move:) userInfo:nil repeats:YES];
    }
    
    //当前值=上一次的值+(目标值-上一次的值)*渐进因子
    /*
      400 + (100 - 400)*0.1 = 370    30p
      370 + (100 - 370)*0.1 = 343    27p
      343 + (100 - 343)*0.1 = 319.7  24.3
    */
    -(void)move:(NSTimer *)timer{
        CGPoint center = self.airCraft.center;
        center.y = center.y+(50-center.y)*0.05;
        self.airCraft.center = center;
        if (center.y<=51.0) {
            [timer invalidate];//结束
        }
    }
    
    @end
    
    5. UIView 动画:真正的动画,有专门的API
    
            5.1 是什么
                
                有UIKit专门制作动画的API,这些API的底层对Core Animation的封装,可以轻松实现动画,不用再计算每一帧的值来实现动画的效果
    
            5.2 制作动画的步骤
    
                step1:设置需要动画的视图的初始值
                step2:给UIView类发消息,告诉UIView类需要什么样的动画
                step3:将动画结束的状态(属性值),即变化的结果,写入到一个Bloack中
    [UIView animateWithDuration:2.0 delay:0 options:UIViewAnimationOptionRepeat|UIViewAnimationOptionAutoreverse animations:^{
            //设置动画结束时,被动画的那个视图的结束状态
            self.airCraft.center = endCenter;
            self.airCraft.transform = transform;
        } completion:nil];
    
                【Demo8_UIView_Animation】
    
            5.3 动画的高级选项
            
                先慢后快再慢
                UIViewAnimationOptionCurveEaseInOut  
                越来越快          
        UIViewAnimationOptionCurveEaseIn  
        越来越慢             
        UIViewAnimationOptionCurveEaseOut  
        匀速            
        UIViewAnimationOptionCurveLinear
        动画重复
        UIViewAnimationOptionRepeat  
        反着执行动画,要配合Repeat选项                  
        UIViewAnimationOptionAutoreverse 
    
             要求:启动后,从屏幕左边弹出label,从屏幕下边弹出image,然后点击按钮,飞机实现旋转飞行,并重复飞行
    #import "ViewController.h"
    
    @interface ViewController ()
    @property (weak, nonatomic) IBOutlet UIImageView *airCraft;
    @property (weak, nonatomic) IBOutlet UILabel *welcomeLabel;
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        CGRect endFrame = self.welcomeLabel.frame;
        CGRect startFrame = endFrame;
        startFrame.origin.x = -startFrame.size.width;
        //1.设置需要动画的视图的初始属性
        self.welcomeLabel.frame = startFrame;
        self.welcomeLabel.alpha = 0.1;
        //2.给UIView发消息
        [UIView animateWithDuration:2.0 animations:^{
            self.welcomeLabel.frame = endFrame;
            self.welcomeLabel.alpha = 1.0;
        }];
        
        endFrame = self.airCraft.frame;
        startFrame = endFrame;
        startFrame.origin.y = self.view.bounds.size.height;
        self.airCraft.frame  = startFrame;
        [UIView animateWithDuration:2.0 animations:^{
            self.airCraft.frame = endFrame;
        }];
        
    }
    
    - (IBAction)start:(id)sender {
        //这是当前中心点
        CGPoint endCenter = self.airCraft.center;
        //计算结束位置的y值
        endCenter.y -=300;
        //旋转
        CGAffineTransform transform = CGAffineTransformMakeRotation(M_PI);
        
        [UIView animateWithDuration:2.0 delay:0 options:UIViewAnimationOptionRepeat|UIViewAnimationOptionAutoreverse animations:^{
            //设置动画结束时,被动画的那个视图的结束状态
            self.airCraft.center = endCenter;
            self.airCraft.transform = transform;
        } completion:nil];
        
    }
    
    @end
    
    作业
    
    1.飞机放到屏幕上以后,点哪,飞哪儿
    
    2.做一个购物车的动画
        在屏幕的左上角有一个UIImageView,图片是一个商品。
        当用户点击此商品时,商品会从上面掉下来,落入到下面的购物车中,
    
        注意:商品掉下来时,屏幕左上角的图片不会消失
    例:
    #import "ViewController.h"
    
    @interface ViewController ()
    
    @end
    
    @implementation ViewController
    #define FPS 30.0
    #define MAX_SIZE 10
    #define MAX_DURATION 10
    
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        //启动定时器,创建雪花
        [NSTimer scheduledTimerWithTimeInterval:1/FPS target:self selector:@selector(animate:) userInfo:nil repeats:YES];
    }
    
    -(void)animate:(NSTimer *)timer{
        //1.创建一个雪花
        UIImageView *snow = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"snow.png"]];
        int viewWidth = self.view.bounds.size.width;
        int viewHeight = self.view.bounds.size.height;
        CGFloat size = MAX_SIZE+arc4random()%MAX_SIZE;
        snow.frame = CGRectMake(arc4random()%viewWidth, -20, size, size);
        [self.view addSubview:snow];
        //2.创建动画
        [UIView animateWithDuration:arc4random()%MAX_DURATION+2  delay:0 options:UIViewAnimationOptionCurveEaseIn animations:^{
            //3. 设置动画结束时雪花的位置信息
            int offset = arc4random()%100 - 50;
            snow.center = CGPointMake(snow.center.x+offset, viewHeight-30);
        }completion:^(BOOL finished) {
            //4.落地动画结束时,开始融雪
            [UIView animateWithDuration:arc4random()%MAX_DURATION delay:0 options:UIViewAnimationOptionCurveEaseIn  animations:^{
                snow.alpha = 0;
            } completion:^(BOOL finished) {
                //5.融雪动画结束时,将图片移出父视图
                [snow removeFromSuperview];
            }];
        }];
    }
    
    ======================================================================
    知识点
    七、Core Animation
    
    1.Core Animation
            1.1是什么
                     是一个图形渲染和动画的底层框架,用于iOS和Mac OS X
    
            1.2 能干什么
                    1)可以提供更多更强大的图形渲染(显示)效果
                    2)可以提供专业级的动画效果
                    3)是高层图形技术的基础
    
            1.3 如何使用Core Animation
                    (内容较多,很庞大,只讲常用的)
                    通过CALayer类,直接对一个视图(UIView及子类)的 Core Animation层进行一些设置,达到需要的效果
    
            1.4 如何获得CALayer这一层呢?
                    任何UIView及其子类都有一个属性叫layer
                    UIView                           CALayer
                    .layer
                    .frame                          .frame
                    .transform                             .transform3D
                    .autoresizing                        .autoresizing
                    .addSubView:                    .addSubLayer:
                【Demo1_CoreAnimation】
    #import "ViewController.h"
    
    @interface ViewController ()
    @property (weak, nonatomic) IBOutlet UIImageView *imageView;
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        CALayer *layer = self.view.layer;
        layer.backgroundColor = [[UIColor orangeColor] CGColor];
        layer.cornerRadius = 30.0;
        
        self.imageView.layer.cornerRadius = 10.0;
        //打开遮罩
        self.imageView.layer.masksToBounds = YES;
        
        // 加子层
        CALayer *subLayer = [CALayer layer];
        subLayer.backgroundColor = [[UIColor purpleColor]CGColor];
        subLayer.frame = CGRectMake(30, 200, 100, 120);
        subLayer.shadowColor = [[UIColor greenColor]CGColor];
        subLayer.shadowOffset = CGSizeMake(2, 2);
        subLayer.shadowRadius = 5.0;
        subLayer.shadowOpacity = 0.8;阴影透明度,设置它阴影才会显示
        subLayer.cornerRadius = 10.0;
        
        [layer addSublayer:subLayer];
        
        //有内容的子层
        CALayer *imageLayer = [CALayer new];
        imageLayer.frame = CGRectMake(180, 250, 100, 120);
        imageLayer.contents = (id)[UIImage imageNamed:@"d.jpg"].CGImage;//添加图片
        imageLayer.cornerRadius = 10;
        imageLayer.masksToBounds = YES;
        
        [layer addSublayer:imageLayer];
    }
    
    @end1.5 CAAnimation    一个抽象的动画类型,很多时候不关心这个父类,而是使用它的子类来实现动画
                
                1) CAKeyframeAnimation 关键帧动画
                    可以根据指定的路径进行动画
                         实现步骤:
                            step1:创建关键帧动画
                                    使用animationWithKeyPath:方法创建,同时,最后一个字符串参数必须是以下几种选择:
                                    position   transform  opacity
                            step2:设置动画属性
                            step3:将动画添加到视图的layer层上
                        
    
                2)CABasicAnimation可以实现缩放,旋转,透明度等动画
                        特点:设置动画属性主要为两个:fromValue  和 toValue
    
    例:点击按钮,图片按曲线移动,并且移动的时候会缩小,并且会消失
    #import "AnimationViewController.h"
    
    @interface AnimationViewController ()
    @property (weak, nonatomic) IBOutlet UIImageView *imageView;
    
    @end
    
    @implementation AnimationViewController
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        
    }
    
    - (IBAction)start:(id)sender {
        UIBezierPath *path = [UIBezierPath bezierPath];
        [self createPath:path];
        
        // 创建关键帧动画
        CAKeyframeAnimation *moveAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
        // 设置相关的属性
        moveAnimation.path = path.CGPath;
        //moveAnimation.duration = 2.0;
        //[self.imageView.layer addAnimation:moveAnimation forKey:nil];
        
        //创建缩放动画
        CABasicAnimation *scaleAnimation = [CABasicAnimation animationWithKeyPath:@"transform"];
        scaleAnimation.fromValue = [NSValue valueWithCATransform3D:CATransform3DIdentity];
        scaleAnimation.toValue = [NSValue valueWithCATransform3D:CATransform3DMakeScale(0.1, 0.1, 0.1)];
        //scaleAnimation.duration = 2.0;
        //[self.imageView.layer addAnimation:scaleAnimation forKey:nil];
        
        //透明度动画
        CABasicAnimation *alphaAnimation = [CABasicAnimation animationWithKeyPath:@"opacity"];
        alphaAnimation.fromValue = @1.0;
        alphaAnimation.toValue = @0.0;
        //alphaAnimation.duration = 2.0;
        //[self.imageView.layer addAnimation:alphaAnimation forKey:nil];
        
        //创建动画组,将所有动画对象添加到组中
        //针对组设置的动画属性,会被应用到组中的每一个动画上面
        CAAnimationGroup *group = [CAAnimationGroup animation];
        group.animations = @[moveAnimation,scaleAnimation,alphaAnimation];
        group.duration = 2.0;
        group.delegate = self;
        [self.imageView.layer addAnimation:group forKey:nil];
    }
    
    //图片消失
    - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{
        [self.imageView removeFromSuperview];
    }
    
    //生成路线
    -(void)createPath:(UIBezierPath *)path{
        [path moveToPoint:self.imageView.center];
        CGPoint tartgetPoint = CGPointMake(self.view.bounds.size.width-self.imageView.frame.size.width-20, self.view.bounds.size.height-self.imageView.frame.size.height-20);
        CGPoint control1 = CGPointMake(self.view.bounds.size.width-self.imageView.frame.size.width-20, self.imageView.frame.origin.y);
        CGPoint control2 = CGPointMake(self.imageView.frame.origin.x, self.view.bounds.size.height-20-self.imageView.frame.size.height);
        [path addCurveToPoint:tartgetPoint controlPoint1:control1 controlPoint2:control2];
        
    }
    
    @end
            
    补充:动画停止
    //停止
    -(void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag{
        
        self.imageView.layer.transform = CATransform3DRotate(self.imageView.layer.transform,M_PI, 1.0, 1.0, 1.0);
    }
    
            1.6CATransform3D
                    1)是什么
                            是一个4X4的矩阵,一个结构体。描述了一个3D图片变形的数据
                    2)创建
                            CATransform3DMakeRotation/scale/Translation//这组方法在定值常量的基础上变形
                            CATransform3DScale/Rotate/Translate //这组方法是在传入值的基础上进行变形
    =====================================================================
    知识点
    八、 UIKit Dynamic 动力特效
    
    1. UIKit Dynamic 动力特效
    
                1.1是什么
                    中文翻译:UIKit 动力、动力模型。。。。iOS7开始的技术。 提供了一个模拟真实世界中力学相关的动画和交互系统,比如,重力、碰撞、吸附等。UIKit Dynamic可以组合 可重用
    
                 1.2 UIKit  Dynamic架构
                    a。核心部分:UIDynamicAnimator  —>视图的坐标系
                    b。UIDynamic xx Behavior (行为)
                            重力  UIGravityBehavior   (.magnitude 重力的强度,即加速度)
                            碰撞  UICollisionBehavior
                                              //将场景视图的四周翻译成可碰撞的四个边
                          collision.translatesReferenceBoundsIntoBoundary = YES;
                            吸附  UIAttachmentBehavior  
                                               self.attachment.anchorPoint //吸附点 (一个坐标)
                                                           self.attachment.frequency=1;//设置吸附行为的频率(左右晃动的大小)
                           self.attachment.damping=0.1;//设置吸附行为的阻尼(上下弹跳的范围)
                            闪烁
                            推力
                            综合力
    
                    【Demo2_Dynamic】
    
           *****给view添加背景色,显示小方格(方法就是重绘一下图形,利用重写初始化方法:然后设置self.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"BackgroundTile"]];
    
    BackgroundView.h
    #import <UIKit/UIKit.h>
    
    @interface BackgroundView : UIView
    
    @property(nonatomic,strong)UIBezierPath *path;
    
    @end
    BackgroundView.m
    #import "BackgroundView.h"
    
    @implementation BackgroundView
    
    
    //当故事板创建此视图对象时调用此方法,初始化方法
    - (id)initWithCoder:(NSCoder *)aDecoder{
        self = [super initWithCoder:aDecoder];
        if (self) {
            self.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"BackgroundTile"]];
        }
        return self;
    }
    //绘制传入的障碍物图形
    - (void)drawRect:(CGRect)rect
    {
        [[UIColor redColor]setFill];
        [[UIColor greenColor]setStroke];
        [self.path stroke];
        [self.path fill];
    
    }
    @end
    =======================================================================================================
    重力 (点击下落就向下,点击停止即停止)
    ViewController.h
    ViewController.m
    #import "ViewController.h"
    
    @interface ViewController ()
    @property (weak, nonatomic) IBOutlet UIImageView *imageView;
    @property(nonatomic,strong)UIDynamicAnimator *animator;
    @property(nonatomic,strong)UIGravityBehavior *gravityBehavior;
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        // 1.构建场景
        UIDynamicAnimator *animator = [[UIDynamicAnimator alloc]initWithReferenceView:self.view];
        self.animator = animator;
        // 2.创建重力行为对象
        UIGravityBehavior *gravity = [[UIGravityBehavior  alloc]initWithItems:@[self.imageView]];
        self.gravityBehavior = gravity;
        
    }
    - (IBAction)begin:(id)sender {
        // 3.将重力行为添加到场景中
        [self.animator addBehavior:self.gravityBehavior];
    }
    
    - (IBAction)stop:(id)sender {
        [self.animator removeBehavior:self.gravityBehavior];//将重力行为从场景中移除
    }
    
    
    @end
    
    碰撞(依靠重力下落,然后碰到矩形框,改变成红色然后停止)
    CollisionViewController.h
    CollisionViewController.m
    
    #import "CollisionViewController.h"
    #import "BackgroundView.h"
    
    @interface CollisionViewController ()<UICollisionBehaviorDelegate>
    
    @property (weak, nonatomic) IBOutlet UIImageView *imageView;
    @property(nonatomic,strong)UIDynamicAnimator *animator;
    @end
    
    @implementation CollisionViewController
    - (void)viewDidLoad{
        [super viewDidLoad];
        self.imageView.transform = CGAffineTransformMakeRotation(M_PI_4);
    }
    - (void)viewWillAppear:(BOOL)animated
    {
        [super viewWillAppear:animated];
        UIDynamicAnimator *animator = [[UIDynamicAnimator alloc]initWithReferenceView:self.view];
        self.animator = animator;
        //重力行为
        UIGravityBehavior *gravity = [[UIGravityBehavior alloc]initWithItems:@[self.imageView]];
        //设置重力行为的强度
        gravity.magnitude = 1;
        [animator addBehavior:gravity];
        //碰撞行为
        UICollisionBehavior *collision = [[UICollisionBehavior alloc]initWithItems:@[self.imageView]];
        //将场景视图的四周翻译成可碰撞的四个边
        collision.translatesReferenceBoundsIntoBoundary = YES;
        
        //添加一条矩形的障碍物
        UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(20, 360, 280, 30) cornerRadius:10.0];
        BackgroundView *myView = (BackgroundView *)self.view;
        myView.path = path;
        [myView setNeedsDisplay];
        [collision addBoundaryWithIdentifier:@"MyPath1" forPath:path];
        collision.collisionDelegate = self;
        [animator addBehavior:collision];
        
    }
    //添加代理实现方法   碰撞时方框实现变色
    -(void)collisionBehavior:(UICollisionBehavior *)behavior beganContactForItem:(id<UIDynamicItem>)item withBoundaryIdentifier:(id<NSCopying>)identifier atPoint:(CGPoint)p{
        //NSLog(@"...");
        UIImageView *box = (UIImageView *)item;
        box.tintColor = [UIColor redColor];
        box.image = [box.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
    }
    
    @end
    
       吸附(设置移动,并在移动到的点与图片的中心点绘制直线,然后移动到哪,图片就吸附到哪,然后有重力,图片还会摆动)
    AttachmentViewController.h
    AttachmentViewController.m
    #import "AttachmentViewController.h"
    #import "BackgroundView.h"
    
    @interface AttachmentViewController ()
    @property (weak, nonatomic) IBOutlet UIImageView *imageView;
    @property(nonatomic,strong)UIDynamicAnimator *animator;
    @property(nonatomic,strong)UIGravityBehavior *gravity;
    @property(nonatomic,strong)UIAttachmentBehavior *attachment;
    
    @end
    
    @implementation AttachmentViewController
    
    
    - (UIDynamicAnimator *)animator{
        if (!_animator) {
            _animator = [[UIDynamicAnimator alloc]initWithReferenceView:self.view];
        }
        return _animator;
    }
    
    - (UIGravityBehavior *)gravity{
        if (!_gravity) {
            _gravity = [[UIGravityBehavior alloc]initWithItems:@[self.imageView]];
        }
        return _gravity;
    }
    
    - (UIAttachmentBehavior *)attachment{
        CGPoint attachmentAnchor = CGPointMake(self.imageView.center.x, self.imageView.center.y - 100);
        if (!_attachment) {
            _attachment = [[UIAttachmentBehavior alloc]initWithItem:self.imageView attachedToAnchor:attachmentAnchor];
        }
        return _attachment;
    }
    
    - (IBAction)tap:(UIPanGestureRecognizer *)sender {
        CGPoint location = [sender locationInView:self.view];
        //将手势滑动到的点作为吸附行为的锚点
        self.attachment.anchorPoint = location;
    }
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
      
    }
    
    - (void)viewWillAppear:(BOOL)animated{
        [super viewWillAppear:animated];
        [self.animator addBehavior:self.gravity];
        
        self.attachment.action = ^{
            //绘制锚点到中心点的悬挂的线
            UIBezierPath *path = [UIBezierPath bezierPath];
            [path moveToPoint:self.attachment.anchorPoint];
            [path addLineToPoint:self.imageView.center];
            BackgroundView *bgView = (BackgroundView *)self.view;
            bgView.path = path;
            path.lineWidth = 5;
            [bgView setNeedsDisplay];
        };
        [self.animator addBehavior:self.attachment];
    }
    
    @end
             
    
    改:吸附类
      移动的时候会出现绘图绿线和重力作用,当手势停止,一切动作都停止
    AttachmentViewController.h
    AttachmentViewController.m
    
    #import "AttachmentViewController.h"
    #import "BackgroundView.h"
    
    @interface AttachmentViewController ()
    @property (weak, nonatomic) IBOutlet UIImageView *imageView;
    @property(nonatomic,strong)UIDynamicAnimator *animator;
    @property(nonatomic,strong)UIGravityBehavior *gravity;
    @property(nonatomic,strong)UIAttachmentBehavior *attachment;
    
    @end
    
    @implementation AttachmentViewController
    
    
    - (UIDynamicAnimator *)animator{
        if (!_animator) {
            _animator = [[UIDynamicAnimator alloc]initWithReferenceView:self.view];
        }
        return _animator;
    }
    
    - (UIGravityBehavior *)gravity{
        if (!_gravity) {
            _gravity = [[UIGravityBehavior alloc]initWithItems:@[self.imageView]];
        }
        return _gravity;
    }
    
    - (UIAttachmentBehavior *)attachment{
        //设置锚点
        CGPoint attachmentAnchor = CGPointMake(self.imageView.center.x, self.imageView.center.y - 100);
        if (!_attachment) {
            _attachment = [[UIAttachmentBehavior alloc]initWithItem:self.imageView attachedToAnchor:attachmentAnchor];
        }
        return _attachment;
    }
    
    - (IBAction)tap:(UIPanGestureRecognizer *)sender {
        
        
        if (sender.state==UIGestureRecognizerStateBegan) {
            [self.animator addBehavior:self.gravity];
            
            self.attachment.frequency=1;//设置吸附行为的频率(左右晃动的大小)
            self.attachment.damping=0.1;//设置吸附行为的阻尼(上下弹跳的范围)
            [self drawLine];
            [self.animator addBehavior:self.attachment];
    
        }else if(sender.state==UIGestureRecognizerStateChanged){
            CGPoint location = [sender locationInView:self.view];
            //将手势滑动到的点作为吸附行为的锚点
            self.attachment.anchorPoint = location;
             [self drawLine];
        }else if(sender.state==UIGestureRecognizerStateEnded){
            [self.animator removeBehavior:self.gravity];
            [self.animator removeBehavior:self.attachment];
            BackgroundView*view=(BackgroundView*)self.view;
            view.path=nil;
            [view setNeedsDisplay];
        }
        
    }
    //执行绘图功能
    -(void)drawLine{
        self.attachment.action = ^{
            //绘制锚点到中心点的悬挂的线
            UIBezierPath *path = [UIBezierPath bezierPath];
            [path moveToPoint:self.attachment.anchorPoint];
            [path addLineToPoint:self.imageView.center];
            BackgroundView *bgView = (BackgroundView *)self.view;
            bgView.path = path;
            path.lineWidth = 5;
            [bgView setNeedsDisplay];
        };
    
    }
    
    @end
    
        ****补充: 在block块中,只要用到self引用必须要用弱引用
    -(void)drawLine{
        
        //弱引用
        __weak UIAttachmentBehavior* weakAttachment=self.attachment;
        __weak UIImageView*weakImageView=self.imageView;
        __weak BackgroundView*weakBgView=(BackgroundView*)self.view;
        
        self.attachment.action = ^{
            //绘制锚点到中心点的悬挂的线
            UIBezierPath *path = [UIBezierPath bezierPath];
            [path moveToPoint:weakAttachment.anchorPoint];
            [path addLineToPoint:weakImageView.center];
            BackgroundView *bgView = weakBgView;
            bgView.path = path;
            path.lineWidth = 5;
            [bgView setNeedsDisplay];
        };
    
    }
    
    
    4. 闪烁行为 UISnapBehavior
    /*
     闪烁其实就是快速移动到某一点,使用变形动画也可以做到这个效果,
     但是,使用snapBehavior,物体在移动到某点以后
     会晃动以下
     注意:在animator中不能添加两种同样的特效,所以需要先移除以前的行为,再添加新的行为
     
    */
    
    SnapViewController.h
    SnapViewController.m
    #import "SnapViewController.h"
    
    @interface SnapViewController ()
    @property (weak, nonatomic) IBOutlet UIImageView *imageView;
    @property(nonatomic,strong)UIDynamicAnimator*dynamicAnimator;
    @property(nonatomic,strong)UISnapBehavior*snapBehavior;
    @end
    
    @implementation SnapViewController
    
    
    -(UIDynamicAnimator *)dynamicAnimator{
        if (!_dynamicAnimator) {
            _dynamicAnimator=[[UIDynamicAnimator alloc]initWithReferenceView:self.view];
        }
        return _dynamicAnimator;
    }
    
    
    - (IBAction)pan:(UIPanGestureRecognizer *)sender {
        
        CGPoint point=[sender locationInView:self.view];
        //先移除原有的闪烁行为 不然只能移一次
        [self.dynamicAnimator removeBehavior:self.snapBehavior];
        
        self.snapBehavior=[[UISnapBehavior alloc]initWithItem:self.imageView snapToPoint:point];
        [self.dynamicAnimator addBehavior:self.snapBehavior];
    }
    
    @end
            
    5. 推力行为 UIPushBehavior
              //推力角度
        self.pushBehavior.angle=M_PI_4;//右下角
        //推力大小
        self.pushBehavior.magnitude=2;
        //激活力   push手势的特别之处:需要激活,否则不起作用
        self.pushBehavior.active=YES;
    
    如:借助移动手势来实现力的方向
    #import "PushViewController.h"
    
    @interface PushViewController ()
    @property (weak, nonatomic) IBOutlet UIImageView *imageView;
    
    @property(nonatomic,strong)UIDynamicAnimator *animator;
    @property(nonatomic,strong)UIPushBehavior *pushBehavior;
    
    @end
    
    /*
     push手势的特别之处:需要激活,否则不起作用
     设置   .active = YES 
    */
    @implementation PushViewController
    
    - (UIDynamicAnimator *)animator{
        if (!_animator) {
            _animator = [[UIDynamicAnimator alloc]initWithReferenceView:self.view];
        }
        return _animator;
    }
    
    - (void)viewDidAppear:(BOOL)animated{
        [super viewDidAppear:animated];
        
        // 添加碰撞行为,遇到边界则停止
        UICollisionBehavior *collision = [[UICollisionBehavior alloc]initWithItems:@[self.imageView]];
        [collision setTranslatesReferenceBoundsIntoBoundaryWithInsets:UIEdgeInsetsMake(self.topLayoutGuide.length, 0,self.bottomLayoutGuide.length, 0)
         ];
        [self.animator addBehavior:collision];
        
        //添加推力行为
        self.pushBehavior = [[UIPushBehavior alloc]initWithItems:@[self.imageView] mode:UIPushBehaviorModeContinuous];
        [self.animator addBehavior:self.pushBehavior];
    }
    - (IBAction)tap:(UITapGestureRecognizer *)sender {
        CGPoint point = [sender locationInView: self.view];
        CGPoint center = self.imageView.center;
        CGFloat angle = atan2(point.y-center.y, point.x-center.x)+M_PI;
        //powf()函数:求某数的某几次幂
        //sqrt()函数:开平方
        CGFloat distance = sqrt(powf((point.x-center.x), 2)+powf((point.y-center.y), 2));
        
        self.pushBehavior.angle = angle;
        self.pushBehavior.magnitude = distance/10;
        self.pushBehavior.active = YES;
    }
    
    @end
                                              点击哪就从这个方向施力
    
    
    
    练习:SpringMessage
    
    弹簧效果短消息:
    1.思路:
            利用手指移动的距离,以及item离手指点的位置的远近,产生一个变化的值,用这个值来修改所有collectionView中的item的锚点
    
    2.步骤
        step1.首先计算scroll的距离scrollDelta
        step2.为了得到每个item与触摸点的之间的距离,还需要知道触摸点的坐标touchLocation。
        step3.可以根据距离对每个锚点进行设置了:简单地计算了原来锚点与触摸点之间的距离distanceFromTouch,并由此计算一个系数。
        step4.接下来,对于当前的item,我们获取其当前锚点位置,然后将其根据scrollDelta的数值和刚才计算的系数,重新设定锚点的位置。
        step5.最后需要告诉UIDynamicAnimator已经完成了对锚点的更新,现在可以开始更新物理计算,并随时准备collectionView来取LayoutAttributes的数据了。
    SpringLayout.h
    #import <UIKit/UIKit.h>
    
    @interface SpringLayout : UICollectionViewFlowLayout
    @property(nonatomic,strong)UIDynamicAnimator *animator;
    
    @end
    SpringLayout.m
    #import "SpringLayout.h"
    
    /*
     1. 为每一个布局属性对象添加行为,让布局属性对象成为behavior的主体
     2. 控制器再来询问布局属性对象(layoutAttribute)
        时,返回具有行为特征的item
     3. 每当屏幕滚动一点,就根据触点和各个item的位置的远近,计算出一个有一定变化规律的因子,根据这个因子,有规律的调整每一个布局属性对象的attachment Behavior的锚点,就可以实现弹簧效果
     */
    
    @implementation SpringLayout
    
    
    //1. 在vc即将跟布局对象要各个布局属性对象之前
    //就将每一个布局属性对象都添加上 吸附  行为
    -(void)prepareLayout{
        if (!self.animator) {
            self.animator = [[UIDynamicAnimator alloc]initWithCollectionViewLayout:self];
            //得到整个collectionView的尺寸
            CGSize contentSize = [self collectionViewContentSize];
            NSArray *layoutAttributes = [super layoutAttributesForElementsInRect:CGRectMake(0, 0, contentSize.width, contentSize.height)];
            //得到整个collectionView中的所有向的
            //布局属性对象,从而添加 吸附  行为
            for (UICollectionViewLayoutAttributes *attribute in layoutAttributes) {
                UIAttachmentBehavior *spring = [[UIAttachmentBehavior alloc]initWithItem:attribute attachedToAnchor:attribute.center];
                spring.damping = 0.6;
                spring.frequency = 0.8;
                [self.animator addBehavior:spring];
            }
        }
    }
    
    //2.当vc再来询问每一个布局属性对象时,返回
    //修改过的 布局属性对象,或者说返回已经成为
    //吸附行为主体 的 那个布局属性对象
    -(NSArray *)layoutAttributesForElementsInRect:(CGRect)rect{
        
        //体系维护对象 按照指定的矩形区域
        //返回该范围内的行为主体(布局属性对象)
        return [self.animator itemsInRect:rect]
        ;
    }
    
    //3.根据vc传入的单元格的坐标,返回该单元格
    //对应的那个用来布局这个单元格的部署属性对象
    //-(UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath{
    //    return [self.animator layoutAttributesForCellAtIndexPath:indexPath];
    //}
    
    //4.当边界bounds发生变化时,是否更新边界
    //思路:1.不更新边界
    //     2.边界发生变化的原因,是因为有滚动事件发生了
    //     虽然不更新边界,但要针对这个用户的操作
    //     修改一下锚点,以此出现弹簧效果
    -(BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds{
        UIScrollView *scrollView = self.collectionView;
        //获取滚动的距离,其实就是坐标系变换的大小
        CGFloat scrollDistance = newBounds.origin.y - scrollView.bounds.origin.y;
        //手指所在的位置
        CGPoint touchLocation = [scrollView.panGestureRecognizer locationInView:scrollView];
        //计算和修改每一个行为的锚点
        for (UIAttachmentBehavior *spring in self.animator.behaviors) {
            //因为attribute是 behavior 行为的主体
            //所以反过来,从行为上获取 与它绑定的主体
            //就需要访问items属性,由于,该行为只关联
            //了一个主体,所以取firstObject
            UICollectionViewLayoutAttributes *attributes = [spring.items firstObject];
            CGPoint center = attributes.center;
            CGPoint anchorPoint = spring.anchorPoint;
            //手指的触点和项的中心点的远近
            //根据 项 离 手指触点的远近,产生一组
            //不同大小的 新的anchor值
            CGFloat distance = fabsf(touchLocation.y - anchorPoint.y);
            // distance是变化的,所以除以最大距离
            //也就是一屏幕的高度,取个整,算600
            //到底一个小于1的可变化的值
            //用这个值作为变化因子,从而使得滚动距离
            //与项离触点远近的变化规律相同了
            center.y += scrollDistance*(distance/600);
            attributes.center = center;
            // 更新体系内的每一个行为的状态
            [self.animator updateItemUsingCurrentState:attributes];
        }
        
        return NO;
    }
    
    @end
    ViewController.h
    ViewController.m
    #import "ViewController.h"
    #import "SpringLayout.h"
    
    @interface ViewController ()<UICollectionViewDataSource>
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        SpringLayout *layout = [[SpringLayout alloc]init];
        layout.itemSize = CGSizeMake(300,40);
        layout.sectionInset = UIEdgeInsetsMake(0, 10, 0, 10);
        UICollectionView *collectionView = [[UICollectionView alloc]initWithFrame:self.view.frame collectionViewLayout:layout];
        collectionView.showsHorizontalScrollIndicator = NO;
        collectionView.showsVerticalScrollIndicator = NO;
        [collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"MyCell"];
        collectionView.dataSource = self;
        [self.view addSubview:collectionView];
    }
    
    
    -(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
        return  50;
    }
    
    -(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
        UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"MyCell" forIndexPath:indexPath];
        cell.backgroundColor = [UIColor lightGrayColor];
        return cell;
    }
    
    @end
      点击屏幕发生晃动
    ===================================================================
    知识点
    九、通知( NSNotification)
    
    1. 通知(Notification)
    
        1.1  是什么? 是一种观察者模式的具体体现
    
        观察者模式:一个对象(A)想知道另一个对象(B)的状态是否发生了改变。思路就是,在对象B上注册一个观察者,当对象B的状态发生改变时,通知对象A,对象A收到通知后进行相关的处理的一种模式
            
        其中观察者模式的一种解决方案叫做—广播
        系统中的通知  就是广播的体现    
        
    
        1.2 好处
        一个对象不需要知道消息的接收者是谁,就可以将一些消息发送给需要的接收者
            
          有时,发送消息的对象无法知道有哪些对象,有多少对象接收消息,也不知道对象是否存在
          有时,消息的接受者和发送者太远(远 指的不是距离,是关系,如 控制器和视图就很近,但Model离控制器就很远)
    
        1.3 具体用法
            1)收听者:找到通知中心
                NSNotificationCenter,注册要收听的一个具体频道  addObserver
            2)发送者:找到通知中心,创建通知对象(NSNotification),使用通知中心来发送这个消息(postNotification)
            3)收听者  收到消息  处理消息(掉个方法)
            4)停止收听,不需要收听时,找到通知中心,注销 removeObserver
        
        1.4关键的类
            NSNotificationCenter,是一个单例类,使用defaultCenter方法永远返回同一个对象,以此保证中心对象只有一个
            NSNotification 通知类(封装通知的内容等信息)
        
        【Demo2_Notification】创建控制台程序
    Company.h
    #import <Foundation/Foundation.h>
    
    @interface Company : NSObject
    -(void)broadcast;
    @end
    Company.m
    #import "Company.h"
    
    @implementation Company
    -(void)broadcast{
        NSNotificationCenter*center=[NSNotificationCenter defaultCenter];
        //发消息
        [center postNotificationName:@"videoUpdate" object:self userInfo:@{@"title": @"锦绣园",@"episode": @"第15集"}];
        
    }
    @end
    Vap.h
    Vap.m
    #import "Vap.h"
    
    @implementation Vap
    
    -(id)init{
        if ([super init]) {
            NSNotificationCenter*center=[NSNotificationCenter defaultCenter];
            [center addObserver:self selector:@selector(updated:) name:@"videoUpdate" object:nil];
        }
        return self;
    }
    
    -(void)updated:(NSNotification*)notification{
        NSDictionary*message=notification.userInfo;
        NSLog(@"%@已经更新到%@",message[@"title"],message[@"episode"]);
    }
    
    -(void)dealloc{
        [[NSNotificationCenter defaultCenter]removeObserver:self];
        NSLog(@"dealloc执行了");
    }
    @end
    main.m
    #import <Foundation/Foundation.h>
    #import "Company.h"
    #import "Vap.h"
    int main(int argc, const char * argv[])
    {
    
        @autoreleasepool {
            Company*company=[[Company alloc]init];
            Vap*vip=[[Vap alloc]init];
            [company broadcast];
     
            NSLog(@"Hello, World!");
            
        }
        return 0;
    }
    
    2.键盘通知
        
        键盘弹起的通知名称:
            UIKeyboardWillShowNotification
        键盘收起的通知名称
            UIKeyboardWillHideNotification
    
        【Demo3_Keyboard_Notification】
    #import "ViewController.h"
    
    @interface ViewController ()
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
    }
    
    -(void)viewWillAppear:(BOOL)animated{
        [super viewWillAppear:animated];
        // 注册监听
        NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
        [center addObserver:self selector:@selector(keyboardOpen:) name:UIKeyboardWillShowNotification object:nil];
        [center addObserver:self selector:@selector(keyboardClosed:) name:UIKeyboardWillHideNotification object:nil];
    }
    
    -(void)keyboardOpen:(NSNotification *)notification{
        NSDictionary *message = notification.userInfo;
        //获取键盘的起始点(0,264)
        NSValue  *value = message[UIKeyboardFrameEndUserInfoKey];
        CGRect rect = [value CGRectValue];
        NSLog(@"%f,%f",rect.origin.x,rect.origin.y);
        //NSLog(@"%@",message);
    }
    
    -(void)keyboardClosed:(NSNotification *)notification{
        NSLog(@"close.....");
    }
    
    //点击右下角关闭键盘
    - (IBAction)inputFinished:(UITextField *)sender {
        [sender resignFirstResponder];
    }
    
    
    - (void)dealloc{
        [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
        [[NSNotificationCenter defaultCenter]removeObserver:self name:UIKeyboardWillHideNotification object:nil];
    }
    
    @end
    qq聊天程序
    TRMessage.h
    #import <Foundation/Foundation.h>
    
    @interface TRMessage : NSObject
    
    @property(nonatomic)BOOL fromMe;
    @property(nonatomic,strong)NSString *content;
    
    +(NSMutableArray *) demoData;
    
    @end
    
    TRMessage.m
    #import "TRMessage.h"
    
    @implementation TRMessage
    
    + (NSMutableArray *)demoData{
        TRMessage *message = nil;
        
        NSMutableArray *array = [NSMutableArray array];
        
        message = [[TRMessage alloc]init];
        message.fromMe = YES;
        message.content = @"Hello 你好Hello 你好Hello 你好Hello 你好";
        [array addObject:message];
        
        message = [[TRMessage alloc]init];
        message.fromMe = NO;
        message.content = @"干嘛呢";
        [array addObject:message];
        
        message = [[TRMessage alloc]init];
        message.fromMe = YES;
        message.content = @"没干嘛你呢";
        [array addObject:message];
        
        message = [[TRMessage alloc]init];
        message.fromMe = NO;
        message.content = @"呵呵 呵呵呵";
        [array addObject:message];
        
        message = [[TRMessage alloc]init];
        message.fromMe = YES;
        message.content = @"今天的大新闻就是苹果手表终于发布了,好喜欢红色的,但是买不起";
        [array addObject:message];
        
        message = [[TRMessage alloc]init];
        message.fromMe = NO;
        message.content = @"就知道你买不起,那就别买了";
        [array addObject:message];
        
        message = [[TRMessage alloc]init];
        message.fromMe = YES;
        message.content = @"还是你送我吧";
        [array addObject:message];
        
        message = [[TRMessage alloc]init];
        message.fromMe = NO;
        message.content = @"做梦";
        [array addObject:message];
        
        return  array;
    
    
    }
    @end
    TRMessageCell.h
    #import <UIKit/UIKit.h>
    #import "TRMessage.h"
    
    @interface TRMessageCell : UITableViewCell
    @property(nonatomic,strong)TRMessage *message;
    @end
    
    TRMessageCell.m
    #import "TRMessageCell.h"
    
    @interface TRMessageCell ()
    @property (weak, nonatomic) IBOutlet UIImageView *popImageView;
    @property (weak, nonatomic) IBOutlet UILabel *label;
    
    @end
    
    @implementation TRMessageCell
    
    #define CELL_MARGIN_TB      4.0     //气泡上下外边距
    #define CELL_MARGIN_LR      10.0    //气泡左右外边距
    
    #define CELL_CORNOR         18.0    //气泡圆角半径
    #define CELL_TAIL_WIDTH     16.0    //气泡尾巴
    
    #define MAX_WIDTH_OF_TEXT   200.0   //文字宽度限制
    #define CELL_PADDING        8.0        //气泡内边距
    
    
    
    - (void)setMessage:(TRMessage *)message{
        
        _message = message;
        self.label.text = self.message.content;
        
        //根据消息的来源,对label和image进行定位
        if (self.message.fromMe) {//蓝色气泡
            
            //设置标签内容和图片视图中的气泡图片
            self.label.textColor = [UIColor whiteColor];
            
            UIImage *image = [UIImage imageNamed:@"message_i.png"];
            image = [image resizableImageWithCapInsets:UIEdgeInsetsMake(CELL_CORNOR, CELL_CORNOR, CELL_CORNOR, CELL_CORNOR+CELL_TAIL_WIDTH)];
            self.popImageView.image = image;
            
            //1。定位Label
            // 先确定文本的高度
            CGRect rectOfText = CGRectMake(0, 0, MAX_WIDTH_OF_TEXT, 999);
            rectOfText = [self.label textRectForBounds:rectOfText limitedToNumberOfLines:0];
            CGRect frameOfLabel = CGRectZero;
            frameOfLabel.size = rectOfText.size;
            frameOfLabel.origin.y = CELL_MARGIN_TB + CELL_PADDING;
            frameOfLabel.origin.x = self.bounds.size.width - CELL_MARGIN_LR - CELL_TAIL_WIDTH - CELL_PADDING - rectOfText.size.width;
            self.label.frame = frameOfLabel;
            
            //2。定位popImageView的坐标
            CGRect frameOfPop = frameOfLabel;
            frameOfPop.origin.x -=CELL_PADDING;
            frameOfPop.origin.y -=CELL_PADDING;
            frameOfPop.size.width += 2 * CELL_PADDING + CELL_TAIL_WIDTH
            ;
            frameOfPop.size.height += 2 * CELL_PADDING;
            self.popImageView.frame = frameOfPop;
            
            //3.设定单元格的bounds
            CGRect bounds = self.bounds;
            bounds.size.height = frameOfPop.size.height + CELL_MARGIN_TB * 2;
            self.bounds = bounds;
        }else{//灰色气泡
            self.label.textColor = [UIColor darkGrayColor];
            
            UIImage *image = [UIImage imageNamed:@"message_other.png"];
            image = [image resizableImageWithCapInsets:UIEdgeInsetsMake(CELL_CORNOR, CELL_CORNOR+CELL_TAIL_WIDTH, CELL_CORNOR, CELL_CORNOR)];
            self.popImageView.image = image;
            
            CGRect rectOfText = CGRectMake(0, 0, MAX_WIDTH_OF_TEXT, 999);
            rectOfText = [self.label textRectForBounds:rectOfText limitedToNumberOfLines:0];
            
            CGRect frameOfLabel = CGRectZero;
            frameOfLabel.size = rectOfText.size;
            frameOfLabel.origin.x = CELL_PADDING+CELL_MARGIN_LR+CELL_TAIL_WIDTH;
            frameOfLabel.origin.y = CELL_MARGIN_TB + CELL_PADDING;
            self.label.frame = frameOfLabel;
            
            CGRect frameOfPop = frameOfLabel;
            frameOfPop.origin.x -=(CELL_PADDING + CELL_TAIL_WIDTH);
            frameOfPop.origin.y -=CELL_PADDING;
            frameOfPop.size.width += CELL_PADDING*2+CELL_TAIL_WIDTH;
            frameOfPop.size.height += CELL_PADDING*2;
            self.popImageView.frame = frameOfPop;
            
            CGRect bounds = self.bounds;
            bounds.size.height = frameOfPop.size.height + CELL_MARGIN_TB *2;
            self.bounds = bounds;
        }
    }
    @end
    TRMessageViewController.h
    #import <UIKit/UIKit.h>
    
    @interface TRMessageViewController : UIViewController
    
    @property(nonatomic,strong)NSMutableArray *messages;
    
    @end
    TRMessageViewController.m
    #import "TRMessageViewController.h"
    #import "TRMessage.h"
    #import "TRMessageCell.h"
    
    @interface TRMessageViewController ()<UITableViewDataSource,UITableViewDelegate>
    @property (weak, nonatomic) IBOutlet UITableView *tableView;
    @property (weak, nonatomic) IBOutlet UIView *inputTextView;
    @property (weak, nonatomic) IBOutlet UITextField *textField;
    
    @end
    
    @implementation TRMessageViewController
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        self.title = @"Message";
        self.messages = [TRMessage demoData];
        [self.tableView registerNib:[UINib nibWithNibName:@"TRMessageCell" bundle:nil] forCellReuseIdentifier:@"Cell"];
        // 设置view的背景图
        self.inputTextView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"ToolViewBkg_Black.png"]];
        
       
    }
    
    -(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
        return 1;
    }
    
    -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
        return self.messages.count;
    }
    
    -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
        TRMessageCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];
        cell.message = self.messages[indexPath.row];
        return cell;
    }
    
    -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
        //在生成cell的时候,在cell的内部曾经
        //根据图片的大小,修改过cell的bounds属性
        //随着修改bounds属性,cell的frame就自动被
        //修改了,变成我们根据图片计算出来的高度
        UITableViewCell  *cell = [self tableView:tableView cellForRowAtIndexPath:indexPath];
        return cell.frame.size.height;
    }
    
    //注册监听系统键盘的弹起
    -(void)viewWillAppear:(BOOL)animated{
        [super viewWillAppear:animated];
        NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
        
        [center addObserver:self selector:@selector(keyboardAppear:) name:UIKeyboardWillShowNotification object:nil];
        [center addObserver:self selector:@selector(keyboardDisappear:) name:UIKeyboardWillHideNotification object:nil];
    }
    
    //键盘弹起时
    -(void)keyboardAppear:(NSNotification *)notification{
       
        //1.获取键盘的坐标体系
        CGRect frameOfKeyboard = [notification.userInfo[UIKeyboardFrameEndUserInfoKey]CGRectValue];
        
        //2.计算输入框的结束的坐标信息
        CGRect frameOfInputView = self.inputTextView.frame;
        
        frameOfInputView.origin.y = frameOfKeyboard.origin.y - frameOfInputView.size.height;
        
        //3.计算表格需要滚动的距离
        CGPoint offset = self.tableView.contentOffset;
        offset.y += frameOfKeyboard.size.height;
        
        //4.为inputTextView添加动画
        NSTimeInterval duration = [notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
        UIViewAnimationOptions options = [notification.userInfo[UIKeyboardAnimationCurveUserInfoKey] unsignedIntegerValue];
        [UIView animateWithDuration:duration delay:0.0 options:options animations:^{
            //设置动画结束时 输入视图的新的位置
             self.inputTextView.frame = frameOfInputView;
            //动画结束时,修改表格的内容的位置
            self.tableView.contentOffset = offset;
    
        } completion:nil];
    }
    
    //键盘收起时
    -(void)keyboardDisappear:(NSNotification *)notification{
        
        CGRect frameOfInputView = self.inputTextView.frame;
        frameOfInputView.origin.y = self.view.bounds.size.height - frameOfInputView.size.height;
        
        CGPoint newOffSet = CGPointMake(0,self.tableView.contentSize.height - self.tableView.frame.size.height);
        
        NSTimeInterval duration = [notification.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
        UIViewAnimationOptions options = [notification.userInfo[UIKeyboardAnimationCurveUserInfoKey] unsignedIntegerValue];
        [UIView animateWithDuration:duration delay:0.0 options:options animations:^{
            self.inputTextView.frame = frameOfInputView;
            self.tableView.contentOffset = newOffSet;
        } completion:nil];
    }
    
    
    -(void)viewDidDisappear:(BOOL)animated{
        [super viewDidDisappear:animated];
        NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
        [center removeObserver:self forKeyPath:UIKeyboardWillShowNotification];
        [center removeObserver:self forKeyPath:UIKeyboardWillHideNotification];
    }
    
    // 点击键盘右下角的return按键
    - (IBAction)send:(UITextField *)sender {
       // NSLog(@"%f",self.tableView.contentSize.height);
        if (![self.textField.text isEqualToString:@""]) {
            TRMessage *message = [[TRMessage alloc]init];
            message.fromMe = YES;
            message.content = self.textField.text;
            //清空文本框
            self.textField.text = @"";
            //message对象添加到数据源
            [self.messages addObject:message];
            //更新表视图显示新增加的消息
            NSIndexPath *indexPath = [NSIndexPath indexPathForRow:self.messages.count - 1 inSection:0];
            [self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationBottom];
           // NSLog(@"%f",self.tableView.contentSize.height);
        }
        
        //[self.textField resignFirstResponder];
    }
    @end
                        
      故事板TRMessageViewController          TRMessageCell
    
            
    
    注意:第一个检查器中关闭自动布局,xib中image的第五个检查器中,点亮的红线只有保持上左即可,其他的关闭就可以了。tableView中第四个检查器中,Separator改为None,去掉表格线。Selection 改为No Selection,实现运行的时候,去掉点击时显示的灰色区域
    ========================================================================
    知识点
    十、Search Bar 搜索栏
    
    1.Search Bar(旧版本)
      故事板中的添加了Search Bar 然后到第四个检查器 点击勾上Shows Scope Bar  
      单元格要记得在第四个检查器中注册identifier为cell
    Product.h
    #import <Foundation/Foundation.h>
    
    typedef NS_ENUM(NSInteger, ProductType){
        ProductTypeDevice,
        ProductTypeSoftware,
        ProductTypeOther
    };
    
    /*定义商品类,包含名称和类别*/
    @interface Product : NSObject
    
    @property(nonatomic,strong)NSString *name;
    @property(nonatomic)ProductType type;
    
    +(NSArray *)demoData;
    
    @end
    
    Product.m        
    #import "Product.h"
    
    @implementation Product
    
    + (NSArray *)demoData{
        Product *p1 = [[Product alloc]init];
        p1.name = @"iPhone4s";
        p1.type = ProductTypeDevice;
        
        Product *p2 = [[Product alloc]init];
        p2.name = @"iPhone5s";
        p2.type = ProductTypeDevice;
        
        Product *p3 = [[Product alloc]init];
        p3.name = @"iPhone6";
        p3.type = ProductTypeDevice;
        
        Product *p4 = [[Product alloc]init];
        p4.name = @"iPhone6 Plus";
        p4.type = ProductTypeDevice;
        
        Product *p5 = [[Product alloc]init];
        p5.name = @"OS X Yosemite";
        p5.type = ProductTypeSoftware;
        
        Product *p6 = [[Product alloc]init];
        p6.name = @"Airport Time Capsule";
        p6.type = ProductTypeOther;
        
        return @[p1,p2,p3,p4,p5,p6];
    }
    
    @end
    ProductViewController.h
    #import <UIKit/UIKit.h>
    
    @interface ProductViewController : UITableViewController
    
    @property(nonatomic,strong)NSArray *products;
    
    @end
    
    ProductViewController.m
    #import "ProductViewController.h"
    #import "Product.h"
    
    @interface ProductViewController ()<UISearchDisplayDelegate>
    //声明一个数组,用于存储搜索到的结果内容
    @property(nonatomic,strong)NSMutableArray *searchResult;
    @end
    
    @implementation ProductViewController
    
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        
        self.products = [Product demoData];
        
        //创建 searchResult 的实例
        self.searchResult = [NSMutableArray array];
        //为显示数据的表格注册单元格
        [self.searchDisplayController.searchResultsTableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"cell"];
        
    }
    
    /*
     当前控制器已经是两个标题视图的 代理对象了。
     一个表视图指的是TVC自带的表视图
     另一个表视图指的是用于显示搜索结果数据展示的表视图
     */
    
    #pragma mark - Table view data source
    
    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
    {
        return 1;
    }
    
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
    {
        //需要区分参数tableView到底是self.tableView
        //还是searchBar的resultTableView
        //return self.products.count;
        if (tableView == self.searchDisplayController.searchResultsTableView) {
            return self.searchResult.count;
        }else{
            return self.products.count;
        }
    }
    
    
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell" forIndexPath:indexPath];
        Product *product = nil;
        if (tableView == self.view) {
            product = self.products[indexPath.row];
        }else{
            product = self.searchResult[indexPath.row];
        }
        cell.textLabel.text = product.name;
        return cell;
    }
    
    
    //只要在搜索框中修改了搜索的内容,立即执行此方法
    -(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString{
        //根据搜索框内写的字符串进行比对
        //生成搜索结果
        //搜索需要两个数据:文本框中输入的+分段控件中选择的搜索类别
        NSInteger type = self.searchDisplayController.searchBar.selectedScopeButtonIndex;
        [self updateContentForProductName:searchString andType:type];
        return YES;
    }
    
    //只要选择了搜索框下面的分段控件,该方法就执行
    -(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption{
        NSString *inputStr = self.searchDisplayController.searchBar.text;
        [self updateContentForProductName:inputStr andType:searchOption];
        return YES;
    }
    
    
    // 根据输入的文本和选择的类别进行匹配
    -(void)updateContentForProductName:(NSString *)searchString andType:(NSInteger )type{
        NSMutableArray *array = [NSMutableArray array];
        for (Product *p in self.products) {
            //查看字符串B在A中的位置及占用的长度
            //ABCDE -> BCD location = 1 lenght = 3
            NSRange range = [p.name rangeOfString:searchString];
            if (range.length > 0 && p.type==type) {
                [array addObject:p];
            }
        }
        self.searchResult = array;
    }
    
    @end
          
    2.iOS8 Search Bar  (Xcode6)
        参考【Demo3_SearchBar_iOS8】
    思想:创建类:用于展示搜索结果的控制器的显示模型,在主控制器创建执行搜索动作的控制器并与 自己创建的类相联系,并设置搜索下边的三项分类,并且将searchResultsUpdater和searchBar分别设置为代理,遵守协议<UISearchResultsUpdating,UISearchBarDelegate>
    Product.h
    Product.m
    同上
    MainTableViewController.h
    #import <UIKit/UIKit.h>
    
    @interface MainTableViewController : UITableViewController
    
    @property(nonatomic,strong)NSArray *products;
    
    @end
    MainTableViewController.m
    #import "MainTableViewController.h"
    #import "SearchTableViewController.h"
    #import "Product.h"
    
    @interface MainTableViewController ()<UISearchResultsUpdating,UISearchBarDelegate>
    //增加属性:用于控制搜索结果显示的控制器
    @property(nonatomic,strong)SearchTableViewController *searchResultViewController;
    @property(nonatomic,strong)UISearchController *searchController;
    
    @end
    
    @implementation MainTableViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        self.products = [Product demoData];
        [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"cell"];
        
        //创建用于展示搜索结果的控制器实例
        self.searchResultViewController = [[SearchTableViewController alloc]init];
        //创建执行搜索动作的控制器,并制定哪个控制器帮助它显示结果
        self.searchController = [[UISearchController alloc]initWithSearchResultsController:self.searchResultViewController];
        
        //设置搜索控制器的结果更新代理对象
        self.searchController.searchResultsUpdater = self;
        //设置显示的bar的大小和样式
        [self.searchController.searchBar sizeToFit];
        self.searchController.searchBar.scopeButtonTitles = @[@"设备",@"软件",@"其它"]; 显示几个按钮是根据给几个名字
        //将搜索bar添加到表头视图
        self.tableView.tableHeaderView = self.searchController.searchBar;
        
        self.definesPresentationContext = YES;
        
        self.searchController.searchBar.delegate = self;
    }
    
    - (void)searchBar:(UISearchBar *)searchBar selectedScopeButtonIndexDidChange:(NSInteger)selectedScope{
        [self updateSearchResultsForSearchController:self.searchController];
    }
    #pragma mark - UISearchResultUpdating
    -(void)updateSearchResultsForSearchController:(UISearchController *)searchController{
        //用户输入的要搜索的文本信息
        NSString *searchText = searchController.searchBar.text;
        //获取选择的scope按钮是哪个
        NSInteger selectedScopeButton = searchController.searchBar.selectedScopeButtonIndex;
        NSLog(@"%ld",selectedScopeButton);
        NSMutableArray *searchResult = [NSMutableArray array];
        for (Product *p in self.products) {
            NSRange range = [p.name rangeOfString:searchText];
            if (range.length > 0 && p.type==selectedScopeButton) {
                [searchResult addObject:p];
            }
        }
        self.searchResultViewController.resultArray = searchResult;
        [self.searchResultViewController.tableView reloadData];
    }
    
    
    
    #pragma mark - Table view data source
    
    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
        return 1;
    }
    
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
        return self.products.count;
    }
    
    
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell" forIndexPath:indexPath];
        Product *p = self.products[indexPath.row];
        cell.textLabel.text = p.name;
        return cell;
    }
    
    @end
    SearchTableViewController.h
    #import <UIKit/UIKit.h>
    
    @interface SearchTableViewController : UITableViewController
    @property(nonatomic,strong)NSArray *resultArray;
    
    @end
    SearchTableViewController.m
    #import "SearchTableViewController.h"
    #import "Product.h"
    
    @interface SearchTableViewController ()
    
    @end
    
    @implementation SearchTableViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        // 注册cell
        [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"cell2"];
    }
    
    #pragma mark - Table view data source
    
    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
        return 1;
    }
    
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
        return self.resultArray.count;
    }
    
    
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell2" forIndexPath:indexPath];
        Product *p = self.resultArray[indexPath.row];
        cell.textLabel.text = p.name;
        return cell;
    }
    
    @end
    
    1.Size Classes
        
            随着苹果设备的增多,屏幕尺寸越来越多样化,为了解决适配不同设备屏幕的问题,从iOS8开始,推出了一项配合Auto layout一起用的Size Classes技术
    
            核心理念:抛弃屏幕尺寸的概念,将不同种类的设备划分到不同的组合内,制作界面时,关注这一个组别,就等同于对这一个组别下的所有设备进行设计界面。运行时,系统会根据当前设备,判断属于哪个组别,然后找到对应组别下的AutoLayout原则,依据此原则计算坐标
    
            有哪些组别?
                    划分组别的标准: 紧凑型     any   标准型
                                    根据右下角确定,当选到any,即可以包括,
        
    
    4.应用程序间的通信
        
        4.1 什么是应用程序间的通讯?
                一个应用给另一个应用发点信息过去,但很少,如果说,打开图片库、点击分享、打印、共享
    
        4.2 使用场景
                将一个字符串或图片发到微博、微信等应用上
    
        4.3 如何做?
                使用一个叫做UIActivityViewController控制器完成任务
    
        4.4 Activity
                把共享时要操作的项目叫做Activity,比如说,拷贝、打印——是 Activity中的操作,微信、微博这种Activity叫做分享
    
        【Demo4_UIActivityViewController】
    ViewController.h
    ViewController.m
    #import "ViewController.h"
    #import "StringReverseActivity.h"
    
    @interface ViewController ()
    @property (weak, nonatomic) IBOutlet UITextField *textField;
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        
    }
    - (IBAction)shared:(UIButton *)sender {
        
        NSString *text = self.textField.text;
        
        //第一步 创建Activity控制器
        //activityItems:要传递的信息
        //applicationActivities:写nil,系统会
        //列出支持的所有activity
        UIActivityViewController *avc = [[UIActivityViewController alloc]initWithActivityItems:@[text] applicationActivities:nil];
        
        //第二步:设置排除的activity
        avc.excludedActivityTypes = @[UIActivityTypeMail];
        //第三步:显示出VC
        [self presentViewController:avc animated:YES completion:nil];
        
    }
    
    - (IBAction)customActivity:(UIButton *)sender {
        NSArray *itemToShare = @[@"Hello",@"World",@12345];
        
        //第一步创建自定义的Activity的对象
        StringReverseActivity *srActivity = [[StringReverseActivity alloc]init];
        
        //第二步 添加activity到Activity控制器上
        UIActivityViewController *avc = [[UIActivityViewController alloc]initWithActivityItems:itemToShare applicationActivities:@[srActivity]];
        
        //第三步  推出avc
        [self presentViewController:avc animated:YES completion:nil];
        
    }
    
    @end
    
        4.5自定义的Activity
                step1:自己写一个类,继承UIActivity
                step2:实现类内的方法
                             类内的6个方法必须实现
        【Demo4_UIActivityViewController】
    
            接上面的编写
    StringReverseActivity.h
    StringReverseActivity.m
    #import "StringReverseActivity.h"
    
    @interface StringReverseActivity ()<UIAlertViewDelegate>
    
    @property(nonatomic,strong)NSMutableArray *activityItems;
    
    @end
    
    @implementation StringReverseActivity
    
    //第一个:返回自己的Activity的类型,只要唯一即可
    -(NSString *)activityType{
        //获得应用程序所在的沙箱的完整路径
        //NSStringFromClass是根据类,获取类的名称
        return [[NSBundle mainBundle].bundleIdentifier stringByAppendingFormat:@".%@",NSStringFromClass([self class])];
    }
    
    //第二个:不要求唯一,但希望短一点
    //返回activity的名称
    -(NSString *)activityTitle{
        return @"反转";
    }
    
    //第三个:显示的图片 Retina: 86 X 86 ipad: 110 X 110
    -(UIImage *)activityImage{
        return  [UIImage imageNamed:@"icon80"];  图片尺寸不行,所以不显示
    }
    
    
    //第四个:将共享的item传过的数据进行检验,看是否可以反转
    -(BOOL)canPerformWithActivityItems:(NSArray *)activityItems{
        for (id object in activityItems) {
            if ([object isKindOfClass:[NSString class]]) {
                //只要有一个string就调用反转方法
                return YES;
            }
        }
        return NO;
    }
    
    //第5个:查找activity的条目,只要有一个item能用就会到达这个方法
    - (void)prepareWithActivityItems:(NSArray *)activityItems{
        //把所有能反转的item挑出来,放到一个数组中
        NSMutableArray *stringObjects = [NSMutableArray array];
        for (id object in activityItems) {
            if ([object isKindOfClass:[NSString class]]) {
                [stringObjects addObject:object];
            }
        }
        self.activityItems = stringObjects;
    }
    
    //第6个:执行activity,编写逻辑---反转
    -(void)performActivity{
        // 为了保存每一个反转后的string
        NSMutableString *reverseString = [[NSMutableString alloc]init];
        //反转
        for (NSString
              *string in self.activityItems) {
            [reverseString appendString:[self myReverseString:string]];
            [reverseString appendString:@"
    "];
        }
        
        //显示反转的结果
        UIAlertView *alert = [[UIAlertView  alloc]initWithTitle:@"字符串反转" message:reverseString delegate:self cancelButtonTitle:@"确定" otherButtonTitles:nil];
        [alert show];
    }
    
    //第7个:点击alert中的确定按钮后,通知activity动作结束
    -(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
        [self activityDidFinish:YES];
    }
    
    //自定义方法:执行字符串的反转
    -(NSString *)myReverseString:(NSString *)paramString
    {
        NSMutableString *reversed = [[NSMutableString alloc]init];
        for (NSInteger index = paramString.length-1; index>=0; index--) {
            [reversed appendFormat:@"%c",[paramString characterAtIndex:index]];
        }
        return  [reversed copy];
    }
    
    @end
                                 系统默认,去掉了邮件              自定义,多增加了反转                           点击反转,只要是字符串就倒过来显示
                   
    5.横竖屏的判断
            【Demo5_All_Orientation】
          1.设置屏幕支持的方向
          2.获取即将要旋转到的某个朝向
    #import "ViewController.h"
    
    @interface ViewController ()
    @property (weak, nonatomic) IBOutlet UIView *greenVIew;
    
    @property (weak, nonatomic) IBOutlet UIButton *button1;
    @property (weak, nonatomic) IBOutlet UIButton *button2;
    @property (weak, nonatomic) IBOutlet UIButton *button3;
    
    @property (weak, nonatomic) IBOutlet UIButton *button4;
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
    }
    
    //1.设置屏幕支持的方向
    - (NSUInteger)supportedInterfaceOrientations{
        //设置支持的设备方向
        return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscape;
    }
    
    //2.获取即将要旋转到的某个朝向
    -(void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration{
        //判断即将到达的朝向,决定选中何种布局
        if (UIInterfaceOrientationIsPortrait(toInterfaceOrientation)) {
            //竖屏
            [self layoutPortrait];
        }else{
            //横屏
            [self layoutLandscape];
        }
    }
    
    
    //自定义的方法,用于竖屏时布局
    -(void)layoutPortrait{
        self.greenVIew.frame = CGRectMake(20, 20, self.view.bounds.size.width-20-20, self.view.bounds.size.height-20*4-35*2);
        
        CGRect frame = CGRectMake(20, self.view.bounds.size.height-20*2-35*2, 130, 35);
        self.button1.frame = frame;
        
        frame.origin.x +=130+20;
        self.button2.frame = frame;
        
        frame.origin.y += (35+20);
        self.button4.frame = frame;
        
        frame.origin.x -= (130+20);
        self.button3.frame = frame;
        
    }
    
    //自定义的方法,用于横屏时布局
    -(void)layoutLandscape{
        
        
    }
    
    //界面显示前判断好方向,界面显示的时候布置
    -(void)viewWillAppear:(BOOL)animated{
        [super viewWillAppear:animated];
        
        //判断出来的那一刻的方向
        UIApplication *app = [UIApplication sharedApplication];
        UIInterfaceOrientation orientation = app.statusBarOrientation;
        if (UIInterfaceOrientationIsPortrait(orientation)) {
            [self layoutPortrait];
        }else{
            [self layoutLandscape];
        }
    
    }
    
    @end
  • 相关阅读:
    在unity中内置一个查询物流信息功能
    socket 广播消息
    Socket通信
    用SecureCRT在windows和CentOS间上传下载文件
    Centos6.5下设置静态IP
    oracle 11g dataguard创建的简单方法
    linux下mysql安装、目录结构、配置
    dba诊断之lock
    oracle11G在linux环境下的卸载操作
    Ubuntu 14.04(32位)安装Oracle 11g(32位)全过程
  • 原文地址:https://www.cnblogs.com/52190112cn/p/5063200.html
Copyright © 2011-2022 走看看