美文网首页
iOS-大小坑

iOS-大小坑

作者: a_超 | 来源:发表于2017-05-10 20:40 被阅读13次

    本文大体是一些细节性的小坑,不定期更新,欢迎纠正。

    关于变量的读写


    变量的读写通常使用 self. 和 _ 两种方式,但他们有什么区别呢?我们先看下面两个例子。

    @property (nonatomic, strong) NSMutableString * str1;
    @property (nonatomic, copy) NSMutableString * str2;
    

    假设我们定义了两个变量,一个用strong属性修饰,一个用copy属性修饰。

    NSMutableString * strA = [[NSMutableString alloc] initWithString:@"A"];
    self.str1 = strA;
    self.str2 = strA;
    [strA appendFormat:@"C"];
    NSLog(@"%@, %@", _str1, _str2); // 输出AC, A
    

    第一个例子使用了self.来给变量赋值,由于str2使用了copy属性修饰,因此它给strA创建了一个不可变副本,当strA发生变化时,不影响str2。

    NSMutableString * strB = [[NSMutableString alloc] initWithString:@"B"];
    _str1 = strB;
    _str2 = strB;
    [strB appendFormat:@"C"];
    NSLog(@"%@, %@", _str1, _str2); // 输出BC, BC
    

    第二个例子直接使用来赋值,但是输出的结果却与第一个不一致,str2也发生了改变。
    当我们使用self.方式时,实际上是调用了set方法来对变量赋值,而使用
    赋值时绕过了set方法,因此copy修饰符没生效,采用了默认的strong修饰符,所以str2的值也跟着发生改变。改进方法:

    _str2 = [strB copy];
    

    关于常量的定义


    常量我们通常使用#define或者extern来定义。
    define其实就是个替代宏,编译器在编译的时候会把该位置转为具体的代码,如果使用define来定义常量,并且该常量被应用于多个位置,那么就可能造成内存的浪费。举一个简单的例子:

    #define NAME @"name"
    
    NSString * name1 = [NSString stringWithString:NAME];
    NSString * name2 = [NSString stringWithString:NAME];
    // 上面两行代码在编译的时候就相当于下面这种写法,多开辟了两个name的内存空间
    NSString * name1 = [NSString stringWithString:@"name"];
    NSString * name2 = [NSString stringWithString:@"name"];
    

    因此比较合理的做法是采用extern的方式来声明。

    // 头文件(.h)中定义
    extern NSString * const name;
    // 实现文件(.m),在import下方书写
    NSString * const name = @"name";
    

    这种方式的写法在未使用name这个常量时,它是个nil值不占内存空间。当第一次使用name时,系统自动为其分配内存,并持续存在,后面的第N次使用都相当于访问这块内存。
    另外const的位置也是有讲究的,举个例子:

    NSString * const constVal1 = @"A";
    NSString const * constVal2 = @"B";
    const NSString * constVal3 = @"C";
    
    constVal1 = @"A1"; // 报错
    constVal2 = @"B1";
    constVal3 = @"C1";
    

    constVal1就是我们常规意义上的常量,它的值是无法改变的。而对于constVal2和constVal3它俩是没有区别的,都是代表指针地址不变,但可指向新的值。
    </br></br>

    iOS7的手势返回


    这里说的手势返回并不是指深度定制的返回动画,而是自带的从屏幕边缘滑动返回。
    重新设定导航栏的leftBarButtonItem后会导致手势返回失效,此时可以通过一行简单的代码来使其重新生效:

    self.navigationController.interactivePopGestureRecognizer.delegate
     = (id)self;
    

    但我们的项目通常会给VC设定一个公共的父类,在父类中设置公共样式的leftBarButtonItem,并且把这行代码写在viewDidLoad中。此时会遇到一个问题——在第一个VC中触发边缘手势,然后点击任意可跳转入二级VC的按钮,会发现界面假死了。
    最大的原因就在于把上述代码写在父类的viewDidLoad时,由于第一个VC也继承了该父类,因此也会触发边缘返回手势,但因为已经是栈底了无法返回,就会导致返回出错,导致想要进入二级界面时,界面假死。
    一个合理的解决方案是将其写在viewDidAppear中,并且过滤第一个VC:

    
    - (void)viewDidAppear:(BOOL)animated {
        [super viewDidAppear:animated];
        if([self.navigationController.viewControllers count] >= 2) {
            self.navigationController.interactivePopGestureRecognizer.enabled = YES;
            self.navigationController.interactivePopGestureRecognizer.delegate = (id)self;
        }else{
            self.navigationController.interactivePopGestureRecognizer.delegate = nil;
            self.navigationController.interactivePopGestureRecognizer.enabled = NO;
        }
    }
    

    状态栏

    在iOS7之后控制状态栏的样式通常使用-preferredStatusBarStyle方法来设定状态栏的风格。(注:View controller-based status bar appearance 要设定为 YES)
    但有时候你会发现,在导航控制器里面的VC重写此方法是无效的。原因很简单,主控权不在当前VC中,而是在它的父VC——NavigationController中。有两种解决方式,重写NavC中的-preferredStatusBarStyle方法或-childViewControllerForStatusBarStyle方法。

    - (UIStatusBarStyle)preferredStatusBarStyle
    {
        return [self.topViewController preferredStatusBarStyle];
    }
    // 上下两种方法任选一
    - (UIViewController *)childViewControllerForStatusBarStyle
    {
        return self.topViewController;
    }
    

    另外,状态栏的隐藏是可以带动画,一种是Fade,一种是Slide

    - (BOOL)prefersStatusBarHidden
    {
        return ![UIApplication sharedApplication].statusBarHidden;
    }
    - (UIStatusBarAnimation)preferredStatusBarUpdateAnimation
    {
        return UIStatusBarAnimationSlide;
    }
    - (IBAction)hideOrShowStatusBar:(id)sender {
        [UIView animateWithDuration:0.2 animations:^{
            [self setNeedsStatusBarAppearanceUpdate];
        }];
    }
    

    相关文章

      网友评论

          本文标题:iOS-大小坑

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