zoukankan      html  css  js  c++  java
  • [BS] 小知识点总结-03

    1.Autolayout中“constrain to margins”

      Autolayout中的页面边距的问题ios8以后的UIView增加了layoutMargins属性,在Storyboard/IB中使用AutoLayout布局时,一般都取消勾选“constrain to margins”,如果勾选,即使你在约束里设置某个控件的上下左右均为0,当查看其真实坐标时,发现x=16,y=20,而且控件的右侧离self.view的最右边也有16point的间距,下边没有间隙。故一般取消勾选即可。

    2. 

    2.1 modal出来的控制器使用下面2个方法都能将其关闭,这两种写法有什么区别啊?
    [self.presentingViewController dismissViewControllerAnimated:YES completion:nil];
    [self dismissViewControllerAnimated:YES completion:nil];

    2.2

        window.rootViewController = tabBarController; //window特有方法,rootVC将与window同生同死

      【tabBarController addChildViewController:navController】; //@property(nonatomic,copy) NSArray *viewControllers;

      navController= [UINavigationController alloc] initWithRootViewController:viewController]; //rootVC被加入导航栈最底部,即navController.viewControllers的第一个元素,与navC同生同死。相当于Sb中Embed in NavigationController。

    注意:

    (1) 以上关系中,viewController的view会被自动添加到以window为基础的UI层级中(注意self.view并没有被直接加到window上,二者之间还有6/7个视图层级)。

    (2) navC和tabC都有切换页面的功能,都有viewControllers属性,又有childViewControllers属性(二者的值完全相同,后者readonly)。而普通的viewController都只有childViewControllers属性,没有viewControllers属性。

    (3) tabBar上面超过5个按钮,那么系统会自动将第5个按钮变为“更多”,第5个及以后的按钮就被放进“more”中。The "More" navigation controller will not be returned by -viewControllers, but it may be returned by -selectedViewController.

    3. UIView.subviews

    所有的UIView都有一个subviews数组属性,管理着它的所有子视图,可以通过以下方法在某个位置插入子视图

      UIView *view = [[UIView alloc]initWithFrame:self.view.frame];

        view.backgroundColor = [UIColor greenColor];

        [self.view insertSubview:view atIndex:0];

    4. 自定义UI控件init方法

    //从Xib创建会调用如下两个方法
    //最先调用
    - (instancetype)initWithCoder:(NSCoder *)aDecoder {
        if (self = [super initWithCoder:aDecoder]) {  
        }
        return self;
    }
    //接着调用
    - (void)awakeFromNib {
    
    }
    //最后调用
    - (void)drawRect:(CGRect)rect {
        [super drawRect:rect];
    }
    
    
    
    //完全代码创建
    //先调用
    - (instancetype)initWithFrame:(CGRect)frame {
        if (self = [super initWithFrame:frame]) {
        }
        return self;
    }
    //然后调用
    - (void)drawRect:(CGRect)rect {
        [super drawRect:rect];
    }

    5.设置UI控件圆角方法

      5.1代码设置(需要获取该控件的引用)

      self.loginButton.layer.cornerRadius = 5;

          self.loginButton.layer.masksToBounds = YES;  //bounds默认是不可见的,只有盖住它才可见。

      5.2在Xib中利用KVC直接设值

      

    6.  

      不管UITextField加载self.view哪个子视图里,在任何一个方法中调用[self.view endEditing]; 都可以把界面上弹出的所有的键盘收回去。

      通过修改某UI控件的约束来实现动画,在修改完约束后,在[UIView animateWithDuration:1.0 animations:^{ [self.view layoutIfNeeded]; }];中不一定非要用该UI控件的父视图来调用layoutIfNeeded方法,最简单的通用方法是直接让self.view重新布局。

    7. 设置背景色的3种方法

        titlesView.backgroundColor = [UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:0.5]; //通用

        titlesView.backgroundColor = [[UIColor whiteColor]colorWithAlphaComponent:0.5];  //设置常见颜色及Alpha

        titlesView.backgroundColor = [UIColor colorWithWhite:1.0 alpha:0.5]; //特殊用法:设置RGB相同的灰色及Alpha

    /*

        + (UIColor *)blackColor;      // 0.0 white 

        + (UIColor *)darkGrayColor;   // 0.333 white

        + (UIColor *)lightGrayColor;  // 0.667 white

        + (UIColor *)whiteColor;      // 1.0 white

        + (UIColor *)grayColor;       // 0.5 white

        + (UIColor *)clearColor;      // 0.0 white, 0.0 alpha

    */

    8. 计算文本框宽高的2种方法 

      NSDictionary *textDict = @{ NSFontAttributeName:[UIFont systemFontOfSize:12] };  

    //方法1:

        CGFloat maxW = self.contentView.frame.size.width - 2* margin;  //限定最大的宽度为:cell宽度-2*margin 

      CGRect textRect = [textStr boundingRectWithSize:CGSizeMake(maxW, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:textDict context:nil];  //如果不限制宽高,就写(MAXFLOAT, MAXFLOAT)

    //方法2:    

      //计算文本框宽高,不设置最大宽度限制,所有文字显示在一横行上(等价于上一种方法不限制宽高)

      CGSize textSize = [text sizeWithAttributes:attrDict];

    9. 根据文字调整宽高sizeToFit:

    [label sizeToFit];      [button sizeToFit];//调整里面的图片框和Label    [button.titleLabel sizeToFit];

    注意:调用sizeToFit会让控件的size立马有值,产生和[self.view layoutIfNeed]类似的效果。

    10.

    取消scrollView和tableView自动布局向下偏移64,要用当前控制器的属性self.automaticallyAdjustsScrollViewInsets = NO;

    注意:该属性是视图控制器的属性,并不是scrollView和tableView的属性。因误以为是scrollView和tableView的属性,在敲代码时Xcode死活没提示。郁闷了一阵,下次不在此栽跟头了。

    //以下写法报错(UIView并没有该属性)

    scrollView.automaticallyAdjustsScrollViewInsets NO; //直接编译报错

    tableView.automaticallyAdjustsScrollViewInsets = NO; //直接编译报错

    //以下属性用于关闭UIView的Autoresizing,一般是在使用AutoLayout给该UIView添加约束前使用。注意别和视图控制器的automaticallyAdjustsScrollViewInsets属性混淆了。

    tableView.translatesAutoresizingMaskIntoConstraints = NO; 

    scrollView.translatesAutoresizingMaskIntoConstraints = NO;

    11.

    //scrollView子控件的frame是参考contentSize左上角(0,0)点来设定的,与scrollView坐标没有关系。

     12. 关于scrollView的一些方法:

     a.通过设置offSet让scrollView匀速滚动:[scrollView setContentOffset:offset animated:YES];

       b.监听setContentOffset停止滚动的时刻:

          //该方法专门监控setContentOffset: animated:方法后的滚动

      - (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView {  }

     c. 监听用户拖动后,停止滚动的时刻:

      //Decelerating的方法特指:用户拖拽过后的减速(用户不施力是匀速滚动)

      - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { }

     

    13.  scrollView.pagingEnabled = YES; //启用分页(拖动时要么滚动一整页,要么不滚动,跟contentOffset有关)

    14. 注意UI控件的viewWithTag:方法(如[self.view viewWithTag:0]),会返回view的视图层级中与给定tag匹配的view,也包含view自身在内。所有的UI控件不设置tag值,默认是0。

    Return:  The view in the receiver’s hierarchy whose tag property matches the value in the tag parameter.

    14.

    tableVC会自动调整tableView顶部内边距为64(状态栏20+导航栏44),即使设置tableViewController.automaticallyAdjustsScrollViewInsets = NO;仍然会被设置向下偏移20(状态栏宽度)。如果想让tableView顶格,需手动设置frame的y = 0;

    //打印继承自scrollView的相关偏移属性
    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
      NSLog(@"tableView.frame:%@",NSStringFromCGRect(tableView.frame));
     NSLog(@"tableView.contentInsets:%@",NSStringFromUIEdgeInsets(tableView.contentInset));//tableVC会自动调整tableView顶部内边距为64
      NSLog(@"tableView.contentOffset:%@",NSStringFromCGPoint(tableView.contentOffset));
      NSLog(@"tableView.contentSize:%@",NSStringFromCGSize(tableView.contentSize));
    }
    
    2016-05-17 18:54:34.622 904. 待办清单ToDoList[45231:2587500] *** -[NSKeyedUnarchiver initForReadingWithData:]: data is NULL
    2016-05-17 18:55:03.588 904. 待办清单ToDoList[45231:2587500] tableView.frame:{{0, 0}, {320, 480}}
    2016-05-17 18:55:03.588 904. 待办清单ToDoList[45231:2587500] tableView.contentInsets:{64, 0, 0, 0}
    2016-05-17 18:55:03.588 904. 待办清单ToDoList[45231:2587500] tableView.contentOffset:{0, -64}
    2016-05-17 18:55:03.588 904. 待办清单ToDoList[45231:2587500] tableView.contentSize:{320, 88}

     15. 设置了tableView的内边距,同时也需要设置滚动条的内边距,否则不协调。

        //设置tableView内边距(此代码必须放到addSubview之前,一显示页面才会生效)

        tableView.contentInset = UIEdgeInsetsMake(CGRectGetMaxY(self.titlesView.frame), 0, self.tabBarController.tabBar.height, 0);

        //设置滚动条的内边距

        tableView.scrollIndicatorInsets = tableView.contentInset;

    16.

      //如果导航栏是半透明的,mj_header在停止刷新后虽然自动隐藏了,但是会被看到。这是只需要设置mj_header允许自动改变透明度即可

        self.tableView.mj_header.automaticallyChangeAlpha = YES;

    17. 使用MJRefreshAutoNormalFooter时的问题

      使用如下代码添加footer刷新:self.tableView.mj_footer = [MJRefreshAutoNormalFooter footerWithRefreshingTarget:self refreshingAction:@selector(loadMoreTopics)];  在数据尚未返回,或者加载失败footer都会跑到最顶部。

    解决方法1: 第一次进来或者每次reloadData否会调一次numberOfRowsInSection:在此方法中控制footer是否隐藏  self.tableView.mj_header.hidden = (self.topics.count == 0);

    解决方法2:直接使用[MJRefreshBackFooter footerWithRefreshingBlock:^(void)refreshingBlock];比较省事,数据为出现或加载失败,footer都会自动隐藏在最下方看不见的地方。

     

    18.

    SVProgressHUD 只需要在第一次尝试的时候采用默认黑色Mask的样式,以后就不需要设置了。

    //提示用户加载失败

    [SVProgressHUD setDefaultMaskType:SVProgressHUDMaskTypeBlack];

     19.

    因UIViewController有这样一个分类,所以对于所有的视图控制器只要是最底层是tabBarController,不管中间隔着多少个控制器,都可以拿到该属性。vc.tabBarController和vc.navigationController属性类似。

    @interface UIViewController (UITabBarControllerItem)

    @property(null_resettable, nonatomic, strong) UITabBarItem *tabBarItem; // Automatically created lazily with the view controller's title if it's not set explicitly.

    @property(nullable, nonatomic, readonly, strong) UITabBarController *tabBarController; // If the view controller has a tab bar controller as its ancestor, return it. Returns nil otherwise.

    @end

     20. 设置ios素材图片的拉伸模式

    21.

     在布局时如果发现某个控件frame尺寸设置正确,但显示出来却不是想要的尺寸frame,一般很可能是因为autoresizing自动伸缩属性(只能设置自身和superView的关系)的影响。解决方法: iconImageView.autoresizingMask = UIViewAutoresizingNone;

    22. UIImageView两种创建方法:

    //1.常规方法: 

    UIImageView *imgView = [[UIImageView alloc]init];  imgView.image = [UIImage imageNamed:@"angle"];

    //2.创建和image同等尺寸的imageView

    UIImageView *imgView1 = [[UIImageView alloc]initWithImage:@"angle"];

    23.

    Xib中加载起来的视图控制器的self.view尺寸是(600,600),此时如果想拿到真实的屏幕尺寸,只能通过[UIScreen mainScreen].bounds来获取屏幕尺寸的准确值。

    //WZShowViewController.h/.m/.xib测试结果如下:

    - (void)viewDidLoad {  

        [super viewDidLoad];

        NSLog(@"self.view:%@",self.view);

    }  //打印结果:self.view:<UIView: 0x7fb72d2ab860; frame = (0 0; 600 600);

     

    24.将UIImage保存到相册:

     UIImageWriteToSavedPhotosAlbum(self.imageView.image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);

    //苹果推荐使用image:didFinishSavingWithError:contextInfo:

    - (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo{

        if (error) {

            [SVProgressHUD showErrorWithStatus:@"保存失败"];

        } else {

            [SVProgressHUD showSuccessWithStatus:@"保存成功"];

        }

    }

    25. 九宫格的写法

        NSArray *images = @[@"video",@"picture",@"text",@"audio",@"publish-review",@"offline"];
        NSArray *titles = @[@"视频",@"图片",@"文字",@"声音",@"审核",@"离线"];
        
        CGFloat buttonW = 72;
        CGFloat buttonH = buttonW + 30;
        CGFloat leadingMargin = 15; //第一个按钮距屏幕左边沿举例
        NSInteger colomns = 3; //每行3个按钮
        NSInteger rows = (images.count % colomns == 0) ? (images.count / colomns) : (images.count/colomns + 1); //计算有多少行
        CGFloat maginX = (screenW - 2 * leadingMargin - colomns * buttonW) / (colomns - 1); //x方向间距
        CGFloat maginY = 15; //y方向间距
        CGFloat row1Y = (screenH - buttonH * rows - maginY * (rows - 1)) * 0.5; //垂直居中
        
        for (int i = 0; i < images.count; i++) {
            
            WZVerticalButton *button = [[WZVerticalButton alloc]init];
            [button setImage:[UIImage imageNamed:images[i]] forState:UIControlStateNormal];
            [button setTitle:titles[i] forState:UIControlStateNormal];
            [button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
            
            button.x = leadingMargin + (i % colomns) * (buttonW + maginX);
            button.y = row1Y + (i / colomns) * (buttonH + maginY);
            button.width = buttonW;
            button.height = buttonH;
    
            [self.view addSubview:button];
        
        }

     26.

    将CGPoint类型包装成对象[NSValue valueWithCGPoint:CGPointMake(100, 100)];

     27. 新建window并显示

    UIWindow *window = [[UIWindow alloc]init];

    window.hidden = NO;

    Note1:想让新建的window显示出来,只需要设置hidden = NO;即可。窗口是老大,别人添加到它上面,它自己想显示,直接取消隐藏即可。

    Note2: [window makeKeyAndVisible]; 等价于 [window makeKeyWindow]; window.hidden = NO;

    Note3: 每个窗口的触摸事件是独立的,不会向后穿透。    

    Note4: 同级别的window,最后设置hidden=NO;的窗口显示在最上面。窗口有3种级别:Normal < StatusBar < Alert 级别。将一个window的windowLevel设置为statusBar级别,然后设置和状态栏一样的frame,相当于自定义状态栏。

    28.

    (1). 设置view的边框和阴影

       

    (2).

    view.layer.masksToBounds = YES;  官方解释:A Boolean indicating whether sublayers are clipped to the layer’s bounds. 设置YES, 则view内部的子layer都会被view.layer.bound所裁剪。  实现阴影效果时,必须设为NO,否则阴影效果消失。设置ImageLayer并显示边框时,必须将masksToBounds设为NO,否则子layer会露出来。

    (3).  

    只要设置layer.cornerRadius=10; 和 layer.borderWidth=3; 就可以显示圆角,和layer.masksToBounds无关,该属性仅影响子layer是否被裁剪。  

    29. 

    (1) 利用transform属性可以对UIView控件进行平移Translation、缩放scale、旋转rotation

    struct CGAffineTransform {

      CGFloat a, b, c, d;

      CGFloat tx, ty;

    };

    创建一个CGAffineTransform类型的transform属性

    view.transform = CGAffineTransformMakeTranslation(CGFloat tx,  CGFloat ty) ;
    view.transform = CGAffineTransformMakeScale(CGFloat sx, CGFloat sy);
    view.transform = CGAffineTransformMakeRotation(CGFloat angle)  //注意:angle是弧度制,并不是角度制

    在某个transform的基础上进行叠加

    CGAffineTransform CGAffineTransformTranslate(CGAffineTransform t, CGFloat tx, CGFloat ty);
    CGAffineTransform CGAffineTransformScale(CGAffineTransform t, CGFloat sx, CGFloat sy);
    CGAffineTransform CGAffineTransformRotate(CGAffineTransform t, CGFloat angle);
     
    清空之前设置的transform属性    view.transform = CGAffineTransformIdentity;

    CG_EXTERN const CGAffineTransform CGAffineTransformIdentity  /* The identity transform: [ 1 0 0 1 0 0 ]. */

    (2) 可以给UIView.layer添加transform.transition、transform.scale、transform.rotation核心动画

     CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"transform.scale"];

        anim.toValue = @0.5;

        anim.repeatCount = MAXFLOAT;

        [self.view.layer addAnimation:anim forKey:nil];

    30. 让layoutSubViews方法中某段代码只执行一次

    //1.使用内部全局BOOL变量记录代码是否被执行过

    static BOOL excuted = NO; //定义内部全局变量

    - (void)layoutSubviews{

      if (excuted == NO) {

      NSLog(@"该代码只会被执行一次!");

      }

      excuted = YES; //全局变量和程序同生同死,只要程序没有重启,下次执行layoutSubviews方法,excuted = YES;中间的代码不会被执行

    }

    //2.使用dispatch_once

      static dispatch_once_t  onceToken;    dispatch_once(&onceToken, ^{  });

     

     

     

     

     

     

     

    iOS开发者交流群:180080550
  • 相关阅读:
    c#中开发ActiveX的学习笔记
    [转]李战大师悟透delphi 第七章 组织你的模块
    在网页中实现QQ的屏幕截图功能
    vs.net的调试小技巧之#define debug(适合新手)
    socket中的byte消息格式设计
    [转]李战大师悟透delphi第五章 包
    [转]李战大师悟透delphi 第九章 多层体系结构
    [转]李战大师悟透delphi第一章 delphi的原子世界
    重温delphi之控制台程序:Hello World!
    silverlight中的socket编程注意事项
  • 原文地址:https://www.cnblogs.com/stevenwuzheng/p/5443751.html
Copyright © 2011-2022 走看看