[OC summary attribute keyword]

Preface

Attribute keywords are particularly important, summarize and review.

Attribute keywords are keywords used to modify attributes to ensure the normal operation of the program.

1. Classification of attribute keywords

  • Keywords related to memory management: weak, assgin, strong, retain, copy;
  • Thread-safe keywords: monatomic,atomic
  • Keywords for access rights: readonly, readwrite.
  • Keywords for modifying variables: const, static, extern.

2. Memory management keywords

2.1 weak

Weak is often used for OC object type data. After the modified object is released, the pointer address will automatically be set to nil. This is a manifestation of weak references.

  • ⚠️In the ARC environment, in order to avoid circular references, delegates are often weak modified. Modified with assgin under MRC . When an object no longer has a pointer of strong type pointing to it, the object will be released. Even if there is a weak pointer type pointing to it, the weak pointer will be cleared.

2.2 assgin

  • assgin is often used for non-pointer variables and is used to modify basic data types and C data types & id type data. Used for copying basic data types.
  • asssgin does not modify the reference count , and can also be used to modify objects. This is generally not recommended, because the address of the pointer still exists after the object modified by assgin is released, becoming a wild pointer (dangling pointer) without a point.

⚠️: The basic types modified by assgin are all basic data types. The basic data types are allocated on the stack. The variables on the stack are automatically managed by the system and will not cause wild pointers and: delegates under MRC are often assgin. This operation is for deletage, self, etc. themselves generate circular references.

For example: When object A holds B through retain, and the delegate object of B is A, if they are both strong references, the mutual holdings will not be released correctly, resulting in a circular reference.

The difference between weak and assgin

  • The modified objects are different: weak modifies data of OC object type, and assgin modifies basic data variables.
  • Reference Count: Neither increases the reference count.
  • The results after release are different: after the weak-modified object is released, the pointer is automatically nil to avoid access to the wild pointer crash. After the assgin-modified object is released, the pointer still exists and becomes a wild pointer .
  • Modify delegate: assgin under MRC, weak under ARC, both to avoid circular references.

2.3 strong

Strong is the most commonly used modifier, mainly used to modify OC object type data: (NSNumber, NSString, NSArray, NSDate, NSDictionary, model classes, etc.). strong is a strong reference, which is equal to retain under ARC, which is different from weak.

Strong is what we usually call pointer copy (shallow copy). The memory address remains unchanged, but a new pointer is generated. The new pointer and the pointer of the reference object point to the same memory address. No new object is generated, there is one more Pointer to this object.

⚠️: Since a memory address is used, when the content stored in the memory address changes, the attributes will also change.

2.4 copy keyword

It is also used to modify the data of the OC object type. It is also used to modify the block during the MRC period, because the block needs to be copied from the stack area to the heap area during the MRC period. The current ARC system automatically does this for us. That is to say, you can now use strong or copy to modify the block.

The similarity between copy and strong is that they are both strong references, with a reference count + 1, but the object modified by copy is a memory copy. When referencing, a new memory address and pointer will be generated, which is exactly the same as the referenced object, and will not change due to Changed by changes to reference attributes.

The difference between copy keyword and strong

copy: memory copy - deep copy, the memory address is different and the pointer address is also different.
storm: pointer copy - shallow copy, the memory address remains unchanged but the pointer address is different.

Declare two copy attributes and two strong attributes, which are mutable and immutable types:

@property(nonatomic,strong)NSString * Strstrong;
@property(nonatomic,copy)NSString * Strcopy;
@property(nonatomic,copy)NSMutableString * MutableStrcopy;
@property(nonatomic,strong)NSMutableString * MutableStrstrong;

1. Assign values ​​to properties of immutable objects. Check the difference between strong modification and copy modification.

