<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="">I am excited by the general direction but I have some concerns about the scope of the design at this time; specifically, it seems like it would benefit a lot from having some flexible-and-efficient way for behaviors to “reach upward” back into their container from within their custom methods (without forcing the caller to pass-in the container to each such call, of course).</div><div class=""><br class=""></div><div class="">I took a stab at mocking up one of the behaviors I’d like to be able to write and hit a lot of roadblocks due to the above; I’ve included it below with some commentary.&nbsp;</div><div class=""><br class=""></div><div class="">Even though this is perhaps a rather extreme/niche behavior to want to implement, I think the issues it encountered are actually general enough that other useful behaviors will also encounter them under the proposal as sketched.</div><div class=""><br class=""></div><div class="">Here’s the sample use, starting with motivation.</div><div class=""><br class=""></div><div class="">For some APIs — e.g. CoreBluetooth — you often wind up with highly-stateful objects that receive callbacks on a specific queue, and typically also do their state-maintenance while on that same queue; these objects typically also have a “public API” with methods that are only meant for use while off the queue (e.g. from the main queue, to update the UI…).</div><div class=""><br class=""></div><div class="">You thus wind up with each method-and-property pretty clearly being one and only one of these:</div><div class=""><br class=""></div><div class="">- “on-queue”, e.g. *only* meant for use while on the object’s queue</div><div class="">- “off-queue”, e.g. *only* meant for use while off the object’s queue</div><div class=""><br class=""></div><div class="">…with concurrency-and-synchronization logic essentially amounting to only calling / using each method-and-property while appropriately on/off queue.</div><div class=""><br class=""></div><div class="">For a concrete example, for an implementer of CBCentralManagerDelegate:</div><div class=""><br class=""></div><div class="">- all the&nbsp;CBCentralManagerDelegate&nbsp;methods are "on-queue"</div><div class="">- all the BT-state-management methods (called in reaction to BT events) are also “on-queue”</div><div class="">- the public methods (e.g. for UI use, or for asking the object to do stuff) are “off-queue”</div><div class="">- some of the basic properties (status, is-peripheral-foo-connected?) are oddballs, and get:</div><div class="">&nbsp; - private backing properties for use/update while on-queue</div><div class="">&nbsp; - public off-queue accessors that do a dispatch_sync, read the backing property, and return it</div><div class=""><br class=""></div><div class="">…and so on.</div><div class=""><br class=""></div><div class="">This can all be handled today "by hand” — it just requires being careful — but it’d be nice to have a custom behavior that would streamline both the implementation of on/off queue access for properties, and make each site-of-use more self-documenting/self-verifying vis-a-vis on/off-queue status.</div><div class=""><br class=""></div><div class="">Here’s my best attempt (issues flagged in ALL-CAPS):</div><div class=""><br class=""></div><div class="">/// Object assumed to have private queue it uses for synchronization.</div><div class="">protocol PrivateQueueOwner : class {</div><div class=""><br class=""></div><div class="">&nbsp; // we don’t want to leak the actual queue to the wider world,</div><div class="">&nbsp; // so we have to bubble these up to the public API:</div><div class="">&nbsp; func dispatchSync&lt;R&gt;(@noescape action: () -&gt; R) -&gt; R</div><div class="">&nbsp; func dispatchBarrierSync&lt;R&gt;(@noescape action: () -&gt; R) -&gt; R</div><div class="">&nbsp; func dispatchAsync(action: () -&gt; ())</div><div class="">&nbsp; func dispatchBarrierAsync(action: () -&gt; ())</div><div class=""><br class=""></div><div class="">&nbsp; // we assume we are managing our queues s.t. we can</div><div class="">&nbsp; // actually get the below to work reliably:</div><div class="">&nbsp; func isOnPrivateQueue() -&gt; Bool</div><div class=""><br class=""></div><div class="">}</div><div class=""><br class=""></div><div class="">/// Behavior used to enforce a particular use-pattern around</div><div class="">/// a property of an object that uses a private queue for synchronization:</div><div class="">struct QueueAccess&lt;Value&gt; {</div><div class="">&nbsp; var value: Value</div><div class="">&nbsp;&nbsp;</div><div class="">&nbsp; // THIS PART IS ONLY-KINDA OK:</div><div class="">&nbsp; subscript&lt;Container:PrivateQueueOwner&gt;(varIn container: Container&gt; {</div><div class="">&nbsp; &nbsp; get {</div><div class="">&nbsp; &nbsp; &nbsp; if container.isOnPrivateQueue() {</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; return self.value</div><div class="">&nbsp; &nbsp; &nbsp; } else {</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; return self.container.dispatchSync() {</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return self.value</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // ^ DOES THIS ACTUALLY WORK AS I’D WANT, IF I AM A STRUCT?</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; }</div><div class="">&nbsp; &nbsp; &nbsp; }</div><div class="">&nbsp; &nbsp; }</div><div class="">&nbsp; &nbsp; set {</div><div class="">&nbsp; &nbsp; &nbsp; if container.isOnPrivateQueue() {&nbsp;</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; self.value = newValue</div><div class="">&nbsp; &nbsp; &nbsp; } else {</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; container.dispatchBarrierAsync() {</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; self.value = newValue</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // ^ DOES THIS ACTUALLY WORK AS I’D WANT, IF I AM A STRUCT?</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; }</div><div class="">&nbsp; &nbsp; &nbsp; }</div><div class="">&nbsp; &nbsp; }</div><div class="">&nbsp; }</div><div class=""><br class=""></div><div class="">&nbsp; // EVERYTHING FROM HERE ON DOWN IS MOSTLY PROBLEMATIC:</div><div class=""><br class=""></div><div class=""><div class="">&nbsp; func onQueueUpdate(newValue: Value) {&nbsp;</div><div class="">&nbsp; &nbsp; assert(self.container.isOnPrivateQueue()) // &lt;- HOW?</div><div class="">&nbsp; &nbsp; self.value = newValue</div><div class="">&nbsp; }</div><div class="">&nbsp;&nbsp;</div><div class="">&nbsp; func offQueueUpdate(newValue: Value) {</div><div class="">&nbsp; &nbsp; assert(self.container.isOffPrivateQueue()) // &lt;- HOW?</div><div class="">&nbsp; &nbsp; self.container.dispatchBarrierAsync() { // &lt;- HOW?</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp;self.value = newValue</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp;// ^ DOES THIS EVEN WORK IF I AM A STRUCT? &nbsp;&nbsp;</div><div class="">&nbsp; &nbsp; }</div><div class="">&nbsp; }</div><div class=""><br class=""></div><div class="">&nbsp; func offQueueAccess() -&gt; Value {</div><div class="">&nbsp; &nbsp; assert(self.container.isOffPrivateQueue()) // &lt;- HOW?</div><div class="">&nbsp; &nbsp; return self.container.dispatchSync() { // &lt;- HOW?</div><div class="">&nbsp; &nbsp; &nbsp; return self.value</div><div class="">&nbsp; &nbsp; }</div><div class="">&nbsp; }</div><div class=""><br class=""></div><div class="">&nbsp; func onQueueAcccess() -&gt; Value {</div><div class="">&nbsp; &nbsp; assert(self.container.isOnPrivateQueue()) // &lt;- HOW?</div><div class="">&nbsp; &nbsp; return self.value</div><div class="">&nbsp; }</div></div><div class=""><br class=""></div><div class=""><div class="">&nbsp; func offQueueAccess&lt;R&gt;(@noescape transform: (Value) -&gt; R) -&gt; R {</div><div class="">&nbsp; &nbsp; assert(self.container.isOffPrivateQueue()) // &lt;- HOW?</div><div class="">&nbsp; &nbsp; return self.container.dispatchSync() { // &lt;- HOW?</div><div class="">&nbsp; &nbsp; &nbsp; return transform(self.value)</div><div class="">&nbsp; &nbsp; }</div><div class="">&nbsp; }</div><div class=""><br class=""></div><div class="">&nbsp; func onQueueAcccess&lt;R&gt;(@noescape transform: (Value) -&gt; R) -&gt; R {</div><div class="">&nbsp; &nbsp; assert(self.container.isOnPrivateQueue()) // &lt;- HOW?</div><div class="">&nbsp; &nbsp; return transform(self.value)</div><div class="">&nbsp; }</div></div><div class=""><br class=""></div><div class="">}</div><div class=""><br class=""></div><div class="">….which if it was implementable, would wind up used like so:</div><div class=""><br class=""></div><div class="">public class BTCentralManagerController : NSObject, CBCentralManagerDelegate, PrivateQueueOwner {</div><div class=""><br class=""></div><div class="">&nbsp; internal lazy var centralManager: CBCentralManager = CBCentralManager(</div><div class="">&nbsp; &nbsp; delegate: self,&nbsp;</div><div class="">&nbsp; &nbsp; queue: self.privateQueue,&nbsp;</div><div class="">&nbsp; &nbsp; options: self.centralManagerOptions()</div><div class="">&nbsp; )</div><div class="">&nbsp;&nbsp;</div><div class="">&nbsp; private let privateQueue: dispatch_queue_t&nbsp;</div><div class="">&nbsp;&nbsp;</div><div class="">&nbsp; public private(set) var (queueAccess) centralManagerState: CBCentralManagerState = .Unknown</div><div class="">&nbsp; internal private(set) var (queueAccess) peripheralControllers: [NSUUID:BTPeripheralController] = [:]</div><div class="">&nbsp;&nbsp;</div><div class="">&nbsp; // internal API sample:</div><div class=""><br class=""></div><div class="">&nbsp; func&nbsp;centralManagerDidUpdateState(_&nbsp;central:&nbsp;CBCentralManager) {</div><div class="">&nbsp; &nbsp; self.centralManagerState.queueAccess.onQueueUpdate(central.state)</div><div class="">&nbsp; }</div><div class="">&nbsp;</div><div class="">&nbsp; // public API sample</div><div class=""><br class=""></div><div class="">&nbsp; public func peripheralControllerForUUID(uuid: NSUUID) -&gt; BTPeripheralController? {</div><div class="">&nbsp; &nbsp; // this is an explicitly “off-queue” method:</div><div class="">&nbsp; &nbsp; self.currentState.queueAccess.offQueueAccess() {</div><div class="">&nbsp; &nbsp; &nbsp; return $0[uuid]</div><div class="">&nbsp; &nbsp; }</div><div class="">&nbsp; }</div><div class=""><br class=""></div><div class="">}</div><div class=""><br class=""></div><div class="">…giving us:</div><div class=""><br class=""></div><div class="">- safe defaults for attempted direct-property access</div><div class="">- self-dcoumenting/self-validating customized getters-and-setters for all internal-use scenarios</div><div class=""><br class=""></div><div class="">But, as the # of ALL-CAPS comments should indicate, this behavior seems *well beyond* what the proposal can provide in a natural way (e.g. we can get closer by passing-in the container to each method, but that’s a lot less natural and a lot clunkier).</div><div class="">&nbsp;</div><div class="">Moreover, even if the “ability to access the container” were to be addressed, I also don’t like having to use a protocol like `PrivateQueueOwner` to make my `queueAccess` behavior re-usable; at least at present, adopted-protocol visibility is the same visibility as the type itself, so that e.g. if a public class conforms to `PrivateQueueOwner` then all the methods in `PrivateQueueOwner` are also public.</div><div class=""><br class=""></div><div class="">This is undesirable, as although I’d want such classes to be public, I wouldn’t want such low-level implementation details to be part of their public API.</div><div class=""><br class=""></div><div class="">Ideally, rather than forcing the container to adopt a protocol, I could instead do something *more* like this:</div><div class=""><br class=""></div><div class=""><div class="">public class BTCentralManagerController : NSObject, CBCentralManagerDelegate {</div></div><div class=""><br class=""></div><div class=""><div class="">&nbsp; private let privateQueue: dispatch_queue_t&nbsp;</div></div><div class="">&nbsp;&nbsp;</div><div class="">&nbsp; // configures `queueAccess` behavior to use `self.privateQueue` (with on-queue check also as-specified)</div><div class="">&nbsp; // ...note that if this becomes possible, the syntax might need to change, b/c the below is not very readable!</div><div class="">&nbsp; public private(set) var (queueAccess(queue: `self.privateQueue`, onQueue: `self.isOnPrivateQueue()`)) currentState: CBCentralManagerState = .Unknown</div><div class="">&nbsp; internal private(set) var (queueAccess(queue: `self.privateQueue`,&nbsp;onQueue: `self.isOnPrivateQueue()`)) peripheralControllers: [NSUUID:BTPeripheralController] = [:]</div><div class=""><br class=""></div><div class="">}</div><div class=""><br class=""></div><div class="">// which somehow interacts with a declaration like this:</div><div class="">struct QueueAccess&lt;Value&gt; {</div><div class=""><br class=""></div><div class="">&nbsp; var value: Value</div><div class=""><br class=""></div><div class="">&nbsp; // declaration stating we expect a `queue` expression during configuration, with the&nbsp;</div><div class="">&nbsp; // following type (and the accessor automagically-synthesized via compiler magic)</div><div class="">&nbsp; container var queue: dispatch_queue_t { get }</div><div class=""><br class=""></div><div class="">&nbsp; // declaration stating we expect an `onQueue` expression&nbsp;during configuration, with the&nbsp;</div><div class="">&nbsp; // following type (and the implementation automagically-synthesized via compiler magic)</div><div class="">&nbsp; container func onQueue() -&gt; Bool</div><div class=""><br class=""></div><div class="">&nbsp; &nbsp;func onQueueUpdate(newValue: Value) {&nbsp;</div><div class="">&nbsp; &nbsp; assert(self.onQueue())&nbsp;</div><div class="">&nbsp; &nbsp; self.value = newValue</div><div class="">&nbsp; }</div><div class="">&nbsp;&nbsp;</div><div class="">&nbsp; func offQueueUpdate(newValue: Value) {</div><div class="">&nbsp; &nbsp; assert(!self.onQueue())</div><div class="">&nbsp; &nbsp; dispatch_barrier_async(self.queue) {</div><div class="">&nbsp; &nbsp; &nbsp; self.value &nbsp;= newValue</div><div class="">&nbsp; &nbsp; &nbsp; // ^ NOTE: this may still be a problem for struct-based behaviors...?</div><div class="">&nbsp; &nbsp; }</div><div class="">&nbsp; }</div><div class="">&nbsp;</div><div class="">&nbsp; // etc...</div><div class="">&nbsp;</div><div class="">}</div><div class=""><br class=""></div><div class="">…which, if possible, would obviously make behaviors a lot more specialized than they are under the current proposal (e.g. they would seemingly need a lot of specialized help from the compiler to be able to access those variables without either creating a strong reference to the container or wasting a lot of space with redundant stored properties, and might be their own specialized type, rather than an otherwise-vanilla struct-or-class as per the current proposal).&nbsp;</div><div class=""><br class=""></div><div class="">But, if the above were possible, the behaviors would be a *lot* more re-usable, and it’d be unnecessary to have the container adopt a particular protocol.</div><div class=""><br class=""></div><div class="">Note also that even if the “unwanted API pollution” issue were resolved — e.g. by making it possible to somehow privately-adopt a protocol, or equivalent — there’d still be the issue of getting efficient access to the container to address, if these use cases are to be supported.</div><div class=""><br class=""></div><div class="">So that’s my reaction; if you read it this far, thanks for your attention.</div><div class=""><br class=""></div><div class="">I’d *completely* understand if the reaction here is simply that such uses are out-of-scope for this proposal; that seems perfectly reasonable!</div><div class=""><br class=""></div><div class="">But keep in mind, the general issue of reaching-up from custom methods of behaviors can show up in simpler contexts:</div><div class=""><br class=""></div><div class="">// convenience logic:</div><div class="">private extension UIViewController {</div><div class=""><br class=""></div><div class="">&nbsp; func viewHasEnteredWindow() -&gt; Bool {</div><div class="">&nbsp; &nbsp; &nbsp;return self.viewIfLoaded()?.window != nil ?? false</div><div class="">&nbsp; }</div><div class="">}</div><div class=""><br class=""></div><div class="">// custom behavior:</div><div class="">struct MustSetBeforeVisibility&lt;Value&gt; {</div><div class="">&nbsp; value: Value?</div><div class="">&nbsp;&nbsp;</div><div class="">&nbsp; // THIS PART OK:</div><div class="">&nbsp; subscript&lt;Container:UIViewController&gt;(varIn container: Container&gt; -&gt; Value? {</div><div class="">&nbsp; &nbsp; get {</div><div class="">&nbsp; &nbsp; &nbsp; if container.viewHasEnteredWindow() {</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; guard let v = self.value else {&nbsp;</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fatalError(“Should’ve set property \(self) by now, b/c our VC’s view is in the window (vc: \(container))”)</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; }</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; return v</div><div class="">&nbsp; &nbsp; &nbsp; } else {</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; return self.value // perfectly-cromulent to be unset at this point in lifecycle</div><div class="">&nbsp; &nbsp; &nbsp; }</div><div class="">&nbsp; &nbsp; }</div><div class="">&nbsp; &nbsp; set {</div><div class="">&nbsp; &nbsp; &nbsp; if !container.viewHasEnteredWindow() {</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; self.value = newValue</div><div class="">&nbsp; &nbsp; &nbsp; } else {</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp; fatalError(“Not meant to be set after we have become potentially-visible!")</div><div class="">&nbsp; &nbsp; &nbsp; }</div><div class="">&nbsp; &nbsp; }</div><div class="">&nbsp; }</div><div class=""><br class=""></div><div class="">&nbsp; // HOW TO DO THIS PART:</div><div class="">&nbsp; /// non-optional convenience accessor; only meant for use once our view has&nbsp;</div><div class="">&nbsp; /// become potentially-visible</div><div class="">&nbsp; func direct() -&gt; Value {</div><div class="">&nbsp; &nbsp; if !container.viewHasEnteredWindow() { // &lt;- HOW?</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp;fatalError(“Trying to do direct-access on \(self) too soon!")</div><div class="">&nbsp; &nbsp; } else if let v = self.value {</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp;return v</div><div class="">&nbsp; &nbsp; } else {</div><div class="">&nbsp; &nbsp; &nbsp; &nbsp;fatalError(“Trying to do direct-access, but never set the value for \(self) appropriately!")</div><div class="">&nbsp; &nbsp; }</div><div class="">&nbsp; }</div><div class=""><br class=""></div><div class="">}</div><div class=""><br class=""></div><div class="">…which is basically another take on a “smarter” implicitly-unwrapped-optional. You don’t *need* a function like `direct()`, but you might want it, and it might be nice to be able to differentiate “using too soon” and “forgot to set the value”.</div><div class=""><br class=""></div><br class=""><div><blockquote type="cite" class=""><div class="">On Dec 17, 2015, at 11:37 AM, Joe Groff via swift-evolution &lt;<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html charset=utf-8" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">Hi everyone. Chris stole my thunder already—yeah, I've been working on a design for allowing properties to be extended with user-defined <strike class="">delegates^W</strike> behaviors. Here's a draft proposal that I'd like to open up for broader discussion. Thanks for taking a look!<div class=""><br class=""></div><div class="">-Joe</div><div class=""><br class=""></div><div class=""><a href="https://gist.github.com/jckarter/f3d392cf183c6b2b2ac3" class="">https://gist.github.com/jckarter/f3d392cf183c6b2b2ac3</a></div><div class=""><br class=""></div><div class=""><div id="generated-toc" class="generate_from_h1 generate_for_page" style="position: fixed; max-height: 90%; width: 250px; overflow-x: hidden; overflow-y: auto; right: 20px; bottom: -972px; font-size: 1.1em; line-height: 1.2em; background-color: rgba(0, 0, 0, 0.8); color: rgb(200, 200, 200); padding: 10px 30px 20px 20px; border-top-left-radius: 10px; border-top-right-radius: 10px; border-bottom-right-radius: 10px; border-bottom-left-radius: 10px; transition: all 0.3s ease-out; -webkit-transition: all 0.3s ease-out; word-wrap: break-word; z-index: 101; outline: 0px; border: 0px; font-family: -webkit-standard;"><ul style="padding-left: 0px; margin-left: 10px;" class=""><li class="notmissing" style="display: block; list-style: none; margin: 10px 0px; background-color: transparent !important; background-position: initial initial !important; background-repeat: initial initial !important;"><ul style="padding-left: 0px; margin-left: 10px;" class=""><li class="notmissing" style="display: block; list-style: none; margin: 10px 0px; background-color: transparent !important; background-position: initial initial !important; background-repeat: initial initial !important;"><ul style="padding-left: 0px; margin-left: 10px;" class=""><li class="missing" style="display: block; list-style: none; margin: 10px 0px; background-color: transparent !important; background-position: initial initial !important; background-repeat: initial initial !important;"><ul style="padding-left: 0px; margin-top: 0px; margin-left: 10px;" class=""><li class="notmissing" style="display: block; list-style: none; margin: 10px 0px; background-color: transparent !important; background-position: initial initial !important; background-repeat: initial initial !important;"><a href="file:///Users/jgroff/src/s/swift-evolution/proposals/XXXX-property-delegates.md#lazy" class="wiki-link" style="color: rgb(255, 255, 255) !important; text-decoration: none; margin-top: 0px; display: block; font-size: 14px; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; border: none !important; background-image: none !important; outline: 0px; background-position: initial initial !important; background-repeat: initial initial !important;">Lazy</a></li><li class="notmissing" style="display: block; list-style: none; margin: 10px 0px; background-color: transparent !important; background-position: initial initial !important; background-repeat: initial initial !important;"><a href="file:///Users/jgroff/src/s/swift-evolution/proposals/XXXX-property-delegates.md#memoization" class="wiki-link" style="color: rgb(255, 255, 255) !important; text-decoration: none; margin-top: 0px; display: block; font-size: 14px; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; border: none !important; background-image: none !important; outline: 0px; background-position: initial initial !important; background-repeat: initial initial !important;">Memoization</a></li><li class="notmissing" style="display: block; list-style: none; margin: 10px 0px; background-color: transparent !important; background-position: initial initial !important; background-repeat: initial initial !important;"><a href="file:///Users/jgroff/src/s/swift-evolution/proposals/XXXX-property-delegates.md#delayedinitialization" class="wiki-link" style="color: rgb(255, 255, 255) !important; text-decoration: none; margin-top: 0px; display: block; font-size: 14px; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; border: none !important; background-image: none !important; outline: 0px; background-position: initial initial !important; background-repeat: initial initial !important;">Delayed Initialization</a></li><li class="notmissing" style="display: block; list-style: none; margin: 10px 0px; background-color: transparent !important; background-position: initial initial !important; background-repeat: initial initial !important;"><a href="file:///Users/jgroff/src/s/swift-evolution/proposals/XXXX-property-delegates.md#resettableproperties" class="wiki-link" style="color: rgb(255, 255, 255) !important; text-decoration: none; margin-top: 0px; display: block; font-size: 14px; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; border: none !important; background-image: none !important; outline: 0px; background-position: initial initial !important; background-repeat: initial initial !important;">Resettable properties</a></li><li class="notmissing" style="display: block; list-style: none; margin: 10px 0px; background-color: transparent !important; background-position: initial initial !important; background-repeat: initial initial !important;"><a href="file:///Users/jgroff/src/s/swift-evolution/proposals/XXXX-property-delegates.md#synchronizedpropertyaccess" class="wiki-link" style="color: rgb(255, 255, 255) !important; text-decoration: none; margin-top: 0px; display: block; font-size: 14px; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; border: none !important; background-image: none !important; outline: 0px; background-position: initial initial !important; background-repeat: initial initial !important;">Synchronized Property Access</a></li><li class="notmissing" style="display: block; list-style: none; margin: 10px 0px; background-color: transparent !important; background-position: initial initial !important; background-repeat: initial initial !important;"><a href="file:///Users/jgroff/src/s/swift-evolution/proposals/XXXX-property-delegates.md#nscopying" class="wiki-link" style="color: rgb(255, 255, 255) !important; text-decoration: none; margin-top: 0px; display: block; font-size: 14px; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; border: none !important; background-image: none !important; outline: 0px; background-position: initial initial !important; background-repeat: initial initial !important;">NSCopying</a></li><li class="notmissing" style="display: block; list-style: none; margin: 10px 0px; background-color: transparent !important; background-position: initial initial !important; background-repeat: initial initial !important;"><a href="file:///Users/jgroff/src/s/swift-evolution/proposals/XXXX-property-delegates.md#referencingpropertieswithpointers" class="wiki-link" style="color: rgb(255, 255, 255) !important; text-decoration: none; margin-top: 0px; display: block; font-size: 14px; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; border: none !important; background-image: none !important; outline: 0px; background-position: initial initial !important; background-repeat: initial initial !important;">Referencing Properties with Pointers</a></li><li class="notmissing" style="display: block; list-style: none; margin: 10px 0px; background-color: transparent !important; background-position: initial initial !important; background-repeat: initial initial !important;"><a href="file:///Users/jgroff/src/s/swift-evolution/proposals/XXXX-property-delegates.md#propertyobservers" class="wiki-link" style="color: rgb(255, 255, 255) !important; text-decoration: none; margin-top: 0px; display: block; font-size: 14px; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; border: none !important; background-image: none !important; outline: 0px; background-position: initial initial !important; background-repeat: initial initial !important;">Property Observers</a></li></ul></li></ul></li><li class="notmissing" style="display: block; list-style: none; margin: 10px 0px; background-color: transparent !important; background-position: initial initial !important; background-repeat: initial initial !important;"><a href="file:///Users/jgroff/src/s/swift-evolution/proposals/XXXX-property-delegates.md#detaileddesign" class="wiki-link" style="color: rgb(255, 255, 255) !important; text-decoration: none; margin-top: 0px; display: block; font-size: 14px; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; border: none !important; background-image: none !important; outline: 0px; background-position: initial initial !important; background-repeat: initial initial !important;">Detailed design</a></li><li class="notmissing" style="display: block; list-style: none; margin: 10px 0px; background-color: transparent !important; background-position: initial initial !important; background-repeat: initial initial !important;"><a href="file:///Users/jgroff/src/s/swift-evolution/proposals/XXXX-property-delegates.md#impactonexistingcode" class="wiki-link" style="color: rgb(255, 255, 255) !important; text-decoration: none; margin-top: 0px; display: block; font-size: 14px; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; border: none !important; background-image: none !important; outline: 0px; background-position: initial initial !important; background-repeat: initial initial !important;">Impact on existing code</a></li><li class="notmissing" style="display: block; list-style: none; margin: 10px 0px; background-color: transparent !important; background-position: initial initial !important; background-repeat: initial initial !important;"><a href="file:///Users/jgroff/src/s/swift-evolution/proposals/XXXX-property-delegates.md#alternativesconsideredtoconsider" class="wiki-link" style="color: rgb(255, 255, 255) !important; text-decoration: none; margin-top: 0px; display: block; font-size: 14px; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; border: none !important; background-image: none !important; outline: 0px; background-position: initial initial !important; background-repeat: initial initial !important;">Alternatives considered/to consider</a><ul style="padding-left: 0px; margin-left: 10px;" class=""><li class="notmissing" style="display: block; list-style: none; margin: 10px 0px; background-color: transparent !important; background-position: initial initial !important; background-repeat: initial initial !important;"><a href="file:///Users/jgroff/src/s/swift-evolution/proposals/XXXX-property-delegates.md#declarationsyntax" class="wiki-link" style="color: rgb(255, 255, 255) !important; text-decoration: none; margin-top: 0px; display: block; font-size: 14px; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; border: none !important; background-image: none !important; outline: 0px; background-position: initial initial !important; background-repeat: initial initial !important;">Declaration syntax</a></li><li class="notmissing" style="display: block; list-style: none; margin: 10px 0px; background-color: transparent !important; background-position: initial initial !important; background-repeat: initial initial !important;"><a href="file:///Users/jgroff/src/s/swift-evolution/proposals/XXXX-property-delegates.md#syntaxforaccessingthebackingproperty" class="wiki-link" style="color: rgb(255, 255, 255) !important; text-decoration: none; margin-top: 0px; display: block; font-size: 14px; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; border: none !important; background-image: none !important; outline: 0px; background-position: initial initial !important; background-repeat: initial initial !important;">Syntax for accessing the backing property</a></li><li class="notmissing" style="display: block; list-style: none; margin: 10px 0px; background-color: transparent !important; background-position: initial initial !important; background-repeat: initial initial !important;"><a href="file:///Users/jgroff/src/s/swift-evolution/proposals/XXXX-property-delegates.md#definingbehaviorrequirementsusingaprotocol" class="wiki-link" style="color: rgb(255, 255, 255) !important; text-decoration: none; margin-top: 0px; display: block; font-size: 14px; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; border: none !important; background-image: none !important; outline: 0px; background-position: initial initial !important; background-repeat: initial initial !important;">Defining behavior requirements using a protocol</a></li><li class="notmissing" style="display: block; list-style: none; margin: 10px 0px; background-color: transparent !important; background-position: initial initial !important; background-repeat: initial initial !important;"><a href="file:///Users/jgroff/src/s/swift-evolution/proposals/XXXX-property-delegates.md#abehaviordeclaration" class="wiki-link" style="color: rgb(255, 255, 255) !important; text-decoration: none; margin-top: 0px; display: block; font-size: 14px; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; border: none !important; background-image: none !important; outline: 0px; background-position: initial initial !important; background-repeat: initial initial !important;">A behavior declaration</a></li><li class="notmissing" style="display: block; list-style: none; margin: 10px 0px; background-color: transparent !important; background-position: initial initial !important; background-repeat: initial initial !important;"><a href="file:///Users/jgroff/src/s/swift-evolution/proposals/XXXX-property-delegates.md#namingconventionforbehaviors" class="wiki-link" style="color: rgb(255, 255, 255) !important; text-decoration: none; margin-top: 0px; display: block; font-size: 14px; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; border: none !important; background-image: none !important; outline: 0px; background-position: initial initial !important; background-repeat: initial initial !important;">Naming convention for behaviors</a></li></ul></li><li class="notmissing" style="display: block; list-style: none; margin: 10px 0px; background-color: transparent !important; background-position: initial initial !important; background-repeat: initial initial !important;"><a href="file:///Users/jgroff/src/s/swift-evolution/proposals/XXXX-property-delegates.md#todo" class="wiki-link" style="color: rgb(255, 255, 255) !important; text-decoration: none; margin-top: 0px; display: block; font-size: 14px; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; border: none !important; background-image: none !important; outline: 0px; background-position: initial initial !important; background-repeat: initial initial !important;">TODO</a></li></ul></li></ul></div><div class=""><br class=""></div></div>
<img src="https://u2002410.ct.sendgrid.net/wf/open?upn=9EwXyNl81W9TT3yZ17PL28-2Be7Ks-2FXLjqa0dZcsddi5b5y8G-2Fn3lLXOA3ZQqrSAmMqa0E1zXRJ5C4Sr9PK9V4pHz8Usi2GRRz1vtd8KA8kJnpkjqi4NGP4iMJtqRFuXjwZcHo8nc17yhkBHMeSkvNEz70VPEs4WVN-2BvDoa2AzMEifTBERp2OpJI-2FSo9vyN8SAdqm1K506JwSRDhErJLa3BMzYAnpiUOjVW4GQeV62XO4-3D" alt="" width="1" height="1" border="0" style="height:1px !important;width:1px !important;border-width:0 !important;margin-top:0 !important;margin-bottom:0 !important;margin-right:0 !important;margin-left:0 !important;padding-top:0 !important;padding-bottom:0 !important;padding-right:0 !important;padding-left:0 !important;" class="">
</div>
_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class="">https://lists.swift.org/mailman/listinfo/swift-evolution<br class=""></div></blockquote></div><br class=""></body></html>