Yep, I also admit the design of forbidding calling a setter before full class initialization is reasonable and what's really annoying is the inconsistency.
However, making @NSCopying attribute not subjects to the fact that setters would not be invoked in initializers perhaps is viable too. In the other words, assigning a value to a property whether or not by calling a setter has no influence on whether @NSCopying semantic'd work: copying should always take place after a property has been declared as @NSCopying. Jean-Daniel writes: >> Le 28 janv. 2017 à 05:34, Torin Kwok via swift-evolution >> <swift-evolution@swift.org> a écrit : >> >> Hello guys, >> >> Note: This issue has been originally presented inswift-usersmailling list >> <https://lists.swift.org/pipermail/swift-users/Week-of-Mon-20170123/004552.html>. >> And then I post it again here at the suggestion >> <https://lists.swift.org/pipermail/swift-users/Week-of-Mon-20170123/004561.html> >> of Jordan Rose: >> >> It might be reasonable to change this behavior, but it probably deserves a >> bit of discussion on swift-evolution; it's not 100%, for-sure a bug. >> --- the original content follows this line --- >> >> 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 since 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 taking advantage of @NSCopying attribute, I would 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 end up with nothing helpful — 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 >> <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. >> >> --- END --- >> >> Jordan: >> >> Your observation is correct: @NSCopying currently does not affect >> initializers. This is because accessing a property in an initializer always >> does direct access to the storage rather than going through the setter. >> I have tested the identical logic in Objective-C and the NSCopying semantic >> works perfectly within Obj-C's class initializer. >> > This is because Obj-C guarantee that all ivars are zero initialized and does > not enforce initializer safety (but forcing initialization of ivars before > calling other methods). > > Calling a setter (like any other method) before full class initialization is > unsafe as the setter may be overridden or simply customized, and may need to > access to the class or subclasses ivars. > > That said, I’m not sure what is the best way to solve that inconsistency. -- Torin Kwok (郭桐) OpenPGP/GnuPG: https://keybase.io/kwok _______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution