<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><blockquote type="cite" class=""><div class="">On Dec 10, 2015, at 3:31 PM, Riley Testut via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:</div><div class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">Using box types solves the portability problems, but it still means O(n) access for clients who want to access the non-boxed values directly. Additionally, these objects aren’t automatically removed from the collection when their values are nil-ed out, which is unfortunate.</span><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br class=""></div><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;">Side note: this is the route I originally tried to take, but unfortunately the Swift doesn’t work well with weak references to protocol types…</div></div></blockquote><div><br class=""></div>Really? Please file a bug about this; I’ve been working in this area recently.</div><div><br class=""></div><div>(Or just point out the radar number if you filed one there already.)</div><div><br class=""></div><div>John.</div><div><br class=""><blockquote type="cite" class=""><div class=""><div class="" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;"><br class=""><div class=""><blockquote type="cite" class=""><div class="">On Dec 10, 2015, at 3:01 PM, Tommy van der Vorst <<a href="mailto:tommy@pixelspark.nl" class="">tommy@pixelspark.nl</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;"><div class="">Hi Riley,</div><div class=""><br class=""></div><div class="">Have you tried using an array of structs that in turn hold weak references to your objects? Something like this should work:</div><div class=""><br class=""></div><div class=""><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;"><div class="" style="margin: 0px; line-height: normal;"><span class="" style="color: rgb(4, 51, 255);">public</span><span class="Apple-converted-space"> </span><span class="" style="color: rgb(4, 51, 255);">class</span><span class="Apple-converted-space"> </span>Weak<T: AnyObject>:<span class="Apple-converted-space"> </span><span class="" style="color: rgb(52, 149, 175);">NSObject</span><span class="Apple-converted-space"> </span>{</div><div class="" style="margin: 0px; line-height: normal; color: rgb(4, 51, 255);"><span class=""><span class="Apple-tab-span" style="white-space: pre;">        </span></span>public<span class=""><span class="Apple-converted-space"> </span></span>private(set)<span class=""><span class="Apple-converted-space"> </span></span>weak<span class=""><span class="Apple-converted-space"> </span></span>var<span class=""><span class="Apple-converted-space"> </span>value:<span class="Apple-converted-space"> </span></span><span class="" style="color: rgb(52, 149, 175);">T</span><span class="">?</span></div><div class="" style="margin: 0px; line-height: normal; min-height: 13px;"><br class=""></div><div class="" style="margin: 0px; line-height: normal;"><span class="Apple-tab-span" style="white-space: pre;">        </span><span class="" style="color: rgb(4, 51, 255);">public</span><span class="Apple-converted-space"> </span><span class="" style="color: rgb(4, 51, 255);">init</span>(<span class="" style="color: rgb(4, 51, 255);">_</span><span class="Apple-converted-space"> </span>value:<span class="Apple-converted-space"> </span><span class="" style="color: rgb(52, 149, 175);">T</span>?) {</div><div class="" style="margin: 0px; line-height: normal;"><span class="Apple-tab-span" style="white-space: pre;">                </span><span class="" style="color: rgb(4, 51, 255);">self</span>.<span class="" style="color: rgb(52, 149, 175);">value</span><span class="Apple-converted-space"> </span>= value</div><div class="" style="margin: 0px; line-height: normal;"><span class="Apple-tab-span" style="white-space: pre;">        </span>}</div><div class="" style="margin: 0px; line-height: normal;">}</div><div class="" style="margin: 0px; line-height: normal;"><br class=""></div><div class="" style="margin: 0px; line-height: normal;"><div class="" style="margin: 0px; line-height: normal;"><span class="" style="color: rgb(4, 51, 255);">let</span><span class="Apple-converted-space"> </span>weakFoo: [<span class="" style="color: rgb(52, 149, 175);">Weak</span><<span class="" style="color: rgb(52, 149, 175);">Foo</span>>] = [Weak<<span class="" style="color: rgb(52, 149, 175);">Foo</span>>(foo), ...]</div></div><div class="" style="margin: 0px; line-height: normal;"><span class="" style="font-family: Helvetica; font-size: 12px;"><br class=""></span></div><div class="" style="margin: 0px; line-height: normal;"><span class="" style="font-family: Helvetica; font-size: 12px;">Comes with the overhead of one extra object instantiated per element, but perhaps this is acceptable for your use case.</span></div><div class="" style="margin: 0px; line-height: normal;"><span class="" style="font-family: Helvetica; font-size: 12px;"><br class=""></span></div><div class="" style="margin: 0px; line-height: normal;"><span class="" style="font-family: Helvetica; font-size: 12px;">/T</span></div></div></div><br class=""><div class=""><blockquote type="cite" class=""><div class="">Op 10 dec. 2015, om 23:55 heeft Riley Testut via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> het volgende geschreven:</div><br class="Apple-interchange-newline"><div class=""><div class="" style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;">In multiple places in my projects, I essentially recreate the “multiple observer” pattern used by NSNotificationCenter. Originally this was implemented by simply maintaining an array of observers, and adding to/removing from it as necessary. However, this had the unintended side effect of maintaining a strong reference to the observers, which in many cases is undesirable (for the same reasons it’s common to mark delegate properties as weak).<div class=""><br class=""></div><div class="">Now, I’m using a private NSHashTable instance, and expose the observers as public API by creating a public computed property which essentially returns an array derived from the NSHashTable like so:</div><div class=""><br class=""></div><div class=""><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135);"><span class="" style="color: rgb(187, 44, 162);">public</span><span class=""><span class="Apple-converted-space"> </span></span><span class="" style="color: rgb(187, 44, 162);">var</span><span class=""><span class="Apple-converted-space"> </span>receivers: [</span>GameControllerReceiverType<span class="">] {</span></div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(0, 132, 0);"><span class=""> <span class="Apple-converted-space"> </span></span>// self.privateReceivers.allObjects as! [GameControllerReceiverType] crashes Swift :(</div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo; color: rgb(79, 129, 135);"><span class=""> <span class="Apple-converted-space"> </span></span><span class="" style="color: rgb(187, 44, 162);">return</span><span class=""><span class="Apple-converted-space"> </span></span><span class="" style="color: rgb(187, 44, 162);">self</span><span class="">.</span>privateReceivers<span class="">.</span><span class="" style="color: rgb(112, 61, 170);">allObjects</span><span class="">.</span><span class="" style="color: rgb(61, 29, 129);">map</span><span class="">({ $0<span class="Apple-converted-space"> </span></span><span class="" style="color: rgb(187, 44, 162);">as</span><span class="">!<span class="Apple-converted-space"> </span></span>GameControllerReceiverType<span class=""><span class="Apple-converted-space"> </span>})</span></div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;">}</div></div><div class="" style="margin: 0px; font-size: 11px; line-height: normal; font-family: Menlo;"><br class=""></div><div class="" style="margin: 0px; line-height: normal;">This workaround works, but is undesirable for a number of reasons. Most notably:</div><div class="" style="margin: 0px; line-height: normal;"><br class=""></div><div class="" style="margin: 0px; line-height: normal;">• NSHashTable is not a native Swift collection, and is also not in the Foundation Swift port, so it is not portable to other systems.</div><div class="" style="margin: 0px; line-height: normal;">• It also has not yet been annotated with generics, so it loses the nice type safety of other Swift collections. Because of this, I have to map the objects to the appropriate type before returning the allObjects array, which runs in O(n) time instead of O(1).</div><div class="" style="margin: 0px; line-height: normal;">• It’s repetitive. For every type that wants to implement this pattern, they must maintain both a public computed method and a private NSHashTable instance. This gets worse when this should be part of a protocol; there’s no way to enforce that each type conforming to it has a NSHashTable, while also keeping that information private from the consumer of the API.</div><div class="" style="margin: 0px; line-height: normal;"><br class=""></div><div class="" style="margin: 0px; line-height: normal;">I think native swift collections with support for weak references for their contents would be very useful, and in more places than just listed above. I don’t think Array could be easily extended to support it (what happens if a value is released? does everything shift down? do they keep their indices?), but Set and Dictionary (where the keys and/or values could be weak, akin to NSMapTable) would be good candidates IMO.</div><div class="" style="margin: 0px; line-height: normal;"><br class=""></div><div class="" style="margin: 0px; line-height: normal;">Thoughts?</div><img src="https://u2002410.ct.sendgrid.net/wf/open?upn=YfJegnDVHFjciv1mJPW79zu0hcjAYJ-2BpFoOAdq9R1JegFoDiuAY72lo9JBPV9zgQfc4e6VQJ2kVBrFKRr6DXU69HIvGPIKP3Z3eDnjZEShrasSIbq1T78yYiMv5tnYs0IkNFdTO2nG47SXXRVxqkzpMw9PAfXj7w8NXOKj4fA0fNKN1ewpqMjFY9yXrmgQl5JoULpM7xC7N44MTq5RejCf1WiNVps9aGnucVZ5TgUi4-3D" alt="" width="1" height="1" border="0" class="" style="height: 1px !important; width: 1px !important; border-width: 0px !important; margin: 0px !important; padding: 0px !important;"></div>_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br class=""></div></blockquote></div><br class=""></div></div></blockquote></div><br class=""></div><img src="https://u2002410.ct.sendgrid.net/wf/open?upn=hWKWvOREWCPT32eVzNXOV7yIWXgGOvlMtgjKbOieJnbLmYmK8GPyhLdUqTDTpTuTdecc2yd8uzkqfgP4-2FMkghPzcFyiUytQS44r-2F1tgbY-2Bl79ejPZlNXG8nsKLPyGmU6GxXtA4yfxfMnc0C4JQZdS5uCOy0Af4M9tdbLKaQQmJ8EkRloSboNnKRIA0FmDn1decG5kSapRPi5xlHeH5o-2BWn2YAT8aexUp-2FxBIqQZ3ob4-3D" alt="" width="1" height="1" border="0" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; height: 1px !important; width: 1px !important; border-width: 0px !important; margin: 0px !important; padding: 0px !important;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class=""><span class="Apple-converted-space"> </span></span><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">_______________________________________________</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">swift-evolution mailing list</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><a href="mailto:swift-evolution@swift.org" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">swift-evolution@swift.org</a><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class="">https://lists.swift.org/mailman/listinfo/swift-evolution</a></div></blockquote></div><br class=""></body></html>