// 不可变对象对属性进行赋值,查看strong修饰和copy修饰的区别
- (void)testNormal {
    
    
    NSString * OriginalStr = @"我已经开始测试了";
    //对 不可变对象赋值 无论是 strong 还是 copy 都是原地址不变,内存地址都为(0x10c6d75c0),生成一个新指针指向对象(浅拷贝)
    self.Strcopy = OriginalStr;
    self.Strstrong = OriginalStr;
    self.MutableStrcopy = OriginalStr;
    self.MutableStrstrong = OriginalStr;
    // 内容
    NSLog(@"原字符串=>%@\n normal:copy=>%@=====strong=>%@\nMutable:copy=>%@=====strong=>%@",OriginalStr,_Strcopy,_Strstrong,_MutableStrcopy,_MutableStrstrong);
    // 内存地址
    NSLog(@"原字符串=>%p\n normal:copy=>%p=====strong=>%p\nMutable:copy=>%p=====strong=>%p",OriginalStr,_Strcopy,_Strstrong,_MutableStrcopy,_MutableStrstrong);
    // 指针地址
    NSLog(@"原字符串=>%p\n normal:copy=>%p=====strong=>%p\nMutable:copy=>%p=====strong=>%p",&OriginalStr,&_Strcopy,&_Strstrong,&_MutableStrcopy,&_MutableStrstrong);
}

}

Please add image description

由上面可以看出,strong修饰的对象,在引用一个对象的时候,内存地址都是一样的,只有指针地址不同,copy修饰的对象也是如此。
为什么呢?不是说copy修饰的对象是生成一个新的内存地址嘛?这里为什么内存地址还是原来的呢?

因为,用不可变对象对属性进行赋值,无论是strong还是copy,都是一样的,原内存地址不变,生成了新的指针地址。

2. Assign attributes to variable objects and see the difference between strong and copy

