Hacker News new | past | comments | ask | show | jobs | submit login
Swift 2 Apps in the App Store (developer.apple.com)
80 points by julien_c on Sept 21, 2015 | hide | past | favorite | 32 comments



I ran the “Convert > To Latest Swift Syntax” on an app with about six view controllers, four views, a network service, and three cocoapods. It worked surprisingly well, most of the changes were really just suggestions ("this var something could be a let something"), small change to how NSData unwraps.

I did have to guess around an obscure compile issue (solution: "Clean Build Folder"), but after that it was clear sailing.

My overall Swift experience has been terrific. I’m not the first to say this, but to anyone who’s wondering if it’s “ready”, yeah, it’s ready.


+1 for mentioning the "Clean Build Folder" issue. I was stuck on that for about an hour yesterday, then I found this post:

http://stackoverflow.com/questions/32586144/upgraded-to-swif...

I didn't know about using the Alt key to reveal "Clean Build Folder", and I've been doing iOS dev for years. I'll add this to the list of unhelpful compile errors that are fixed by cleaning the build.


"Clean Build Folder" is basically the "turn it off, then turn it back on" of Xcode. Almost anytime you get a weird compiler error on a project that compiled fine moments ago, it's solved by "Clean Build Folder."

Definitely a good trick to know.


Or for those who prefer automating, add this to ~/.bash_profile:

   alias nuke="rm -rf ~/Library/Developer/Xcode/DerivedData/"


That's pretty drastic. That nukes the derived data folder of all your Xcode projects. If you work on more than 1, using this to solve a problem in 1 will lead to needing to rebuild all of your projects. That seems a bit extreme for an issue in a single project.


I always advice people to put their DerivedData and build folder somewhere accessible. You can change it settings, don't use the default setting.


Good tip. As someone with quite a small main HDD I'll do this ASAP.


cmd+shift+k followed by cmd+alt+shift+k is a multiple-times-a-day incantation for me :)


Definitely ready. I've had a Swift app out for 4 months and it's been quite successful[1], with no Swift-related issues.

I've just updated the app to Swift 2 and it's all working great.

The only issue has been related to the new Bitcode feature in iOS, which isn't Swift-specific. It's been very difficult getting third-party libraries with Bitcode support, but Bitcode is required for watchOS 2 apps.

[1] http://streaksapp.com


I really like Swift too, but for serious usage, I find that it still gets kinda wonky in generics land. Also, not crazy about the fact that there's no such thing as abstract classes. A lot of iOS coding for me is stuff that builds on top of each other. You can subclass, but there's so many times when it's "all subclasses gotta just do this one or two things and base class can take care of rest." So what you do is define them in the base-class and throw "Must override" exception, but still, I wish this mechanic would somehow just get built-in.

Anyway, Swift is a great language though I don't mean to discredit it. It just doesn't take the spot of my #1 -- Scala. :)


Protocol extensions seem like a good way to get what you'd frequently want out of abstract classes. What's missing?


What I want (Scala land):

  trait Robot
    var serialCode = generateSerialCode()
  
    def gas
    
    def engine = Engine(gas)
    def body = Body(engine)

  class SunnyRobot extends Robot
    def gas = sun

  class OilyRobot extends Robot
    def gas = oil
Protocol extensions don't hold state. They are meant to provide default implementations for a type, not as a 1:1 relationship with the class it's implementing functionality for. Following what you're saying, I would be doing something like this:

* `extension Robot where Self = SunnyRobot { def gas() = ... }`

* `extension Robot where Self = OilyRobot { def gas() = ... }`

That looks all good and well, right? Ok, well now my sunny robot wants to find the sun and my oily robot wants to go find oil. How to provide functionality unique to each of them? Maybe I'm just not getting something, but I'm pretty sure protocol extensions are not the answer to the problem I'm trying to describe.

When you're working in front-end land, you can do your best to stay functional and be cool and all that jazz, but it's just a waste of time usually. You're going to use a lot of state and you just have to learn how to manage that effectively (IMO). What this boils down to for me is that I might build a cell that does 3 things great and will be on every cell, but then business designs call for 2 slightly different cells still based upon that main cell. Oh and when those different cells are tapped, different things should happen.

So again, I just go about doing it with the simple base class gonna throw you an exception unless you override the "abstract" method. This way, I get to keep state going down and classes can actually fill up naturally rather than playing the protocol game.


Wouldn't you define gas() and whatever class-specific methods in the class itself, instead of in extensions on the protocol?

    class SunnyRobot : Robot {
      func gas() { ... }
      func findSun() { ... }
    }


By defining `gas()` in the children, you can't take advantage of it in base class. For example, the base robot might know how to move and all that, but the sunny robot just needs to know where it's going.

Protocol extensions just don't cut it, I'm sorry. They're great for defining some default behavior and doing kinda-abstract-classes, but it's a different playing field in Swift/Obj-C than Java/Scala/C#/etc..


I think this[1] does what you want, unless I'm not understanding your problem description. AFAIK you are correct about protocol extensions not holding state. So I don't think you can implement the `var serialCode = generateSerialCode()` with just a protocol. But you could do it with a protocol + base class.

[1]: https://gist.github.com/jayrhynas/49945331e41314fc3ede

Edit: I just realized that with this method, the protocol extension is useless, you could just define `move` on Robot. So protocol extensions can give you a mix of abstract & default methods but if you need to inherit state you need to use a base class.


