iOS

iOS疑难点

iOS疑难点总结,不定期更新

Posted by 袁平 on February 27, 2019

前言

iOS疑难点总结,部分摘自参考链接


正文


self.var还是_var?

在iOS中常见到如下写法:

@interface Demo ()

@property(nonatomic, strong) NSString *name;

@end

@implementation Demo

- (void)test {
    _name = @"";
//    self.name = @"";
}

@end

在上述写法中,self.name_name有什么区别呢?

在解释其区别之前,需要先了解一下OC中的属性和实例变量,实例变量具有私有性,一般仅在类内部使用,为了方便给外界读写这个实例变量,就有了属性(@property)

在iOS第一版中,需要同时声明属性和底层实例变量,那时,属性是oc语言的一个新的机制,并且要求必须声明与之对应的实例变量;如下:

// MyViewController.h

@interface MyViewController : UIViewController
{
    UIButton *myButton; // 实例变量
}

@property (nonatomic, retain) UIButton *myButton; // 属性

@end

之后,苹果将默认编译器从GCC转换为LLVM(low level virtual machine),从此不再需要为属性声明实例变量了。如果LLVM发现一个没有匹配实例变量的属性,它将自动创建一个以下划线开头的实例变量(即var属性及与其对应的_var实例变量),如下:

// MyViewController.h

@interface MyViewController : UIViewController

@property (nonatomic, retain) UIButton *myButton; // 将自动创建一个_myButton实例变量与之对应

@end

在MyViewController.m中可以直接使用_myButton实例变量,也可以通过self.myButton来访问,二者的区别也是下面要讲解的;

再来看下面一个例子:

// MyViewController.h

@interface MyViewController : UIViewController
{
    NSString *name; // 实例变量
}

@end

在MyViewController.m文件中,如果通过self.name访问的话,编译器会报错,Xcode会提示使用->,即使用self->name,这是因为OC中点表达式表示调用方法,而这里的name是一个实例变量,没有与其对应的name方法

另外,还有一个与@property合用的@synthesize,通过@synthesize还可以指定与属性对应的实例变量名,如下:

// MyViewController.h

@interface MyViewController : UIViewController

@property (nonatomic, retain) UIButton * myButton;

@end

// MyViewController.m

@implementation MyViewController

@synthesize myButton = otherButton;

@end

此时,与属性myButton对应的实例变量名为otherButton了,默认的_myButton就不能使用了;还需要注意的一点是,如果只是声明了@synthesize myButton;,那么此时默认与myButton对应的实例变量名为myButton,_myButton也不能用了

到这里我们应该知道了使用self.var_var的区别,即self.var实际上是调用了属性方法,即getter和setter方法,而_var是直接调用的实例变量,不会走getter和setter方法;因此,这里需要注意的是,当我们要重写getter方法时,在getter方法中必须使用_var实例变量,否则会造成getter方法的递归调用;同理,重写setter方法时,在setter方法中也只能使用_var实例变量,否则也会造成settter方法的递归调用;另外,直接访问实例变量的话,就不会调用其setter方法,这样就绕过了为相关属性所定义的内存管理语义。例如:在ARC下直接访问一个语义为copy的属性,那么并不会copy该属性,而仅仅是保留新值并释放旧值

参考链接:

  1. https://www.jianshu.com/p/48056965ddce
  2. http://www.cnblogs.com/crazypebble/archive/2013/11/23/3439261.html

@property与@synthesize

我们知道@property可用于在头文件中声明getter和settter方法,@synthesize方法可用于.m文件中实现getter和setter方法;但是实际情况是,如果我们只是在头文件中使用了@property,而没有在.m文件中使用@synthesize,编译器实际上还是会为我们生成getter和setter方法;这是因为从Xcode 4.4 开始,@synthesize属性是默认声明了的

参考链接:

  1. https://stackoverflow.com/questions/7496463/objective-c-property-declaration-without-implementation-synthesize

扩展(extension)与分类(category)

参考链接:

  1. https://www.jianshu.com/p/9e827a1708c6
  2. https://blog.csdn.net/hherima/article/details/44242469

宏定义中的do{}while(0)使用

参考链接:

  1. https://blog.csdn.net/luoweifu/article/details/38563162

Toolbar,Tab Bar和NavigationBar的区别

ToolbarTab Bar都是显示在App的底部,Toolbar中包含的内容和当前界面相关,比如:添加一个Item,删除一个Item,拍照等;Tab Bar是用于在不同界面之间切换的;需要注意的是,ToolbarTab Bar不能在同一个界面中使用

NavigationBar是顶部的导航栏