// 可变对象对属性进行赋值,查看strong和copy的区别
- (void)testMutable {
    
    
    NSMutableString * OriginalMutableStr = [NSMutableString stringWithFormat:@"我已经开始测试了"];
    //对 不可变对象赋值 无论是 strong 还是 copy 都是原地址不变,内存地址都为(0x10c6d75c0),生成一个新指针指向对象(浅拷贝)
    self.Strcopy = OriginalMutableStr;
    self.Strstrong = OriginalMutableStr;
    self.MutableStrcopy = OriginalMutableStr;
    self.MutableStrstrong = OriginalMutableStr;
    [OriginalMutableStr appendFormat:@"改变了"];
    // 内容
    NSLog(@"原字符串=>%@\n normal:copy=>%@=====strong=>%@\nMutable:copy=>%@=====strong=>%@",OriginalMutableStr,_Strcopy,_Strstrong,_MutableStrcopy,_MutableStrstrong);
    // 内存地址
    NSLog(@"原字符串=>%p\n normal:copy=>%p=====strong=>%p\nMutable:copy=>%p=====strong=>%p",OriginalMutableStr,_Strcopy,_Strstrong,_MutableStrcopy,_MutableStrstrong);
    // 指针地址
    NSLog(@"原字符串=>%p\n normal:copy=>%p=====strong=>%p\nMutable:copy=>%p=====strong=>%p",&OriginalMutableStr,&_Strcopy,&_Strstrong,&_MutableStrcopy,&_MutableStrstrong);

Please add image description

在上面的结果可以看出,strong修饰的属性内存地址依然没有改变,但是copy修饰的属性内存值产生了变化。
由此得出结论:
对可变对象赋值 strong 是原地址不变,引用计数+1(浅拷贝)。 copy是生成一个新的地址和对象生成一个新指针指向新的内存地址(深拷贝)

3. Change the value of OriginalMutableStr at this time
Please add image description
. Result:

Please add image description

result:

  1. It is an attribute modified by strong and has been changed accordingly.
  2. When the original value is changed, since OriginalMutableStr is a variable type, it is modified on the original memory address. Neither the pointer address nor the memory address changes, only the data stored in the current memory address changes. Although the pointer address of the attribute modified by strong is different, the pointer points to the original memory address, so it will change with the change of OriginalMutableStr.
  3. ⚠️ Different from strong, the type modified by copy not only has a different pointer address, but also points to a different memory address than OriginalMutableStr, so it will not change with the change of OriginalMutableStr.
Notice
  1. Using self.Strcopy and _Strcopy to assign values ​​also have two different results , because the latter does not call the set method, and the reason why there is a difference between copy and strong is because in the set method , the attribute modified by copy: _Strcopy is called = [Strcopy copy] method .

2.5 Multiple copy modes: copy and mutableCopy operate on container objects

When performing copy operations on container objects (NSArray), there are several types:

  1. copy: only pointer copy is performed
  2. mutableCopy: Copy the content. The single layer here refers to the completion of the deep copy of the NSArray object without processing the objects in the container (the memory addresses of the NSArray objects are different, but the memory addresses of the internal elements remain unchanged)

2.6 Problem summary

  1. What is the difference between shallow copy and deep copy?
  • Shallow copy is just a copy of the memory address. Two pointers point to the same address, the reference count of the copied object is increased, and no new memory allocation occurs.
    Deep copy: The target object pointer and the source object pointer point to two memory spaces with the same content.
    2 characteristics: the reference count of the copied object is not increased, new memory allocation is generated, and 2 blocks of memory appear.
  • To summarize the differences:
    • A shallow copy increases the reference count and does not create new memory.
    • Deep copy does not increase the reference count and will allocate new memory.
  1. Does the copy keyword affect the mutable and immutable properties of an object?
  • Mutable object (mutable) copy and mutableCopy are both deep copies
  • The copy of immutable objects (immutable) is a shallow copy, and mutableCopy is a deep copy.
  • The copy method returns immutable objects. If the copied object is a mutable object, it will also return an immutable object.
    Insert image description here
  1. What problems will occur if NSMutableArray is modified with copy?

There is an uncontrollable problem of calling variable methods, which will cause the program to crash. Assign a value to the Mutable attribute that is declared as copy modified. The process is described as follows:

  • If the NSMutableArray object is assigned, a copy operation will be performed on the mutable object. The copy result is immutable, so the copy will be an NSArray.
  • If the NSArray object is assigned, the immutable object will be copied. The copy result is still immutable, so it will still be an NSArray after copying.
  • So no matter what object is assigned, as long as the copy operation is performed on NSMutableArray, the returned object will be immutable.
    The original attribute declaration is NSMutableArray, and the add or remove method may be called. The result after copying is an immutable object, so once these methods are called, the program will crash.
  1. So what is the difference between strong and weak?
  • strong means pointing to and owning the object. **The reference count of the modified object will be increased by 1.** The object will not be destroyed as long as the reference count is not 0. Of course, forcing it to nil can also destroy it.
  • weak means pointing to but not owning the object. The reference count of the object it modifies will not be incremented . No manual setting is required, the object is destroyed in memory by itself.
  1. How to understand the thread safety of atomic? Are there any hidden dangers?
  • Ensure the thread safety of the setter and getter access methods (only lock the setter and getter methods).
  • Atomic assignment or acquisition of an array can ensure thread safety. However, if you perform operations on the array, such as adding objects to data or removing objects, it is not within the scope of atomic guarantees.
  1. How can a variable modified with a weak attribute be automatically set to nil after the variable has no strong reference?
  • The runtime maintains a weak_table_t weak reference table, which is used to store all weak pointers pointing to a certain object. The weak table is actually a hash table,
    the key is the address of the pointed object, and the value is an array of addresses of weak pointers.
  • When the object is recycled, all weak pointer addresses are arrayed according to the address of the object, and the data in the array is traversed and set to nil.

3. Thread-safe keywords (nonatomic, atomic)

3.1 nonatomic keyword

nonatomic: non-atomic operation, no locking, thread execution is fast, but multiple threads accessing the same property may cause a crash

3.2 atomic keyword

Atomic atomic operation: locking to ensure thread safety of setter and getter access methods (only setter and getter methods are locked). Because the thread is locked, when other threads access the current attribute, they will first complete the current operation of the attribute.

⚠️Note: Atomic only locks the getter/setter methods of properties, so security is only for the getter/setter methods, not the entire thread safety, because a property does not only have setter/getter methods, for example: (if a thread While the getter or setter is in progress, another thread performs a release operation on the property at the same time. If the release is completed first, it will cause a crash)

4. Keywords for modifying variables (const, static, extern)

4.1 Constant const

The constant modifier means immutability and can be used to modify the basic variables and pointer variables on the right (put them in front of whom to modify (basic data variable p, pointer variable *p)).

  1. const type * variable name a: the pointer pointing can be changed, but the content pointed to by the pointer cannot be changed. Const is placed in front of the * sign to constrain the parameter, indicating that *a is read-only. Only address a can be modified, and the memory space accessed cannot be modified through a.
int x = 12;
int new_x = 21;
const int *px = &x; 
px = &new_x; // 改变指针px的指向,使其指向变量y

  1. Type * const variable name: The content pointed to by the pointer can be changed, but the pointing of the pointer cannot be changed. Const is placed after the constraint parameter, which means that a is read-only and the address of a cannot be modified. Only the value accessed by a can be modified, but the address of the parameter cannot be modified.
复制代码int y = 12;
int new_y = 21;
int * const py = &y;
(*py) = new_y; // 改变px指向的变量x的值

4.2 The difference between constant modifier (const) and macro definition (define):

There is not much difference in the memory occupied by using macros and constants. Macros define constants. Constants are placed in the constant area and only one copy of memory is generated.
shortcoming:

  • Compilation time: Macros are precompiled (processed before compilation), and const is the compilation stage . If too many macro definitions are used, the compilation speed will become slower and slower as the project gets larger.
    Macros are not checked and will not report compilation errors, but are just replaced. Const will be compiled and checked, and compilation errors will be reported.

advantage:

  • Macros can define some functions and methods. const cannot.

4.3 static

The object modified by the definition can only be accessed in the current file and cannot be referenced through extern.

By default, the scope of global variables is the entire program (can be referenced through extern). After being modified by static, it can only be referenced by the current file. Other files cannot be referenced by extern.

  1. Static modified global variables: can only be accessed in this file, modify the scope of global variables, and the life cycle will not change. Avoid repeatedly defining global variables (singleton mode)
  2. static modified local variables:
  • Sometimes it is hoped that the value of a local variable in a function will not disappear after the function call is completed but will continue to retain its original value, that is, the storage unit it occupies will not be released, and the variable will already have a value when it is called next time. At this time, you should specify the local variable as a static variable and declare it with the keyword static.
  • Extend the life cycle of local variables (the scope of the variable is not changed, it is only useful in the current scope), and it will not be destroyed until the end of the program.

⚠️Note: When you write this in object A, static int i = 10;the i will still exist after A is destroyed.
When you alloc init an object of A again, you can still get i = 90 in the new object.
Unless you kill the program and enter it again, you can get i = 0. .

Local variables will only generate one copy of memory and will only be initialized once. Allocate it in a static storage area. This variable will not be released during the entire program execution, and its allocated space will always exist.

Static modification of local variables can also extend the life cycle of face-changing.

- (void)test{
    
    
    // static修饰局部变量1
    static int age = 0;
    age++;
    NSLog(@"%d",age);
}
-(void)test2{
    
    
    // static修饰局部变量2
    static int age = 0;
    age++;
    NSLog(@"%d",age);
}

[self test];
[self test2];
[self test];
[self test2];
[self test];
[self test2];

打印 1 1 2 2 3 3

It can be seen that the variable life cycle has been extended, but the scope has not changed.

4.4 Constant extern

It is only used to obtain the value of global variables (including global static variables) and cannot be used to define variables.

Search priority: First search for global variables in the current file. If not found, it will search in other files.

#import "JMProxy.h"
@implementation JMProxy
int ageJMProxy = 20;
@end

@implementation TableViewController
- (void)viewDidLoad {
    
    
    [super viewDidLoad];
    extern int ageJMProxy;
    NSLog(@"%d",ageJMProxy);
}
@end

⚠️ extern cannot be used to define variables.

4.4 Use static and const together

Declare a static global read-only constant. Some of the global variables declared during development do not want the outside world to change and only allow reading.

Common usage scenarios of staic and const in iOS are to replace macros and define a frequently used string constant as a static global read-only variable.

// 开发中经常拿到key修改值,因此用const修饰key,表示key只读,不允许修改。
static  NSString * const key = @"name";

// 如果 const修饰 *key1,表示*key1只读,key1还是能改变。

static  NSString const *key1 = @"name";

4.5 Combined use of extern and const

The same string constant that is frequently used in multiple files can be combined with extern and const.

Combination of extern and const: only one global variable needs to be defined, shared by multiple files

@interface Person : NSObject
extern NSString * const nameKey = @"name"; 
@end

#import "ViewController.h"
@interface ViewController ()

@end
NSString * const nameKey; // 必须用xonst才能访问到 extern与const组合组合修饰的全局变量

Guess you like

Origin blog.csdn.net/weixin_61639290/article/details/131831873