I noticed via an Xcode autocompletion suggestion that #State seems to not only autogenerate a $-prefixed member for accessing the corresponding Binding (as is commonly known), but also a _-prefixed member, seemingly exposing the actual State wrapper.
This makes me wonder, what's the use case for it, and where is it mentioned in the docs?
I found out it's actually due to how Swift (rather than SwiftUI) compiles propertyWrappers under the hood.
From the official swift docs (under propertyWrapper):
The compiler synthesizes storage for the instance of the wrapper type by prefixing the name of the wrapped property with an underscore (_)—for example, the wrapper for someProperty is stored as _someProperty. The synthesized storage for the wrapper has an access control level of private.
Here's what's happening each time you use a propertyWrapper:
(From better programming)
As to its practical application in the context of SwiftUI, you can use it to initialize the #State variable, as described in this SO answer or this blog post.
Related
Headline: description called by super.init()
This is a new take on an old question. As a primarily Swift programmer I tend to not use NSObject for class definitions because of the residual side effects of Objective-C. Like if I have a read-only property called length and I then want to create a setter function called setLength, I get warnings about it conflicting with a similar definition from Objective-C. I just discovered the set(var){} setter. If I subclass a Cacoa class like UIDocument, etc. that inherit from NSObject, I have to live with these side effects.
I have a class that uses two other classes in the property definitions, none of them NSObjects. This class has a description computed variable that uses the description computed variables for the other two classes in its composition. All three classes need to conform to the CustomStringConvertable protocol. Ok, everything is good.
At some point this class got upgraded to being a UIDocument and the CustomStringConvertable became redundant and was removed. Everything still works.
Here is what I found out today. I wanted to break at a point in the program where it was printing one of the two properties and as a convenience I set the break point in the description variable for that class, thinking that it should only be called at the point I am interested in, where it is printed out. What I discovered is that the description variable gets called during all the super.init() of the UIDocument sub-class! And there were a few of them. I think composing strings as being relatively expensive but didn't care because they were only used in debug, but with them being called and who knows how they are used in super.init(), I need to change this.
I checked another UIDocument class in the same program that has 200 files associated with it and it is also calling description in super.init().
Does anyone have any input on the Best Practices for using description vs debugDescription?
I'm going to answer my own question as a matter of documentation.
I switched the UIDocuments subclasses to define and use debugDescription. I am debugging some code that loads all the files and does some manipulation and I was able to reduce the load time from 9.8 seconds to 6.8 seconds.
I also went through all the places where the Swift 3 conversion added String(describing:) to the program and found I could change a lot of them to using debugDescription and eliminate the String(describing:) wrapper.
I think the best practice is to only define and use debugDescription and for my non-NSObjects change conformance from CustomStringConvertable to CustomDebugStringConvertable.
In the Swift.org migration guide under the SDK section reference is made to struct “wrapper types”, I have a number of questions related to them.
In Swift 3, many of Foundation’s “stringly-typed” APIs have been
changed to use struct “wrapper types”, such as the new
Notification.Name type. Since, it’s common for notification names and
other string constants to be declared globally or as static members,
the best way to take advantage of these new types is usually to
construct the wrapper at the point of declaration:
What are these, are they a wrapper function? As described by wikipedia or are they an implementation of the Adapter Pattern
What are the benefits of using a struct “wrapper type”?
I've been trying to find the best way to implement a stored property in an extension, and came across this question: Swift extension stored properties alternative. However, I have not found a reason why in the discussion or anywhere else. Is there a reason why stored properties are not allowed in Swift? And if so, what is the reason?
Extensions are for extending the functionality of an existing class without changing the memory structure. It's more or less syntactic sugar. Imagine you could add stored properties and methods, what would it be? Nothing else but inheritance. So if you like to add new properties and methods just inherit from the class.
I'm having a strange issue that appeared with iOS 8 Beta 5 (this issue did not occur with previous versions).
I tried to create an empty project and try to replicate the issue, but I'm unable to do so, so I'm not quite sure where the issue lies.
What I'm seeing is that attempting to access methods of a custom NSManagedObject subclass results in a strange EXC_BAD_ACCESS error.
For example:
var titleWithComma: String {
return "\(self.title),"
}
This method, out of many others, causes this issue when called. However, adding a dynamic keyword before it makes the issue go away:
dynamic var titleWithComma: String {
return "\(self.title),"
}
I know I'm not giving enough info, because I honestly don't know how to pinpoint the actual issue, but can anyone explain what is possibly happening, and why adding dynamic might resolve this issue?
From Swift Language Reference (Language Reference > Declarations > Declaration Modifier)
Apply this modifier to any member of a class that can be represented
by Objective-C. When you mark a member declaration with the dynamic
modifier, access to that member is always dynamically dispatched using
the Objective-C runtime. Access to that member is never inlined or
devirtualized by the compiler.
Because declarations marked with the dynamic modifier are dispatched
using the Objective-C runtime, they’re implicitly marked with the objc
attribute.
It means that your property/method can be accessed by Objective-C code or class. Normally it happens when you sub-classing a Swift class of Objective-C base class.
This is from the prerelease Swift / Objective-C interoperability documentation:
Implementing Core Data Managed Object Subclasses
Core Data provides the underlying storage and implementation of properties in subclasses of the NSManagedObject class. Add the #NSManaged attribute before each property definition in your managed object subclass that corresponds to an attribute or relationship in your Core Data model. Like the #dynamic attribute in Objective-C, the #NSManaged attribute informs the Swift compiler that the storage and implementation of a property will be provided at runtime. However, unlike #dynamic, the #NSManaged attribute is available only for Core Data support.
So, because of some of the Objective-C runtime features that Core Data uses under the covers, Swift properties need to be specially annotated.
Sorry if it's too obvious for you. I'm still learning objetive-c and proper design patterns.
Could you explain me why it is a good idea to declare a property inside #interface in implementation file of a class as a private property? You just can use a local declaration of your type with a class scope, since nobody outside your class would use any getter or setter for this property.
Thanks.
By using the property semantics, you get memory management behavior handled 'for free' by the compiler. Even if your data is private within your class, having the compiler emit correct release/retain/copy saves time and mistakes down the line.
With the modern ARC compiler, this is probably less of an issue now.
When you declare something as #private, usually an instance variable or a property, it became only accessible in methods of the class that declared it. Trying to access it from a subclass results in an error.
I know you didn't asked for this but there is also #protected, when a property is declared like this, it becomes only accessible in methods of the class that declared it and in the methods of any class that inherits from that class.
The source for this info is the best book I know about Objective-C - Learning Objective-C 2.0 by Robert Clair.