SoFunction
Updated on 2025-04-11

A brief discussion on several commonly used protocols in iOS NSCoping/NSMutableCopying

1. Some explanations

Speaking of NSCopying and NSMutableCopying protocols, we have to mention copy and mutableCopy.

If the class wants to support copy operations, it must implement the NSCopying protocol, that is, implement the copyWithZone method;

If the class wants to support mutableCopy operations, it must implement the NSMutableCopying protocol, that is, implement the mutableCopyWithZone method;

Some classes in the iOS system have implemented the NSCoping or NSMutableCopying protocol methods. If you send a copy or mutableCopy message to a system class or custom class that does not implement the corresponding method, it will crash.

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Person copyWithZone:]: unrecognized selector sent to instance 0x6080000314c0'

Sending copy and mutableCopy messages is both for copying operations, but the copying methods are slightly different in non-container classes of immutable objects, non-container classes of mutable objects, container classes of mutable objects, and container classes of immutable objects; but the following two points are the same:

Send a copy message, and the copy is an immutable object;

Send mutableCopy message, and the copy is a mutable object;

Therefore, the following operations will cause crash

NSMutableString *test1 = [[NSMutableString alloc]initWithString:@"11111"];
NSMutableString *test2 = [test1 copy];
[test2 appendString:@"22222"];

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSTaggedPointerString appendString:]: unrecognized selector sent to

2. System non-container class

In the non-container classes provided by the system, such as NSString and NSMutableString, there are the following characteristics:

Send copy to an immutable object, and copy the pointer; send a mutalbeCopy message to an immutable object, and copy the content;

NSString *test3 = @"111111";
NSString *test4 = [test3 copy];
NSMutableString *test5 = [test3 mutableCopy];
NSLog(@"test3 is %p, test4 is %p, tast5 is %p",test3,test4,test5);
test3 is 0x10d6bb3a8, test4 is 0x10d6bb3a8, tast5 is 0x600000073e80

Sending copy and mutableCopy messages to mutable objects are both deep copies, that is, content copies;

NSMutableString *test11 = [[NSMutableString alloc]initWithString:@"444444"];
NSString *test12 = [test11 copy]; 
NSMutableString *test13 = [test11 mutableCopy]; 
NSLog(@"test11 is %p, test12 is %p, tast13 is %p",test11,test12,test13);
 
test11 is 0x600000073e00, test12 is 0xa003434343434346, tast13 is 0x600000073dc0

3. System container class

In the container classes provided by the system, such as NSArray and NSDictionary, there are the following characteristics:

Immutable object copy is a shallow copy, that is, pointer copy; sending mutableCopy is a deep copy, that is, content copy;

NSArray *array = [NSArray arrayWithObjects:@"1", nil];
NSArray *copyArray = [array copy];
NSMutableArray *mutableCopyArray = [array mutableCopy];
NSLog(@"array is %p, copyArray is %p, mutableCopyArray is %p", array, copyArray, mutableCopyArray);
array is 0x60800001e580, copyArray is 0x60800001e580, mutableCopyArray is 0x608000046ea0

Both mutable object copy and mutableCopy are single-layer deep copies, that is, single-layer content copies;

NSMutableArray *element = [NSMutableArray arrayWithObject:@1];
NSMutableArray *array = [NSMutableArray arrayWithObject:element];
NSArray *copyArray = [array copy];
NSMutableArray *mutableCopyArray = [array mutableCopy];
NSLog(@"array is %p, copyArray is %p, mutableCopyArray is %p", array, copyArray, mutableCopyArray);
[mutableCopyArray[0] addObject:@2];
NSLog(@"element is %@, array is %@, copyArray is %@, mutableCopyArray is %@", element,array,copyArray, mutableCopyArray);
 
2017-02-22 11:53:25.286 test[91520:3915695] array is 0x600000057670, copyArray is 0x600000000bc0, mutableCopyArray is 0x6080000582a0
2017-02-22 11:53:25.287 test[91520:3915695] element is (
1,
2
), array is (
 (
 1,
 2
)
), copyArray is (
 (
 1,
 2
)
), mutableCopyArray is (
 (
 1,
 2
)
)

4. Custom Classes

Important Note:

1. Therefore, the code design is designed to meet business needs.

2. For custom classes, the same is true for deciding whether to send copy and mutableCopy messages to the object;

1. @property declaration uses copy to modify it

I have to talk about the difference between copy and strong when copying. I will not talk about the issue of reference counting here.

copy: Copy an immutable copy and assign it to the attribute; so when the original object value changes, the attribute value will not change;

strong: It is possible to point to a mutable object. If this mutable object is modified externally, it will affect the property;

@interface Person : NSObject 
@property (nonatomic, copy) NSString *familyname;
@property (nonatomic, strong) NSString *nickname;
@end
Person *p1 = [[Person alloc]init];
 
NSMutableString *familyname = [[NSMutableString alloc]initWithString:@"Zhang San"];
 = familyname;
[familyname appendString:@"peak"];
 
NSLog(@" is %@",);
 
NSMutableString *nickname = [[NSMutableString alloc]initWithString:@"Ergou"];
 = nickname;
[nickname appendString:@"Egg"];
 
NSLog(@" is %@", );
2017-02-22 13:53:58.979 test[98299:3978965]  is Zhang San
2017-02-22 13:53:58.979 test[98299:3978965]  is Ergoudan'er

2. Copy of class objects

The only thing that needs to be explained here is to pay attention to the inheritance of classes.

This article has very clear and detailed descriptions, and only the conclusions are copied here:

1 Class is directly inherited from NSObject, without calling [super copyWithZone:zone]

2 The parent class implements the copy protocol, and the subclass also implements the copy protocol. The subclass needs to call [super copyWithZone:zone]

3 The parent class does not implement the copy protocol, the subclass implements the copy protocol, and the subclass does not need to call [super copyWithZone:zone]

4. [[[self class] alloc] init] should be called in the copyWithZone method to allocate memory

5、NSCopying

NSCopying is a protocol for object copying.

If the object of the class supports copying, the class should comply with and implement the NSCopying protocol.

NSCopyingThere is only one method in the protocol,as follows:
- (id)copyWithZone:(NSZone *)zone { 
 Person *model = [[[self class] allocWithZone:zone] init];
  = ;
  = ;
 //Unknown members model->_nickName = _nickName;
 return model;
}

3、NSMutableCopying

When a custom class has a property that is a mutable object, the mutableCopyWithZone operation must be performed when copying this property.

- (id)copyWithZone:(NSZone *)zone {
 AFHTTPRequestSerializer *serializer = [[[self class] allocWithZone:zone] init];
  = [ mutableCopyWithZone:zone];
  = ;
  = ;
 
 return serializer;
}

The above article briefly talks about several commonly used protocols in iOS. NSCoping/NSMutableCopying is all the content I have shared with you. I hope you can give you a reference and I hope you can support me more.