<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div class=""><div class="" style="font-family: LucidaGrande;"><p style="-webkit-print-color-adjust: exact; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; font-variant-ligatures: normal; orphans: 2; widows: 2; margin-top: 0px !important;" class=""></p><p style="-webkit-print-color-adjust: exact; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; font-variant-ligatures: normal; orphans: 2; widows: 2; margin-top: 0px !important;" class="">To better demonstrate the problems Iā€™m describing, I gave out a simple demo running in Playground to reproduce that. Apart from that, I also attached a Playground file that contains identical content in this mail, for the convenience of examination.</p><div style="-webkit-print-color-adjust: exact; font-family: Helvetica, arial, sans-serif; font-size: 14px; font-variant-ligatures: normal; orphans: 2; widows: 2;" class=""><pre class="line-numbers language-none" style="-webkit-print-color-adjust: exact; margin-top: 0.5em; background-image: linear-gradient(transparent 50%, rgba(69, 142, 209, 0.0392157) 50%); background-origin: content-box; background-clip: content-box; background-color: rgb(253, 253, 253); background-size: 3em 3em; border-width: 1px 1px 1px 10px; border-style: solid; border-color: rgb(204, 204, 204) rgb(204, 204, 204) rgb(204, 204, 204) rgb(53, 140, 203); font-size: 13px; line-height: 1.5; overflow: visible; padding: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; word-spacing: normal; word-break: normal; word-wrap: normal; tab-size: 4; position: relative; box-shadow: rgb(53, 140, 203) -1px 0px 0px 0px, rgb(223, 223, 223) 0px 0px 0px 1px; box-sizing: border-box; counter-reset: linenumber 0; background-position: 0% 0%; background-repeat: initial initial;"><code class=" language-none" style="-webkit-print-color-adjust: exact; margin: 0px; padding: 0px 1em 0px 3.8em; border: none; background-image: none; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace; word-spacing: normal; word-break: normal; word-wrap: normal; line-height: 1.5; tab-size: 4; max-height: inherit; height: 2052px; display: block; overflow: auto; position: relative; background-position: initial initial; background-repeat: initial initial;">import Foundation

class Person: NSObject,
  NSCopying {

  var firstName: String
  var lastName: String
  var job: String?

  init( firstName: String, lastName: String, job: String? = nil ) {
    self.firstName = firstName
    self.lastName = lastName
    self.job = job

    super.init()
    }

  /// Conformance to &lt;NSCopying&gt; protocol
  func copy( with zone: NSZone? = nil ) -&gt; Any {
    let theCopy = Person.init( firstName: firstName, lastName: lastName )
    theCopy.job = job

    return theCopy
    }

  override var description: String {
    return "\(firstName) \(lastName)" + ( job != nil ? ", \(job!)" : "" )
    }

  }

let johnAppleseed = Person( firstName: "John", lastName: "Appleseed", job: "CEO" )
var refJohnAppleseed = johnAppleseed

// assigning wihtout copying semantic:
refJohnAppleseed.job = "Engineer"

// `cloneJohnAppleseed` and `johnAppleseed` have the identical `job` ...
refJohnAppleseed
johnAppleseed
// ... and the assertion **would not** fail:
assert( refJohnAppleseed === johnAppleseed )

// Assigning a copy of johnAppleseed to clonedJohnAppleseed,
// which was returned by `copy( zone: ) -&gt; Any`
var clonedJohnAppleseed = johnAppleseed/* refJohnAppleseed is also okay */.copy() as! Person

clonedJohnAppleseed.job = "Designer"
johnAppleseed
// Alright you see, setting the job of `clonedJohnAppleseed` doesn't affect the
// job stored in `johnAppleseed`.

//: Up to now, everything goes right. However, when we begin introducing a new class consuming instances of `Person` class...

class Department: NSObject {

  // Here, we're expecting that `self.employee` would automatically
  // store the deeply-copied instance of `Person` class
  @NSCopying var employee: Person