All uploaded builds of my iOS 9 content blocker, written in Swift 2 with Xcode 7 GM, were (and still are!) stuck "In Processing" on iTunes Connect.

I rewrote the extension in Objective C and uploaded another build, and after a few minutes, I was able to submit it to the App Store.

Just a random anecdote that made me go back into late adopter mode for the rest of the year. It's great that Swift mostly works, but I'm really scared of the times when it doesn't.

(Edit: Not just me - https://forums.developer.apple.com/message/50182#50182)


Swift 2 seems to have fixed one of my biggest bugbears about Swift 1: that if you command-clicked a function where one of the parameters was the wrong type, it wouldn't take you to the closest matching declaration in the headers (as it did in Obj-C) but would instead tell you that it couldn't find the function declaration. Now it seems to work! No more having to dig through the docs for small corrections.

Dunno about exceptions, though. I've seen lots of great arguments against them on HN and elsewhere, and the error reference (or alternatively double-return via tuple, especially since you can name tuple slots) seemed more clear.


I love Obj-C (probably because I love Smalltalk). Before Swift 2, I didn't see what the excitement was about. Since using Swift 2, I want to use it everywhere. I will miss some of the dynamic features of Obj-C, but there are other ways to get to the same end. The terseness of Swift while maintaining Obj-C clarity, is wonderful.


That's a pretty small app. Sure, it's ready for smaller apps but, things aren't so great on larger scale apps.


This was being down-voted for no reason. He's right..


If your Swift app is using SpriteKit it might take a little longer to get it ready for the App Store: https://forums.developer.apple.com/thread/17463

Apple really screwed up SpriteKit badly in the new version. I'm experiencing almost all of the problems mentioned in the forum.


I scanned the post and it seemed the issues are regardless of the language.


That's true. I didn't want to badmouth swift, I quite enjoy developing with it. I guess I just needed to vent my anger about SpriteKit a little.


I maintain a database of Swift resources: http://www.h4labs.com/dev/ios/swift.html

It appears that most iOS devs who blog are using Swift.


Here's my prediction : apple is currently working on a replacement framework for cocoa (at least uikit), that will be writen for swift first, taking advantage of its great special features.

My other guess is that it will come in time for ios 10 and be cross-platform ( aka work on mac os as well as ios).

I have absolutely zero inside info, but the fact is cocoa felts great and elegant on ios3 , but with all the latest additions it now starts to feel old and convoluted. Objective-c has been patched incredibly well but can only go so far, and the convergence of hardware between devices makes the distinction between computers and tablets more and more obsolete.


Plus, OSX needs a UIKit-style revival, especially with all the recent grumbling about the Mac App Store. Having just written an OSX app after doing UIKit for several years, it feels incredibly old and clunky in comparison. Even simple layer transform animations are for the most part unsupported!


Ok cool, but where's the source code? It's been almost three months since the announcement and no ones even mentioning it anymore.


This was ask on Reddit recently, and Chris Lattner answered:

https://www.reddit.com/r/swift/comments/3kbjjn/so_swift_isnt...

We are still on track to open source Swift (including Linux support) "by the end of 2015" as promised, more details will come out when they can.

-Chris


Swift 2 is fantastic except (har har) for exceptions. Optional<T> has been hanging out, monad-y and all, since v1. Why not Result<T, E>? You can't flatMap exceptions, and the Swift 2 implementation even throws away type data (or hides it, at least). Huh?


I guess you mean the new do-try-catch syntax? IMO it's quite lovely, and strikes exactly the right balance between the checked exception tyranny of Java, and the strap-in-and-good-luck wild west of C++.

My favorite feature of Swift's exceptions is the 'try' syntax required at the call site. This isn't like Java's try syntax: every call that may raise an exception needs a try, even if all you want to do is rethrow the exception. But the syntax is lightweight: just preface the call with 'try', it doesn't make a new scope. This makes the abnormal control flow explicit, addressing one of the strongest critiques of Java-style exceptions.

My second favorite features is the 'try!' syntax. This is the escape hatch: Swift's version of the empty-catch-block pattern of Java, except that it's 1. much more lightweight, because it doesn't introduce a new scope, and 2. the default behavior is to abort instead of swallow. It's perfect for non-production code like tests.

Regarding "you can't flatMap exceptions," I would respond that exceptions are meant to be exceptional, and this is what justifies the abnormal control flow. The do-try-catch syntax is an adequate substitute for flatMap, and more lightweight than requiring explicit unpacking of every return value ala Go.

But as you say, the hiding of type data is definitely weird. For those following along at home, Swift requires explicitly annotating functions that may throw errors, but not what those errors are, so you have to refer to the documentation. Also the compiler will complain if you don't have a backstop exception handler. Lastly, it introduces a magic variable 'error' that is defined within catch blocks: convenient but it feels ad-hoc.


Well, for example, try/catch don't work asynchronously, so you can't pass it to a callback (or use it in a SignalProducer in RAC). If failure/success is Just Another Value, it works everywhere that values work. That they already use an ADT for nullability it what confuses me - ".None, but with an error" isn't a far off concept from that.

antitypical/Result already provides Result.init(() throws -> T) -> Result<T, E>, so it's easy enough to work around, at least.

The magic variable stuff exists in didSet as well, weird and sketchy to use. Would prefer it to be explicit in all cases.


There are no exceptions in swift.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: