Our company is still sticking to Objective-C, but my goal is to have at least one of our apps use Swift when Swift 2.0 is ready. Today I wrote a small tool in Swift and I'd like to ask a few questions based on that experience. - When implementing delegates in Swift, there were two things that puzzled me: 1) Swift doesn't allow optional methods in a protocol (unless you decorate it, but my goal is Swift-only). 2) I don't have to make my "var delegate" weak? - Swift could implement a few more overloads to make it a bit easier / friendlier to use. I know that you can create what your heart desires by creating extensions, but it takes time, is prone to bugs and distracts from the actual work. For example, the Array type seems to lack a remove method that takes an object argument and a method to find the index of an element. If you use a Set you do get that remove method. The Set's removeAll method forces you to specify a keepCapacity argument, which seems irrelevant in 99% of the use cases? - Why do we call extra initializers in classes "convenience initializers", but just regular extra initializers in structs? - Why do many for-loop examples in Swift write ; ++i at the end instead of i++. It gives a false sense that your loop will start with 1 instead of 0, but I assume it doesn't matter which of the two you write there. - Working with JSON is a pain in Swift. Although Swift 2.0 will make that a bit easier with the guard statement. It doesn't help that Xcode 6.4 doesn't really understand how to indent multiple "if let ..." statements separated by commas. - There is no autocompletion in Xcode of module names when you type "import ..."? - Just a sidenote: the Cocoa classes for OS X need some love. Adding labels, that are actually NSTextFields and setting the text via the oddly named property "stringValue". Even worse is the NSTextView, that you have to dig out of the NSScrollView, dig into its optional textStorage and append a NSAttributedString. A bit of legacy framework that could use some TLC? Thank you.
A Day With Swift
It seems that the forum isn't iPhone compatible? All my newlines were stripped and I can't edit my post?
You should file bug reports for basically all of this. A couple of things:
— Swift does allow optional methods in a @objc protocol
— It varies on a case by case basis whether a delegate is weak. Some delegate-using-classes need to keep a strong reference to a delegate, others don't.
— In many cases, the delegate is going to be unowned, not weak.
— Since arrays are, in general, arrays of Any, there isn't an object reference to search for, nor is there Equatable conformance to use for searching (corresponding to indexOfObjectIdenticalTo: and indexOfObject: in NSArray).
— 'keepCapacity' has a default value, so you don't need to specify it.
— For integer-based loops, 'for i in 0 ..< count' is probably a more natural Swift construction that the C-ish one with an increment and a test. (Writing the increment as a pre-increment is just something some people do. It'd be a mistake to regard it as implying anying. But it's an entirely C style matter, nothing to do with Swift.)
— NSTextFIeld.stringValue is a consequence of being a subclass of NSControl, which has a more general value mechanism (the typeless objectValue is the property underlying all the type-specific ones). This sort of thing is a historical artifact going back to the Next days, and the fact that it hasn't been changed in 30 years or so probably tells you something.
— Yes, entering and editing forum posts in iOS is pretty much broken.
Convenience initalizers in classes are different from designated initalizers, since only the designated initalizers have to initialize all instance variables. This is a relevant distinction when subclassing. Structs cannot be subclassed, so this distinction is not relevant for structs. That at least how I interpret the language.
I believe you are mistaken with the operator increments bit. ++i happens before evaluation, i++ happens after.
If it doesn't behave this way in Swift, it's a bug and a possibly serious bug at that.
A simple use such as printing an integer won't really care but, a conditional loop may.
For instance in a loop that you want to go through 10 times, if you start of with i=0 and compare
i<10 then the loop will only run 10 times with ++i but will attempt to run 11 times with i++
If you increase the scale of these values to 64 bit integers this could result in some serious
problems. Especially if your code is directly mapping specific bits in memory as one might
in a kext or modifying an audio or video buffer.
I think we're talking about this:
for i = 0; i < 10; i++ { … }
which is equivalent to this:
var i = 0
while i < 10 {
…
i++
}
(with the test at the top of the loop and the increment at the bottom). In those circumstances, it doesn't matter whether the increment is i++ or ++i, since the actual result of the increment expression isn't used — all that matters is its side effect of incrementing i.
In the "Basic Operators" section of the Swift Programming Guide, it says
Unless you need the specific behavior of
, it is recommended that you usei++
and++i
in all cases, because they have the typical expected behavior of modifying--i
and returning the result.i
which might explain why we see ++i much more often now in Swift, compared to objC and other languages where the convention-by-default has been to write i++ for statements where the return value is ignored.
Great replies, thanks guys!
Quincey, why does Swift only allow optional methods when it is decorated with @objc. What to do in a Swift only world? And could you give me a proper delegate example in Swift? There seem to be a lot of incorrect examples. Thanks!
Ahltorp, why is the distinction between designated and convenience initializers relevant? One way or another they all have to initialize all local variables right?
Why haven't they implemented a "default" implementation of Equatable to compare references based on their memory address? You can guarantee that two instances are the same if you are actually comparing against yourself.
You can guarantee that two instances are the same in that case, but you can't guarantee that they're not the same in all other cases, so your default doesn't make sense generally. It's only a few lines of code to make a class comparable using its objectIdentifier so I don't see much value there.
By “the same” I mean “equal” but the forum software won't let me edit my own post to clarify that.
In my opinion the reason why Swift supports "optional" protocol methods only for Objective-C objects is to keep protocol conformance strict in pure Swift while supporting optional protocol methods for Objective-C objects for language interoperability.
In pure Swift, you can use the new protocol default method implementations instead.
It is only the designated initalizers that initalize the variables. The convenience initalizers are required to call a designated initalizer before they access/assign any instance variables. In that way, convenience initializers are more like Objective-C factory methods, but they cannot actually choose which object to return.
default implementations don't really do the same thing as optional methods in a protocol.
nesting protocols could do it, and that would be nice for other reasons, but in this case it'd just increase boilerplate.