Hacker News new | past | comments | ask | show | jobs | submit login
Dictionary and Set Improvements in Swift 4.0 (swift.org)
116 points by Nuance on Oct 4, 2017 | hide | past | web | favorite | 69 comments

The language definitely feels like it has matured as the change from 3.0 to 4.0 was pretty much painless. The big issue with programming in Swift is no longer swift itself but the libraries around it. A lot of the API's you use in day to day Cocoa programming are based on Objective-C and often stringly typed and not very compile safe.

For example NSNotificationCenter, setting attributed strings, core data or fetching resources. Also the whole MVC ViewController lifecycle is full of optionals. A lot of people abandon using Storyboards just to have ViewControllers that have everything set up compile safe, don't use prepareForSegue to pass in variables and so on. But that means doing everything in code, which is inefficient for complicated one-off layouts.

Attributed Strings got better type information in Swift 4 (it got what Notification keys got in Swift 3), but like notifications it's an open-ended API so I don't know what else you can do...

You can't use an enum for the keys because it supports custom attributes (at least you can't without exposing a `.custom(name: String)` case, which would defeat the purpose). And the values can be different types (enums for underline styles, URLs for links, [NS|UI]Color for foreground colors, etc.). I think the `NSAttributedStringKey` box type is a good compromise.

Maybe I'm biased (the Cocoa text system is one of my favorite APIs, and NSAttributedString is at the top), but I'm really happy with the state of attributed strings in Swift 4 myself.

True, but that's exactly the kind of change to the API required to make it more compile-safe. I still managed to crash this API by not providing a .rawValue somewhere. I don't think applications need to crash on key-value errors.

An enum wouldn't be so bad if it also would use the associated value. Would make it impossible to set the wrong value at least.

Ahh right, NSUnderlineStyle... I totally thought that was improved in Swift 4, what a bummer. I have some unit tests in my apps that make sure I'm setting the .rawValue instead of the enum case itself, because that one does suck. I'm gonna file a bug.

Yup that was exactly the one!

I see Swift supports generics so could they let you define subclasses of string enums that support custom string values?

Swift also supports associated values with enum cases, so you could do something like this[0] and get type-safety. Now you could only associate a URL type with a link attribute, or an NSColor type with a foregroundColor attribute, etc.

