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@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@swift.org > https://lists.swift.org/mailman/listinfo/swift-users _______________________________________________ swift-users mailing list swift-users@swift.org https://lists.swift.org/mailman/listinfo/swift-users