美文网首页iOS Developer
iOS零星知识点 - 04

iOS零星知识点 - 04

作者: 浮桥小麦 | 来源:发表于2016-06-29 15:56 被阅读160次

    查看提示

    01 UIView 的触摸事件处理
    02 手势识别器----UIGestureRecognizer 的具体手势
    03 屏幕适配相关的东东
    04 CALayer的一些属性
    05 UIView 和 CALayer 的选择
    06 修改 UITableViewCell 距离 UITableView 上下左右边距
    07 自定义控件--纯代码
    08 自定义控件--xib
    09 各种手势操作的示范
    10 NSArray 快速求总和 最大值 最小值 和 平均值
    11 单例模式的宏定义
    12 调节屏幕亮度
    13 导航控制器原理详解
    14 按钮的图片设置问题
    15.监听导航栏左侧的返回按钮(局限只能做简单地逻辑判断处理)
    
    
    pragma mark - 01 UIView 的触摸事件处理
    一根或者多根手指开始触摸 view,系统会自动调用 view 的下面方法:
    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
    
    一根或者多根手指在view上移动,系统会自动调用view的下面方法(随着手指的移动,会持续调用该方法):
    - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
    
    一根或者多根手指离开 view,系统会自动调用 view 的下面方法:
    - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
    
    触摸结束前,某个系统事件(例如电话呼入)会打断触摸过程,系统会自动调用 view 的下面方法:
    - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
    
    【备注】UIImageView 的 userInteractionEnabled 默认就是 NO,
    因此 UIImageView 以及它的子控件默认是不能接收触摸事件的。
    
    pragma mark - 02 手势识别器----UIGestureRecognizer 的具体手势
    (1)UITapGestureRecognizer(敲击)
    (2)UIPinchGestureRecognizer(捏合,用于缩放)
    (3)UIPanGestureRecognizer(拖拽)
    (4)UISwipeGestureRecognizer(轻扫)
    (5)UIRotationGestureRecognizer(旋转)
    (6)UILongPressGestureRecognizer(长按)
    
    pragma mark - 03 屏幕适配相关的东东
    设置一个按钮在父控件的屏幕适配:
    UIViewAutoresizingFlexibleLeftMargin 距离父控件左边的间距是伸缩的
    UIViewAutoresizingFlexibleWidth 自己的宽度跟随着父控件的宽度进行伸缩
    UIViewAutoresizingFlexibleRightMargin 距离父控件右边的间距是伸缩的
    UIViewAutoresizingFlexibleTopMargin 距离父控件顶部的间距是伸缩的
    UIViewAutoresizingFlexibleHeight 自己的高度跟随着父控件的高度进行伸缩
    UIViewAutoresizingFlexibleBottomMargin 距离父控件底部的间距是伸缩的
    举例
    UIButton *btn = [UIButton buttonWithType:UIButtonTypeContactAdd];
    btn.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
    
    pragma mark - 04 CALayer的一些属性
    宽度和高度:
    @property CGRect bounds;
    位置(默认指中点,具体由 anchorPoint 决定):
    @property CGPoint position;
    锚点(x,y 的范围都是 0-1),决定了 position 的含义:
    @property CGPoint anchorPoint;
    背景颜色(CGColorRef 类型):
    @property CGColorRef backgroundColor;
    形变属性:
    @property CATransform3D transform;
    边框颜色(CGColorRef 类型):
    @property CGColorRef borderColor;
    边框宽度:
    @property CGFloat borderWidth;
    圆角半径:
    @property CGColorRef borderColor;
    内容(比如设置为图片 CGImageRef):
    @property(retain) id contents;
    例如:
    //边框宽度
    self.iconView.layer.borderWidth = 10;
    // 边框颜色
    self.iconView.layer.borderColor = [UIColor greenColor].CGColor;
    // 圆角
    self.iconView.layer.cornerRadius = 10;
    // 超出主层边框范围的内容都剪掉
    self.iconView.layer.masksToBounds = YES;
    // 阴影颜色
    self.iconView.layer.shadowColor = [UIColor blueColor].CGColor;
    // 阴影偏差
    self.iconView.layer.shadowOffset = CGSizeMake(20, 20);
    // 阴影不透明度
    self.iconView.layer.shadowOpacity = 0.5;
    
    pragma mark - 05 UIView 和 CALayer 的选择
    • 通过 CALayer,就能做出跟 UIView 一样的界面效果,既然 CALayer 和 UIView 都能实现相同的显示效果,那究竟该选择谁好呢?
    • 其实,对比 CALayer,UIView 多了一个事件处理的功能。也就是说,CALayer 不能处理用户的触摸事件,而 UIView可以。
    • 所以,如果显示出来的东西需要跟用户进行交互的话,用 UIView;如果不需要跟用户进行交互,用 UIView 或者 CALayer 都可以。
    • 当然,CALayer 的性能会高一些,因为它少了事件处理的功能,更加轻量级。
    pragma mark - 06 修改 UITableViewCell 距离 UITableView 上下左右边距
    UITableViewCell 默认是和 UITableView 上下左右边距没有距离的,要想其上下左右都有一段距离,如下:
    方法为重写 UITableViewCell 的 setFrame 方法:
    - (void)setFrame:(CGRect)frame{
    frame.origin.y += 10;
    frame.origin.x = 10
    ;frame.size.width -= 2 * 10;
    frame.size.height -= 10;
    [super setFrame:frame];
    }
    
    pragma mark - 07 自定义控件--纯代码
    • 一般来说我们的自定义类继承自 UIView,首先在 initWithFrame:方法中将需要的子控件加入 view 中。
    1. 注意,这里只是加入到 view 中,不要设置各个子控件的尺寸。为什么要在 initWithFrame:方法而不是在 init 方法?因为使用纯代码的方式创建自定义类,在以后使用的时候可能使用 init 方法创建,也有可能使用 initWithFrame:方法创建,但是无论哪种方式,最后都会调用到 initWithFrame:方法。

    2. 在这个方法中创建子控件,可以保证无论哪种方式都可以成功创建。为什么要在 initWithFrame:方法里面只是将子控件加到 view 而不设置尺寸?前面已经说过,两种方式最后都会调用到 initWithFrame:方法。如果使用 init 方法创建,那么这个 view 的 frame有可能是不确定的:
      CYLView *view = [[CYLView alloc] init];view.frame = CGRectMake(0, 0, 100, 100);...

    3.如果是这种情况,那么在 init 方法中,frame 是不确定的,此时如果在 initWithFrame:方法中设置尺寸,那么各个子控件的尺寸都会是 0,因为这个 view 的 frame 还没有设置。(可以看到是在发送完 init 消息才设置的)所以我们应该保证 view 的 frame 设置完才会设置它的子控件的尺寸。

    4.在 layoutSubviews 方法中就可以达到这个目的。第一次 view 将要显示的时候会调用 layoutSubviews 方法,之后当 view 的尺寸(不是位置)改变时,也会调用这个方法。所以正常的做法应该是在 initWithFrame:方法中创建子控件,注意此时子控件有可能只是一个局部变量,所以想要在 layoutSubviews 访问到的话,一般需要创建这个子控件的对应属性来指向它。
    @property (nonatomic, weak) UIButton *button; // 注意这里使用 weak 就可以,因为 button 已经被加入到self.view.subviews 这个数组里。...
    举例:

    - (instancetype)initWithFrame: (CGRect)frame{
    if (self = [super initWithFrame: frame]) 
    {
    // 创建一个 button
    UIButton *button = ... 
    // 设置 button 的属性
    [button setTitle: ...] 
    // 将 button 加到 view 中,并不设置尺寸
    [self.view addSubview: button]; 
    //将 self.button 指向这个 button 保证在 layoutSubviews 中可以访问
    self.button = button; 
    // 其他的子控件同理
    UILabel *label = ... 
    }
    }这样我们就可以在 layoutSubviews 中访问子控件,设置子控件的尺寸,因为此时 view 的 frame 已经确定。
    - (void)layoutSubviews{
    // 注意,一定不要忘记调用父类的 layoutSubviews 方法!
    [super layoutSubviews]; 
    // 设置 button 的 frame
    self.button.frame = ... 
    // 设置 label 的 frame
    self.label.frame = ... 
    }
    经过以上的步骤,就可以实现自定义控件。
    
    pragma mark - 08 自定义控件--xib
    • 使用 xib 的方式可以省去 initWithFrame:和 layoutSubviews 中添加子控件和设置子控件尺寸的步骤,还有在 viewcontroller 里面设置 view 的 frame,因为添加子控件和设置子控件的尺寸以及整个 view 的尺寸在 xib 中就已经完成。
    • (注意整个 view 的位置还没有设置,需要在控制器里面设置。)我们只需对外提供数据接口,重写 setter 方法就可以显示数据。注意要将 xib 中的类设置为我们的自定义类,这样创建出来的才是自定义类,而不是默认的父类。当然,用 xib 这种方式是需要加载 xib 文件的。
    // 第一种方法(较为常用)
    CYLView *view = [[[NSBundle mainBundle] loadNibNamed:@"CYLView" owner:nil options:nil] firstObject]; 
    //CYLView 代表 CYLView.xib,代表 CYLView 这个类对应的 xib 文件。这个方法返回的是一个 NSArray,我们取第一个 Object 或最后一个(因为这个数组只有一个 CYLView 没有其他对象)就是需要加载的 CYLView。
    // 第二种方法
    UINib *nib = [UINib nibWithNibName:@"CYLView" bundle:nil];
    NSArray *objectArray = [nib instantiateWithOwner:nil options:nil];
    CYLView *view = [objectArray firstObject];
    
    #建议在 awakeFromNib 方法中进行初始化外的额外操作。因为 awakeFromNib 是在初始化完成后调用
    
    比如在 CYLView.h 中提供一个类工厂方法:
    + (instancetype)viewWithBook: (Book *)book;
    然后在 CYLView.m 中实现这个方法:
    + (instancetype)viewWithBook: (Book *)book
    {
    CYLView *view = [[[NSBundle mainBundle] loadNibNamed: NSStringFromClass(self) owner: nil opetions: nil]firstObject];
    view.book = book;
    return view;
    }
    这样外界只需用 viewWithBook:方法传入一个 book,就可以创建一个 CYLView 的对象,而具体是怎么创建的,只有 CYLView 才知道。
    
    pragma mark - 09 各种手势操作的示范

    轻击手势(TapGestureRecognizer)

    //新建tap手势 
    UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapGesture:)]; 
    //设置点击次数和点击手指数 
    tapGesture.numberOfTapsRequired = 1; //点击次数 
    tapGesture.numberOfTouchesRequired = 1; //点击手指数 
    [self.view addGestureRecognizer:tapGesture]; 
    
    //轻击手势触发方法 
    -(void)tapGesture: (id)sender 
    { //轻击后要做的事情
    }
    

    长按手势(LongPressGestureRecognizer)

    //添加长摁手势 
    UILongPressGestureRecognizer *longPressGesture = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressGesture:)]; 
    //设置长按时间 
    longPressGesture.minimumPressDuration = 0.5; //(2秒) 
    [self.view addGestureRecognizer:longPressGesture]; 
    在对应的回调方法中添加相应的方法(当手势开始时执行):
     
    //常摁手势触发方法 
    -(void)longPressGesture:(id)sender 
    { 
    UILongPressGestureRecognizer *longPress = sender; 
    if (longPress.state == UIGestureRecognizerStateBegan) 
    { 
     
    UIAlertView *alter = [[UIAlertView alloc] initWithTitle:@“提示” message:@“长按触发” delegate:nil cancelButtonTitle:@“取消” otherButtonTitles: nil]; 
    [alter show]; 
    } 
    }
    手势的常用状态如下
    开始:UIGestureRecognizerStateBegan
    改变:UIGestureRecognizerStateChanged
    结束:UIGestureRecognizerStateEnded
    取消:UIGestureRecognizerStateCancelled
    失败:UIGestureRecognizerStateFailed
    

    轻扫手势(SwipeGestureRecognizer)

    //添加轻扫手势 
    UISwipeGestureRecognizer *swipeGesture = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeGesture:)]; 
    //设置轻扫的方向 
    swipeGesture.direction = UISwipeGestureRecognizerDirectionRight; //默认向右 
     [self.view addGestureRecognizer:swipeGesture]; 
     
     
     //添加轻扫手势 
     UISwipeGestureRecognizer *swipeGestureLeft = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(swipeGesture:)]; 
     //设置轻扫的方向 
     swipeGestureLeft.direction = UISwipeGestureRecognizerDirectionLeft; //默认向右 
     [self.view addGestureRecognizer:swipeGestureLeft];
    
    //轻扫手势触发方法 
    -(void)swipeGesture:(id)sender 
    { 
    UISwipeGestureRecognizer *swipe = sender; 
    if (swipe.direction == UISwipeGestureRecognizerDirectionLeft) 
    { 
    //向左轻扫做的事情 
    } 
    if (swipe.direction == UISwipeGestureRecognizerDirectionRight) 
    { 
     //向右轻扫做的事情 
    } 
    } 
    

    捏合手势(PinchGestureRecognizer)

    //添加捏合手势 
    UIPinchGestureRecognizer *pinchGesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(pinchGesture:)]; 
    [self.view addGestureRecognizer:pinchGesture]; 
    捏合手势要触发的方法(放大或者缩小图片):
     
     ////捏合手势触发方法 
    -(void) pinchGesture:(id)sender 
    { 
    UIPinchGestureRecognizer *gesture = sender; 
     //手势改变时 
    if (gesture.state == UIGestureRecognizerStateChanged) 
    { 
    //捏合手势中scale属性记录的缩放比例 
    _imageView.transform = CGAffineTransformMakeScale(gesture.scale, gesture.scale); 
    } 
     //结束后恢复 
    if(gesture.state==UIGestureRecognizerStateEnded) 
    { 
    [UIView animateWithDuration:0.5 animations:{ 
    _imageView.transform = CGAffineTransformIdentity;//取消一切形变 
    }]; 
    } 
    } 
    

    拖动手势(PanGestureRecognizer)

    //添加拖动手势 
    UIPanGestureRecognizer *panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panGesture:)]; 
    [self.view addGestureRecognizer:panGesture]; 
    
    //拖动手势 
    -(void) panGesture:(id)sender 
    { 
    UIPanGestureRecognizer *panGesture = sender; 
     CGPoint movePoint = [panGesture translationInView:self.view]; 
     //做你想做的事儿 
    } 
    

    旋转手势(RotationGestureRecognizer)

    //添加旋转手势 
     UIRotationGestureRecognizer *rotationGesture = [[UIRotationGestureRecognizer alloc] initWithTarget:self action:@selector(rotationGesture:)]; 
     [self.view addGestureRecognizer:rotationGesture]; 
     //旋转手势 
    -(void)rotationGesture:(id)sender 
     { 
     UIRotationGestureRecognizer *gesture = sender; 
     if (gesture.state==UIGestureRecognizerStateChanged) 
    { 
    _imageView.transform=CGAffineTransformMakeRotation(gesture.rotation); 
    } 
     if(gesture.state==UIGestureRecognizerStateEnded) 
    { 
    [UIView animateWithDuration:1 animations:{ 
    _imageView.transform=CGAffineTransformIdentity;//取消形变 
    }]; 
    } 
    }
    
    pragma mark - 10 NSArray 快速求总和 最大值 最小值 和 平均值
    NSArray *array = [NSArray arrayWithObjects:@"5.0", @"2.3", @"8.0", @"3.0", @"10", nil];
    CGFloat sum = [[array valueForKeyPath:@"@sum.floatValue"] floatValue];
    CGFloat avg = [[array valueForKeyPath:@"@avg.floatValue"] floatValue];
    CGFloat max =[[array valueForKeyPath:@"@max.floatValue"] floatValue];
    CGFloat min =[[array valueForKeyPath:@"@min.floatValue"] floatValue];
    NSLog(@"%f\n%f\n%f\n%f",sum,avg,max,min);
    

    pragma mark -- 11 单例模式的宏定义

    singleton.h文件
    
    //##:连接字符串和参数
    //拖进工程就可以用了,传入自己的单例名就好
    #define singleton_h(name) + (instancetype)shared##name;
    
    #define singleton_m(name) \
    static id _instance; \
    + (id)allocWithZone:(struct _NSZone *)zone \
    { \
        static dispatch_once_t onceToken; \
        dispatch_once(&onceToken, ^{ \
            _instance = [super allocWithZone:zone]; \
        }); \
        return _instance; \
    } \
     \
    + (instancetype)shared##name \
    { \
        static dispatch_once_t onceToken; \
        dispatch_once(&onceToken, ^{ \
            _instance = [[self alloc] init]; \
        }); \
        return _instance; \
    } \
     \
    + (id)copyWithZone:(struct _NSZone *)zone \
    { \
        return _instance; \
    }
    

    pragma mark — 12 调节屏幕亮度

    方法:
    [[UIScreen mainScreen] setBrightness: value];
    value:value就是屏幕的亮度值  这个值介于0和1之间
    
    另外 这个方法  会即时刷新  无需手动刷新  但这个方法是调整整个手机界面的亮度的  并不仅仅是某个app的亮度  也就是说这个亮度就是在你完全退出这个app后还是会保持的 所以当我们不需要这个亮度继续保持的时候 我们需要在app的代理方法里做些处理 :
    //这个方法会在app失去激活状态的时候调用  比如说程序进入后台
    - (void)applicationWillResignActive:(UIApplication *)application {
     [[UIScreen mainScreen] setBrightness: 0.5];//0.5是自己设定认为比较合适的亮度值
    }
    //获取当前屏幕的亮度:
    CGFloat *currentLight = [[UIScreen mainScreen] brightness];
    另外,屏幕的亮度调节只能在真机上看到效果 在模拟器上看不到效果
    
    

    pragma mark — 13 导航控制器原理详解

     程序一进入时,就要让窗口的根控制器是一个导航控制器.
        1.新建窗口
        2.创建导航控制器.并设置导航控制器的根控制器
        3.把导航控制器设为窗口的根控制器.
        4.显示窗口.
    
     说明:1.当设置导航控制器的根控制器时,也就是initWithRootViewController,
                它底层其实是调用了导航控制器的push方法.把该控制器添加为导航控制器的子控制器.
                并且它会把该控制器的View添加到导航控制器专门存放子控制器的View上面.
    
             2.把导航控制器设为窗口的根控制器时,它就会把导航控制器的View添加到窗口的View上面.
                所以程序一运行时, 我们看到的就是一个导航控制器的View.
                导航控制器的View内部默认有两个子view.一个是导航条, 一个是转专存放子控制器的View.
                现在专门存放子控制器的View里面存放的就是导航控制器根控制器的View.
    
                导航控制器的子控制器都是存放到一个栈中.也就是一个数组当中.
    
        当调用导航控制器的push方法时, 就会把一个控制器压入到导航控制器的栈中.
        那么刚压入栈中的这个导航控制器就在栈的最顶部.
        它就会把原来导航控制器View当中存放的子控制器View的内容移除,
        然后把导航控制器栈顶控制器的View添加到导航控制器专门存放子控制器View当中.
        注意:只是把控制器的View从导航控制器存放子控制器的View当中移除,并没有把控制器从栈中移除.所以上一个控制器还在.
    
        当调用pop当方法时, 就会把导航控制器存放子控制器View当中控制器的View移除,并且会把该控制器从栈里面移除.
        此时该控制器就会被销毁.接着它就会把上一个控制器的View添加到导航控制器专门存放子控制器的View当中.
    

    pragma mark — 14 按钮的图片设置问题

    #1.有时我们给按钮设置了不可交互,然后按钮上又有图片,这时图片会变为灰色
    解决方法— btn.adjustsImageWhenDisabled = NO;
    
    #2.btn.contentEdgeInsets  = UIEdgeInsetsMake(0,0,0,0);
    这个属性是设置btn内部内容到边界的距离的。 如果按钮的宽高为100,100. 我设置了UIEdgeInsetsMake(10,10,10,10);,那么实际按钮内部可显示控件区域为(80,80)
    
    

    pragma mark — 15.监听导航栏左侧的返回按钮(局限只能做简单地逻辑判断处理)

    - (void)viewWillDisappear:(BOOL)animated
    {
        if ([self.navigationController.viewControllers indexOfObject:self]==NSNotFound)
        {
            NSLog(@"clicked navigationbar back button");
        }
    }
    
    
    

    相关文章

      网友评论

        本文标题:iOS零星知识点 - 04

        本文链接:https://www.haomeiwen.com/subject/bwqxjttx.html