However, you can't (at least currently) add new cases to someone else's enum (the way you can add methods). So if I decided I wanted my own custom text attributes (which isn't uncommon), we're back to type-unsafe land. We'd need the original enum to have an extra attribute case, like this[1].

[0]https://pastebin.com/L1xPcueu [1]https://pastebin.com/h8Rp3Ajy

Storyboards kind of suck for any team bigger than 1 as far as I’m concerned. They also lock you into a visual binding style development pattern the doesn’t scale as your app grows. Don’t get me wrong, they’re great for fast prototyping or teaching someone how to write code as it helps with a ton of boilerplate.

I think that's a bit overstated but it really depends what kind of application you're writing. I have an accounting app I maintain alone where I almost completely abandoned storyboards because a lot of screens had similar elements and it was very important to have all data reliably passed around. Also helped with consistency and maintainability. On the other hand I'm doing a new app with three people now where we use storyboards because every screen is vastly different.

The following things should be improved to make storyboards more useful in teams:

* No more bullshit changes of 0.5px just by looking at the storyboard alone

* Compile time check for connected outlets and actions, allowing to set them without the ! or ?

* Constructable view controllers that always require you to init them in some kind of way, so you don't end up with optionals everywhere

* Reusable constants for colors, sizes etcetera. I want to simply state cellSpacing as a value for the constant of a constraint where cellSpacing is something I can change in one place.

* Reusable components / controls, like .xibs but immediately visible

* Less flaky IBDesignable performance

Some nice improvements but could have really used a syntax for anonymous functions that makes.

Why did they choose this wierd

{ parameter in doSomething(parameter) }


I think Swift's philosophy is to use keywords when possible instead of symbols, for better typability.

Looks fine to me. What's wrong about that syntax?

Feels backwards to me, at least as a gut feel.

    groceriesByDepartment.mapValues { items in items.count }
vs e.g. Ruby (or at least close, it has been a while):

    groceriesByDepartment.map { |item| item.count }
The "in" makes it feel like you're calling "items.count" on...? and then getting the "items" from it (since it sorta implies that items are in items.count, which seems like nonsense).

E.g. this reads more naturally to me:

    groceriesByDepartment.mapValues { item.count in item }
    otherStuff.do { a.value + b.value in a, b }
which would also move the "what it does" further to the left, rather than having to skip over the argument names (which are frequently obvious in context, and/or something trivial like "it" or "item" or "x").


That said, if you consider it as "use 'items' in [a block of code]" it basically makes sense, and I could probably learn to stop worrying, and love the syntax.

I agree, the examples in the article look terribly confusing. And they're inconsistent with Swift's own for loop syntax: https://developer.apple.com/library/content/documentation/Sw...

    for item in groceries { print item.department }

    Dictionary(grouping: groceries by: { item in item.department })
The people who chose this syntax probably said "hey, it's VARIABLE in EXPRESSION, same thing right?". But the semantics are completely different!

In the for loop it's "for PRODUCT in SOURCE": the expression is evaluated first, and the variable is assigned with each of its items in turn. In the lambda or whatever it is, it's "{ SOURCE in PRODUCT }": first the variable is assigned, then the expression is evaluated based on it. The data flow is the opposite!

This is just objectively bad language design.

I prefer Ruby's syntax too, but Swift also has a shorthand version which is, IMO, usually nicer.

  groceriesByDepartment.mapValues { $0.count }

stuff like this always makes me miss Ruby's even-shorter-hand version though :)

  groceriesByDepartment.mapValues(&:count)  # not ruby, but meh

The shorthand version doesn‘t let you specify argumen types (only works when they can be inferred)

Which is vast majority of cases. Unless you work with a lot of legacy ObjC code.

Well, for starters, what does it mean? I haven’t seen that in any other language.

It is similar to let var=..... in exp from ML languages.

Haskell have let-in expressions, I think it is the inspiration for swift in this case.

You can also shorten it to:

{ doSomething($0) }

Or just


I wasn't aware of that syntax? It will just pass the arguments from the parent to the child in order?

As long as the signature of the function matches you can pass it in directly

Functions are values in Swift. Closure literal syntax is just a shorthand where you don’t have to name the function first.

The emojis are cute in this description of language changes, but I’m worried some programming newbies will look at this as an example of “pros” / Apple endorsing it and will start using them in real programs.

One of the many reasons you have code reviews. A formal review isn’t even necessary, since the first time anyone but the author sees the code, the ensuing ridicule will ensure that it never happens again.

OTOH, one of things hammered into me at Microsoft was “sample code becomes production code”.

Why stop at identifiers when you can have C++ #defines? http://lallouslab.net/tag/emoji/

Please give us concurrent collections.

I was a bit disappointed at the string api in swift4 recently. They removed the need to access characters every time, but they kept the Index type, which adds an intermediate step every time you want to build a range, without providing any more safety than just using integers: it still crashes on index out of bounds, so you still need to manually bound check, only you have to compare to startIndex and endIndex.

I still don’t get the benefit..

I really wish Swift could find a way to be useful on platforms other than Apple. I'd be willing to commit more to it if I could write truly portable code in it. It's got a good start on Linux, but Windows and Android would be cool too. Though Kotlin won out over Swift for Android (very similar languages but I like Swift a bit better there).

Any language that wishes first class support on Android needs to support a painless way to interoperate with Java APIs on their compiler toolchain.

Otherwise developers are going to have lots of pain manually writting JNI wrappers to 90% of Android APIs.

Likewise on Windows with COM support.

let's say android or windows adopted swift. I don't think that would eliminate the biggest learning curve of dealing with the frameworks. in my experience, learning UIKit stuff was way trickier than swift. I imagine the same experience developing for other OS'.

I dunno how true that is, Rust has fantastic support across Windows and Android but leaves UI framework up to the platform.

I wish Rust had such fantastic support you claim.

There is no support for integrated debugging, across languages on Android Studio and Visual Studio.

No support for COM or UWP and Win32 is WIP.

Not sure how much NDK APIs are actually wrapped.

I hate to be a bit blunt but you're really barking up the wrong tree.

VSCode debugger works fine on both msvc and mingw targets.

Asking for COM or UWP is like saying that Javascript has a horrible interop story with COM/UWP. You're picking Rust to build something fast and/or low memory. Leave building a UI to the right tools.

C# has a fantastic FFI and works just fine with Rust. I actually have a project using UWP and Rust together. I get all the portability of Rust and get to use UWP as the UI frontend with minimal fuss.

I am just raising awareness, it is all a matter if you feel like it matters to earn the hearts of. Windows developers using to their VS, C# + C++ and respective tooling productivity.

Picking up your example,how do you expose and debug UWP components?

Those are probably what the parent means by "UI framework." The Rust toolchain does integrate seamlessly with those platforms' native toolchains, using the same binary and debug info formats.

Perhaps this is perception is just caused by e.g. the extremely low bar set by MinGW, which doesn't do any of that despite "supporting" Windows.

Those stacks are more than just UI.

For example since Longhorn failure, COM has become the major way to introduce Windows APIs, since Vista Win32 doesn't get much love.

I think that’s what he’s saying?

Sort-a. I think frameworks are a separable problem with the platform support.

You can lump UI frameworks in with others, right?

I'm talking more about portable business logic, libraries I could write and access on all platforms.


This is a good start, at least for Android hardware..

Amazing. Thanks for the link.

It's probably going to end up similar to the equally hyped objectiveC where the core language was made portable but few of the tooling/API's used for real world OSX applications ended up supporting anything but OSX in any production ready capacity despite GNUSTEP actually shipping a ObjetiveC/OpenSTEP clone for Linux.

For the time being swift on Linux is a case of a few PaaS vendors trying to product differentiate by also offering swift frameworks because they can(due to modern container wrangling) more then due to any real market demand.

One of the biggest causes of this for Objective-C was the lack of the Foundation framework (a higher-level interface to Core Foundation) - but this is being reimplemented in Swift. See https://github.com/apple/swift-corelibs-foundation

Of course UIKit will still be missing, but thats sort of expected.

Not if Microsoft keeps this up: https://github.com/Microsoft/WinObjC/tree/develop/Frameworks...

I'm not saying that's entirely reasonable, but it exists.


”macOS, Ubuntu Linux LTS, and the latest Ubuntu Linux release are the current supported host development operating systems”

Also, on the page you reference:

”Note that all compiled Swift binaries are only executable within Bash on Windows and are Ubuntu, not Windows, executables.”

> macOS, Ubuntu Linux LTS, and the latest Ubuntu Linux are the current supported host development operating systems

I believe that "supported" here means the test suites and CI are run on those platforms. More importantly, any regressions on those platforms would be considered bugs. However, there have been partial or complete ports to several other platforms, including some weird ones.

Aside from Apple platforms, I see code in-tree for Linux, CYGWIN, Windows, FreeBSD, PS4[0], Android, and Haiku[1] (a revived BeOS). And that's not some stray LLVM code, it's in the Swift compiler itself. I've read that there was/is an out-of-tree upstream port to some IBM mainframe hardware, as well.

A bit tangential to your original point, but I think it's interesting.

[0]https://github.com/apple/swift/commit/83901998c91f9242a133aa... [1]https://github.com/apple/swift/commit/aee81d272f3147c0a9b610...

I really wish Apple would focus more on getting Xcode up to par. It's in a truly horrid state, both performance and feature-wise. Developing an Objective-C app is worlds ahead of Swift right now.

Are you aware that Xcode 9 just shipped last week and is a major rewrite of much of the IDE? It's one of the largest updates in Xcode's history.

XCode 9 is unsurprisingly terrible for me. Between it and the Swift tool chain, they use over 10 gbs of memory and constantly using 100% of my CPU. XCode 9 seems like an improvement over 8 in some cases, but its way less stable, uses an insane amount of resources, and crashes more often.

It’s been so bad that I actually installed Jetbrains AppCode. It’s working great . I finally just bought the entire subscription since I already use IntelliJ, datagrip, gogland, and webstorm

Xcode 9 has been a lot less stable for me compared to previous versions. It will lock-up multiple times per day during simple text editing tasks, with SourceKitService going bananas until I force quit it.

It boggles the mind that they just can’t seem to fix SourceKitService for three versions now, it’s such a massive part of making the Xcode experience suck.

It’s worse than no completion, you never know when it’s actually going to work.

I guess it does do something though, for eating up all those cycles.

> it’s such a massive part of making the Xcode experience suck.


Whenever my fans start spinning up, I head on over to Activity Monitor and sure enough SourceKitService is sitting at 120% CPU draining battery like nothing else.

I probably kill the service between 5-10 times a day when using Xcode.

I've found that disabling 'live issues' in preferences helps somewhat, at the expense of not getting live updates to errors as I'm typing, but SourceKitService will still go off the deepend - usually while adding stuff that will not yet compile because I haven't included the appropriate headers yet or am still refactoring/moving about code.

Sounds like a great reason to stick with v8 for at least six months.

So ... any good?

The only that truly annoyed me was that CMD+click doesn't work immediately anymore but conjures some kind of intermediary menu. Haven't figured out if there's a new keystroke for it, but I'm still doing too much work in Xcode 8.

To me it was nothing but progress compared to 8 apart from that. Everything faster and better.

There is a checkbox in Xcode preferences to change it back. Not sure where as I’m on mobile, but that annoyed me to no end till I found the option.

I agree on faster and better, but still buggy. Autocomplete still regularly dies for me and requires a restart (of Xcode.)

Preferences > Navigation > "Command Click on Code"

The new key command for it is right there in the menu when it pops up. If you select the first item to do what the old command did, it's literally just to the right of the command!

Yeah....but muscle memory....

It's CMD+Control

I haven't used it much yet myself, but I did notice that one annoyance I had was fixed, regarding zooming the font onscreen.

I've used it for a couple of days now. I've seen some issues with the Simulator but I think that's not strictly related to the IDE. As far as Xcode and the editor is concerned - it's extremely quick now. Functionally also better in terms of the code editor.

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