OC学习项目

iOS-static const extern与多个关键字的使用

2017-06-19  本文已影响237人  wxkkkkk

静态变量、静态常量、全局变量

静态变量
  • 当我们希望一个变量的作用域不仅仅是作用域某个类的某个对象,而是作用域整个类的时候,这时候就可以使用静态变量。

static

static修饰的变量,是一个私有的全局变量。
C或者Javastatic关键字修饰的变量,可以使用类名直接拿到这个变量对象,在其他类中可以进行修改。但是在OCstatic修饰的变量是不能通过类名直接访问的,它只作用于它声明所在的.m文件中。
static修饰的变量必须放在@implementation外面或方法中,它只在程序启动初始化一次。

static int num;

静态常量

const

  • const修饰的变量是不可变的,如果需要定义一个时间间隔的静态常量,就可以使用const修饰。
NSString * const myName = @"wxk";

如果试图修改myName编译器则会报错。

如果我们定义一个字符串类型的静态常量就要注意了,这两种写法是一样的,而且是可以修改的。

static NSString const * myName = @"wxk";
static const NSString * myName = @"wxk";

这两种写法const修饰的是* myName,*是指针指向符,也就是说此时指向内存地址是不可变的,而内存保存的内容时可变的。
所以我们应该这样写:

static NSString * const myName = @"wxk";

当我们定义一个对象类型常量的时候,要将const修饰符放到*指针指向符后面。
结论:const右边的总不能被修改

想了解更多点击关于iOS 宏(define)与常量(const)的正确使用


全局变量

** extern**

比如在 ViewController的.m文件里 定义myName
#import "ViewController.h"
#import "FirstViewController.h"
NSString * myName = @"wwxxkk";
@interface ViewController ()
@end

(我们从ViewController跳转到FirstViewController)

在FirstViewController的.m文件里使用extern查找myName,然后打印myName的值
#import "FirstViewController.h"
extern NSString * myName;
@interface FirstViewController ()
@end
@implementation FirstViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    NSLog(@"myName = %@",myName);
    //2017-06-19 21:43:12.434 112233[4696:381459] myName = wwxxkk
}
@end

static与extern是一对“水火不容”的家伙,也就是说extern和static不能同时修饰一个变量;其次,static修饰的全局变量声明与定义同时进行,也就是说当你在头文件中使用static声明了全局变量后,它也同时被定义了;最后,static修饰全局变量的作用域只能是本身的编译单元,也就是说它的“全局”只对本编译单元有效,其他编译单元则看不到它.


关键字

OBJC_IVAR_$类名$属性名称 // 该属性的“偏移量” (offset),这个偏移量是“硬编码” (hardcode),表 示该变量距离存放对象的内存区域的起始地址有多远

实际流程:
每次增加一个属性,系统都会在 ivar_list 中添加一个成员变量的描述,在 method_list 中增加 setter 与 getter 方法的描述,在 prop_list 中增加一个属性的描述,计算该属性在对象中的偏移量,然后给出 setter 与 getter 方法对应的实现。
在 setter 方法中从偏移量的位置开始赋值,在 getter 方法中从偏移量开始取值,为了能够读取正确字节数,系统对象偏移量的指针类型进行了类型强转。


关键字 注释
readwrite 此标记说明属性会被当成读写的,这也是默认属性。
readonly 此标记说明属性只可以读,也就是不能设置,可以获取。
assign 不会使引用计数加1,也就是直接赋值。
retain 会使引用计数加1。
copy 建立一个索引计数为1的对象,在赋值时使用传入值的一份拷贝。
nonatomic 非原子性访问,多线程并发访问会提高性能。
atomic 原子性访问。
**strong ** 打开ARC时才会使用,相当于retain
weak 打开ARC时才会使用,相当于assign,可以把对应的指针变量置为nil。


delegate 代理属性,代理属性也可使用
assign自身已经对它进行一次强引用,没有必要再强引用一次,此时也会使用 weak
自定义IBOutlet 控件属性一般也使用weak;当然,也可以使用 strong,但是建议使用 weak

weak 策略在属性所指的对象遭到摧毁时,系统会将 weak 修饰的属性对象的指针指向 nil,在 OC 给 nil 发消息是不会有什么问题的;如果使用 assign 策略在属性所指的对象遭到摧毁时,属性对象指针还指向原来的对象,由于对象已经被销毁,这时候就产生了野指针,如果这时候在给此对象发送消息,很容造成程序奔溃assigin 可以用于修饰非 OC 对象,而 weak必须用于 OC 对象。



copy 关键字


关键字                            注释
浅复制(shallow copy)    在浅复制操作时,对于被复制对象的每一层都是指针复制。
深复制(one-level-deep copy)  在深复制操作时,对于被复制对象,至少有一层是深复制。
完全复制(real-deep copy)     在完全复制操作时,对于被复制对象的每一层都是对象复制。

非集合类对象的 copy 与 mutableCopy
[不可变对象 copy] // 浅复制 
[不可变对象 mutableCopy] //单层深复制
[可变对象 copy] //单层深复制
[可变对象 mutableCopy] //单层深复
这里需要注意的是集合对象的内容复制仅限于对象本身,对象元素仍然是指针复制。
上一篇 下一篇

猜你喜欢

热点阅读