  init( employee _ExternalPerson: Person ) {

    // CAUTION! That's the key point:
    // `self.employee` has been marked with `@NSCopying` attribute
    // but what would take place here is only the shallow-copying.
    // In the other words, `self.employee` will share identical underlying
    // object with `_ExternalPerson`.
    self.employee = _ExternalPerson
    super.init()

    // Assertion will definitely 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 !== employee ) */
    }

  override var description: String {
    return "A Department: [ ( \(employee) ) ]"
    }

  }

let isaacNewton = Person( firstName: "Isaac", lastName: "Newton", job: "Mathematician" )
let lab = Department.init( employee: isaacNewton )

isaacNewton.job = "Astronomer"
lab.employee
// Oops! Setting the job of `isaacNewton` affects the job stored in `lab.employee`.
// That's an unexpected behavior as we have declared `employee` property as
// `@NSCopying`. Obviously, `@NSCopying` semantic became effectless implicitly
// within the initializer of `Department` class.

// For the moment, we're required to explictly invoke `copy()` method on instances
// that wanna be copied to make sure that classes' properties are able to store
// deeply-copied results during the initialization:

/* self.employee = _ExternalPerson.copy() as! Person */

//: What indeed makes me confusing is that...

// @NSCopying semantic does work properly within the scope other than initializers:

