> On Jan 13, 2017, at 11:27, Joseph Newton via swift-evolution
> <[email protected]> wrote:
>
> Hi,
>
> I've done a lot of Objective-C and have been been a fan of Swift since it's
> come out, however, there's a small feature of Objective-C that I would really
> like to see implemented in Swift:
>
> In Objective-C you have a few options implementation-wise when creating
> properties for your class. You could use the @synthesize statement to have
> the compiler create the backing ivar along with the appropriate accessor
> methods or your could use the @dynamic statement to tell the compiler that
> you're going to create your own accessor methods and backing ivar (if needed).
>
> Additionally, one could use the @synthesize statement to have the compiler
> create the backing ivar, and then they could create custom accessor methods
> to supply custom functionality or validation. I use this third case
> extensively in my Objecitve-C code but there's not a concise way of doing
> this in Swift.
>
> For example, I might have an Objective-C implementation that looks like this:
>
> @interface Foo : NSObject
> @property (nullable, copy) NSString *bar;
> @end
>
> @implementation Foo
> @synthesize bar = _bar; // Creates ivar '_bar'
>
> - (void)setBar:(NSString *)bar {
> if (bar.length < 100)
> _bar = nil;
> else
> _bar = [bar copy];
> }
>
> @end
>
> Currently, the only way to implement this in Swift - AFAIK - is as follows:
>
> class Foo {
> private var _bar: String?
> public var bar: String? {
> get { return _bar }
> set {
> if (newValue?.characters.count ?? 0) < 100 {
> _bar = nil
> }
> else {
> _bar = newValue.copy() as! String
> }
> }
> }
> }
>
> Although this works, it isn't exactly glamorous. The main drawback of this
> implementation (unless intended) is that you now have any additional '_bar'
> variable accessible within the scope of your class.
I believe you can do this using didSet without the `_bar`:
class Foo {
public var bar: String? {
didSet {
if (bar?.characters.count ?? 0) < 100 {
bar = nil
}
}
}
}
> My proposal is to allow stored properties in the declaration block of
> computed properties. For this example, the '_bar' declaration would simply be
> moved inside of the declaration block for 'bar':
>
> class Foo {
> public var bar: String? {
> var _bar: String?
>
> get { return _bar }
> set {
> if (newValue?.characters.count ?? 0) < 100 {
> _bar = nil
> }
> else {
> _bar = newValue.copy() as! String
> }
> }
> }
> }
>
> Only the getter and setter methods of 'bar' are allowed to access and modify
> the stored '_bar' property. My proposal would also allow for multiple stored
> properties of varying types within the scope of a single computed property.
> This would also simply atomic synchronization for single variables:
>
> class Foo {
> static var synchronizedBar: String? {
> var queue = DispatchQueue(label: "Foo.synchronizedBar")
> var bar: String?
>
> get { return queue.sync { return bar } }
> set { queue.sync { bar = newValue } }
> }
> }
>
> Are there any suggestions or arguments, for or against, for this proposal?
It's an interesting idea, for sure. Because of the persistent storage required
for `_bar`, I think one way to look at what you're proposing is essentially as
a way to allow for a variable to be declared publicly as one type, be
implemented as another (anonymous, in this case) type under the hood, and to
specify a mechanism for automatically converting between the two types.
- Dave Sweeris
_______________________________________________
swift-evolution mailing list
[email protected]
https://lists.swift.org/mailman/listinfo/swift-evolution