[swift-users] @NSCopying semantic does not appear to copy in Swift initializer

Rod Brown rodney.brown6 at icloud.com
Fri Jan 27 07:28:04 CST 2017


Hi Torin,

Just a few notes:

I believe the @NSCopying behaviour actually uses the copy(with zone: NSZone?) method rather than the indirect copy() method. I would check that you’ve implemented that correctly. If you have, then it appears to be a bug. I would breakpoint on this method (not copy()) to check the copy is actually occurring.

I would note however that this check doesn’t necessarily work for some of Apple’s API’s though. A lot of the Foundation API’s implement copy avoidance. That is, if you copy() an NSArray, it will actually just return itself, retained, rather than a new array, because an NSArray is immutable, and so the copy is needless. NSMutableArray then overrides the method and actually does return a true copy, because it is mutable and therefore dangerous. A lot of the foundation classes that implement NSCopying do this (think of this as a poor man’s copy-on-write!), and so the !== check isn’t necessarily the correct check to ensure it is setting via NSCopying. Breakpointing or checking with mutable variant classes is a more correct check with Foundation-style APIs.

Thanks,

Rod

> On 27 Jan 2017, at 6:30 pm, Torin Kwok via swift-users <swift-users at swift.org> wrote:
> 
> Hello guys,
> 
> I wanna ask a question about the behavior of `@NSCopying` semantic in
> Swift 3. Well, according to Apple's official documentation:
> 
>> In Swift, the Objective-C copy property attribute translates to
>> @NSCopying. The type of the property must conform to the NSCopying
>> protocol.
> 
> However, I encountered a strange behavior when I declared a property
> with the `@NSCopying` attribute:
> 
> ```
> // `Person` class inherits from `NSObject` class and conforms to `NSCopying` protocol
> @NSCopying var employee: Person
> ```
> 
> and then assigned an external instance of `Person` class protocol to
> this property within the designated init methods:
> 
> ```
> // Designated initializer of `Department` class
> init( employee externalEmployee: Person ) {
>  self.employee = externalEmployee
>  super.init()
> 
>  // Assertion would fail because Swift do not actually copy the value assigned to this property         
>  // even though `self.employee` has been marked as `@NSCoyping`
>  // assert( self.employee !== externalEmployee )
>  }
> ```
> 
> If I indeed require the deep copying behavior during the init process,
> instead of making advantage of `@NSCopying` attribute, I have to
> invoke the `copy()` method manually:
> 
> ```
> init( employee externalEmployee: Person ) {
>  // ...
>  self.employee = externalEmployee.copy() as! Person  
>  // ...
>  }
> ```
> 
> In fact, what really makes me confusing is that `@NSCopying` semantic
> does work properly within the other parts of the class definition such
> as normal instance methods, or external scope. For instance, if we're
> assigning an external instance of `Person` to the `self.employee` proper
> of `Department` directly through setter rather than initializer:
> 
>> department.employee = johnAppleseed
> 
> then `self.employee` property and `johnAppleseed` variable will no
> longer share the same underlying object now. In the other words,
> `@NSCopying` attribute makes sense.
> 
> After I looked through a great deal of results given by Google, and
> dicussions on StackOverflow, I finally found nothing related — the vast
> majority of articles, documentations as well as issues talking about
> this similar topics only focus on the basic concepts and effects of
> `@NSCopying` itself but do not mentioned this strange behavior at all —
> besides one radar descriping the same problem (rdar://21383959) and a
> final conclusion mentioned in a guy's Gist comment: **... values set
> during initialization are not cloned ...**
> 
> That is, `@NSCopying` semantic has no effect in initializers.
> 
> Then, what I want to figure out is the reason why `@NSCopying` semantic
> will become effectless implicitly whithin initializers of a class, and
> the special considerations behind this behavior, if any.
> 
> Thank you very much.
> 
> Best Regards,
> Torin Kwok
> 
> _______________________________________________
> swift-users mailing list
> swift-users at swift.org
> https://lists.swift.org/mailman/listinfo/swift-users



More information about the swift-users mailing list