lab.employee = isaacNewton
isaacNewton.job = "Physicist"
lab.employee
// That's it! If we assigned external instance to `lab.employee`,
// `@NSCopying` semantic would be well respected.</code></pre></div><div class=""><br class=""></div></div></div><br class=""><div><blockquote type="cite" class=""><div class="">On 28 Jan 2017, at 12:34, Torin Kwok &lt;<a href="mailto:torin@kwok.im" class="">torin@kwok.im</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><p style="-webkit-print-color-adjust: exact; margin-right: 0px; margin-bottom: 15px; margin-left: 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; font-variant-ligatures: normal; orphans: 2; widows: 2; margin-top: 0px !important;" class="">Hello guys,</p><p style="-webkit-print-color-adjust: exact; margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; font-variant-ligatures: normal; orphans: 2; widows: 2;" class=""><strong style="-webkit-print-color-adjust: exact;" class="">Note:</strong>&nbsp;This issue has been&nbsp;<a href="https://lists.swift.org/pipermail/swift-users/Week-of-Mon-20170123/004552.html" style="-webkit-print-color-adjust: exact; color: rgb(65, 131, 196);" class="">originally presented in&nbsp;<strong style="-webkit-print-color-adjust: exact;" class="">swift-users</strong>&nbsp;mailling list</a>. And then I post it again here at the&nbsp;<a href="https://lists.swift.org/pipermail/swift-users/Week-of-Mon-20170123/004561.html" style="-webkit-print-color-adjust: exact; color: rgb(65, 131, 196);" class="">suggestion</a>&nbsp;of Jordan Rose:</p><blockquote style="-webkit-print-color-adjust: exact; margin: 15px 0px; border-left-width: 4px; border-left-style: solid; border-left-color: rgb(221, 221, 221); padding: 0px 15px; color: rgb(119, 119, 119); font-family: Helvetica, arial, sans-serif; font-size: 14px; font-variant-ligatures: normal; orphans: 2; widows: 2;" class=""><div style="-webkit-print-color-adjust: exact; margin: 0px;" class="">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.</div></blockquote><p style="-webkit-print-color-adjust: exact; margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; font-variant-ligatures: normal; orphans: 2; widows: 2;" class=""><strong style="-webkit-print-color-adjust: exact;" class="">--- the original content follows this line ---</strong></p><p style="-webkit-print-color-adjust: exact; margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; font-variant-ligatures: normal; orphans: 2; widows: 2;" class="">I encountered a strange behavior when I declared a property with the&nbsp;<code style="-webkit-print-color-adjust: exact; margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px;" class="">@NSCopying</code>&nbsp;attribute:</p><div style="-webkit-print-color-adjust: exact; font-family: Helvetica, arial, sans-serif; font-size: 14px; font-variant-ligatures: normal; orphans: 2; widows: 2;" class=""><pre style="-webkit-print-color-adjust: exact; margin-top: 15px; margin-bottom: 15px; background-color: rgb(248, 248, 248); border: 1px solid rgb(204, 204, 204); font-size: 13px; line-height: 19px; overflow: auto; padding: 6px 10px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class=""><code class="language-swift" style="-webkit-print-color-adjust: exact; margin: 0px; padding: 0px; border: none; background-color: transparent; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-position: initial initial; background-repeat: initial initial;">// `Person` class inherits from `NSObject` class and conforms to `NSCopying` protocol
@NSCopying var employee: Person</code></pre></div><p style="-webkit-print-color-adjust: exact; margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; font-variant-ligatures: normal; orphans: 2; widows: 2;" class="">and then assigned an external instance of&nbsp;<code style="-webkit-print-color-adjust: exact; margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px;" class="">Person</code>&nbsp;class protocol to this property within the designated init methods:</p><div style="-webkit-print-color-adjust: exact; font-family: Helvetica, arial, sans-serif; font-size: 14px; font-variant-ligatures: normal; orphans: 2; widows: 2;" class=""><pre style="-webkit-print-color-adjust: exact; margin-top: 15px; margin-bottom: 15px; background-color: rgb(248, 248, 248); border: 1px solid rgb(204, 204, 204); font-size: 13px; line-height: 19px; overflow: auto; padding: 6px 10px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class=""><code class="language-swift" style="-webkit-print-color-adjust: exact; margin: 0px; padding: 0px; border: none; background-color: transparent; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-position: initial initial; background-repeat: initial initial;">// 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 )
 }</code></pre></div><p style="-webkit-print-color-adjust: exact; margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; font-variant-ligatures: normal; orphans: 2; widows: 2;" class="">If I indeed require the deep copying behavior during the init process, instead of taking advantage of&nbsp;<code style="-webkit-print-color-adjust: exact; margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px;" class="">@NSCopying</code>&nbsp;attribute, I would have to invoke the&nbsp;<code style="-webkit-print-color-adjust: exact; margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px;" class="">copy()</code>&nbsp;method manually:</p><div style="-webkit-print-color-adjust: exact; font-family: Helvetica, arial, sans-serif; font-size: 14px; font-variant-ligatures: normal; orphans: 2; widows: 2;" class=""><pre style="-webkit-print-color-adjust: exact; margin-top: 15px; margin-bottom: 15px; background-color: rgb(248, 248, 248); border: 1px solid rgb(204, 204, 204); font-size: 13px; line-height: 19px; overflow: auto; padding: 6px 10px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class=""><code class="language-swift" style="-webkit-print-color-adjust: exact; margin: 0px; padding: 0px; border: none; background-color: transparent; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-position: initial initial; background-repeat: initial initial;">init( employee externalEmployee: Person ) {
 // ...
 self.employee = externalEmployee.copy() as! Person  
 // ...
 }</code></pre></div><p style="-webkit-print-color-adjust: exact; margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; font-variant-ligatures: normal; orphans: 2; widows: 2;" class="">In fact, what really makes me confusing is that&nbsp;<code style="-webkit-print-color-adjust: exact; margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px;" class="">@NSCopying</code>&nbsp;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&nbsp;<code style="-webkit-print-color-adjust: exact; margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px;" class="">Person</code>&nbsp;to the&nbsp;<code style="-webkit-print-color-adjust: exact; margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px;" class="">self.employee</code>&nbsp;proper of&nbsp;<code style="-webkit-print-color-adjust: exact; margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px;" class="">Department</code>&nbsp;directly through setter rather than initializer:</p><div style="-webkit-print-color-adjust: exact; font-family: Helvetica, arial, sans-serif; font-size: 14px; font-variant-ligatures: normal; orphans: 2; widows: 2;" class=""><pre style="-webkit-print-color-adjust: exact; margin-top: 15px; margin-bottom: 15px; background-color: rgb(248, 248, 248); border: 1px solid rgb(204, 204, 204); font-size: 13px; line-height: 19px; overflow: auto; padding: 6px 10px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class=""><code class="language-swift" style="-webkit-print-color-adjust: exact; margin: 0px; padding: 0px; border: none; background-color: transparent; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; background-position: initial initial; background-repeat: initial initial;">department.employee = johnAppleseed</code></pre></div><p style="-webkit-print-color-adjust: exact; margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; font-variant-ligatures: normal; orphans: 2; widows: 2;" class="">then&nbsp;<code style="-webkit-print-color-adjust: exact; margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px;" class="">self.employee</code>&nbsp;property and&nbsp;<code style="-webkit-print-color-adjust: exact; margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px;" class="">johnAppleseed</code>&nbsp;variable will no longer share the same underlying object now. In the other words,&nbsp;<code style="-webkit-print-color-adjust: exact; margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px;" class="">@NSCopying</code>&nbsp;attribute makes sense.</p><p style="-webkit-print-color-adjust: exact; margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; font-variant-ligatures: normal; orphans: 2; widows: 2;" class="">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&nbsp;<code style="-webkit-print-color-adjust: exact; margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px;" class="">@NSCopying</code>&nbsp;itself but do not mentioned this strange behavior at all ā€” besides one radar descriping the same problem (<a href="rdar://21383959" style="-webkit-print-color-adjust: exact; color: rgb(65, 131, 196);" class="">rdar://21383959</a>) and a final conclusion mentioned in a guy's Gist comment:&nbsp;<strong style="-webkit-print-color-adjust: exact;" class="">... values set during initialization are not cloned ...</strong></p><p style="-webkit-print-color-adjust: exact; margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; font-variant-ligatures: normal; orphans: 2; widows: 2;" class="">That is,&nbsp;<code style="-webkit-print-color-adjust: exact; margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px;" class="">@NSCopying</code>&nbsp;semantic has no effect in initializers.</p><p style="-webkit-print-color-adjust: exact; margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; font-variant-ligatures: normal; orphans: 2; widows: 2;" class="">Then, what I want to figure out is the reason why&nbsp;<code style="-webkit-print-color-adjust: exact; margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px;" class="">@NSCopying</code>&nbsp;semantic will become effectless implicitly whithin initializers of a class, and the special considerations behind this behavior, if any.</p><p style="-webkit-print-color-adjust: exact; margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; font-variant-ligatures: normal; orphans: 2; widows: 2;" class=""><strong style="-webkit-print-color-adjust: exact;" class="">--- END ---</strong></p><p style="-webkit-print-color-adjust: exact; margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; font-variant-ligatures: normal; orphans: 2; widows: 2;" class="">Jordan:</p><blockquote style="-webkit-print-color-adjust: exact; margin: 15px 0px; border-left-width: 4px; border-left-style: solid; border-left-color: rgb(221, 221, 221); padding: 0px 15px; color: rgb(119, 119, 119); font-family: Helvetica, arial, sans-serif; font-size: 14px; font-variant-ligatures: normal; orphans: 2; widows: 2;" class=""><div style="-webkit-print-color-adjust: exact; margin: 0px;" class="">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.</div></blockquote><p style="-webkit-print-color-adjust: exact; margin: 15px 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; font-variant-ligatures: normal; orphans: 2; widows: 2;" class="">I have tested the identical logic in Objective-C and the&nbsp;<code style="-webkit-print-color-adjust: exact; margin: 0px 2px; padding: 0px 5px; white-space: nowrap; border: 1px solid rgb(234, 234, 234); background-color: rgb(248, 248, 248); border-radius: 3px;" class="">NSCopying</code>&nbsp;semantic works perfectly within Obj-C's class initializer.</p><p style="-webkit-print-color-adjust: exact; margin-top: 15px; margin-right: 0px; margin-left: 0px; font-family: Helvetica, arial, sans-serif; font-size: 14px; font-variant-ligatures: normal; orphans: 2; widows: 2; margin-bottom: 0px !important;" class="">I have no idea whether it's a bug or special consideration. After all, as a special consideration, it seems too strange that this behavior has not been obviously documented.</p><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><font face="Helvetica" class=""><span style="font-size: 14px;" class="">Best Regards,</span></font></div><div class=""><font face="Helvetica" class=""><span style="font-size: 14px;" class="">Torin Kwok</span></font></div><div class=""><br class=""></div><div class=""><br class=""></div></div></div></blockquote></div><br class=""></body></html>