try! Swift NYC 2017 Recap
In case you’ve never heard of it, try! Swift is one of the newest iOS conferences on the block. First starting in Japan in March of 2016, try! Swift has quickly become an international conference, recently adding Bangalore as its third and final stop for this year. The conference is organized by Natasha Murashev (@NatashaTheRobot) who also runs the This Week in Swift iOS newsletter (which I highly recommend signing up for). Earlier this month, I had the opportunity to attend my first try! Swift conference in New York City.
About the Conference
The single track conference spanned three days — one pre-conference workshop + two main conference days — and had some awesome presentations by over 20 speakers. I really enjoyed the format of the conference, with each talk lasting roughly 20–30 min and direct access to the speakers during “office hours.” There was a dedicated space outside of the main theater where each speaker would post up for questions immediately after his or her talk.
In addition to all of the wonderful speakers, there were what I consider some “big names” in the iOS community in attendance as well. There was support from server-side swift leaders like Jonathan Guthrie (Swift Perfect), who ran the server-side Swift workshop; and Tanner Nelson (Vapor), who did a presentation on server-side Swift and Vapor in general. RxSwift founder, Krunoslav Zaher, did a talk on a new RxSwift architecture called RxFeedback. There were also well-established bloggers like Soroush Khanlou (khanlou.com), who wasn’t a schedule speaker, but filled in for a presenter who got sick. Other blogging veterans include Matt Gallagher (cocoawithlove.com), who did a great view-state driven application presentation; and Ash Furrow (ashfurrow.com), who ran the RxSwift workshop.
Favorite Talks
These are my notes from some of my favorite talks of the conference. While all of the talks were awesome, these presentations stood out as being most relevant to my current proficiency and interests within iOS development. I’ve included links to code and/or presenter notes, if possible. I will do my best to keep the page updated as I find more speaker materials are released. It’s also worth noting that all talks were recorded by Realm, and the videos/transcripts will be available soon!
Update 9/26/2017: Realm has started posting the videos from try! Swift NYC 2017. Check them out on the conference page of Realm Academy!
Map and FlatMap Magic
Video: https://academy.realm.io/posts/try-swift-nyc-2017-neem-serra-map-and-flatmap-in-swift/
Slides: slideshare.net/NeemSerra/map-and-flat-map-magic
This talk contained many cool and new (to me) map
and flatMap
techniques. Neem went over the basics of map
and flatMap
using example collections of simple Cupcake
structs to make it easier to understand what was going on.
I really enjoyed how Neem gave several before and after examples where she showed the “old way” of doing something before unveiling the “new way” of accomplishing the same task using functional techniques.
The “old way” typically involves a lot of for
loops that modify mutable state. This is one of the shorter examples:
The new, functional way of doing things involves what Neem described as “visually explicit chaining” to create a clear, sequential code path:
Despite the somewhat introductory sounding title, there was so much good information in this presentation that I will be doing a separate blog post later to highlight the tips and tricks I felt will help me the most!
Driving view state through data for fun and/or debugging
Video: https://academy.realm.io/posts/try-swift-nyc-2017-matt-gallagher-driving-view-state-through-data/
Code: github.com/mattgallagher/Clocks
In this talk, Matt showcased an alternative implementation of the Redux/ReSwift Time Travel feature. What impressed me the most was the ability to drive the data/document state and presentation state separately. This could theoretically allow you to easily put the app into a state that’s otherwise very hard to enter.
Matt defined view-state as anything mutable in a view that isn’t written to the main “model.” For instance, each character of text typed into a search field is a piece of view-state, but doesn’t need to be saved to the main app-state each time the user enters a character.
While standard Cocoa apps treat view-state as a side-effect of presentation, Matt showed how inverting the paradigm to treat presentation as a consequence of view-state could allow these time travel features to be easily built.
The primary example Matt showed involves the common task of transitioning to a detail screen in an app. In the standard presentation-driven approach, a view controller would typically call performSegue(withIdentifier:)
to initiate the transition and subclass prepare(for segue:sender:)
to catch and set data on the view controller during the transition. In a data-driven approach, an update to the view-state is made and then the presentation is performed in response to the updated view-state.
Example code is shown below (sorry for the subpar photo quality):
What impressed me the most was certainly the demo that Matt showed. I’ve created a quick video showcasing the standard time travel feature and then turning on the second slider to enable driving the main app-state and view-state independently of each other.
Creating Rich Custom UI Notifications
Slides: slideshare.net/thedevme/creating-rich-custom-ui-notifications
Code: bit.ly/tryswiftcc
In Craig’s talk, he gave a great overview of what it takes to implement the custom notifications UI that was introduced in iOS 10. I’ve personally not implemented this feature yet, so it was awesome to get a “crash course” in their implementation.
Setup is as simple as implementing three methods:
AppDelegate
application(_:didRegisterForRemoteNotificationsWithDeviceToken:)
— check if we’ve got permissionsUNUserNotificationCenterDelegate
userNotificationCenter(_:willPresent:withCompletionHandler:)
— called when the app receives a push while in the foregroundUNUserNotificationCenterDelegate
userNotificationCenter(_:didReceive:withCompletionHandler:)
— called when the app receives a push while in the background
To enable your custom notifications to run, the value for themutable-content
key on the aps
push notification payload must be set to 1
(an Int
).
{
"aps": {
"alert": "New Message",
"mutable-content": 1
}
}
New in iOS 11 is the ability to turn off the notification preview text, which means the user would see the text “Notification” instead of the alert message that you set on the push payload.
In order to customize this text, your app can include a strings.dict
plist that will pluralize the message. This would allow the message to read something like “3 new tweets” instead of just “Notification.” Check out Apple’s Localizing Your App documentation for more information.
Also new in iOS 11 is the thread-id
key on the aps
push notification payload. This allows iOS to automatically merge related messages. For example, subsequent game updates could be combined into one message that contained the latest score.
{
"aps": {
"alert": "New Message",
"mutable-content": 1,
"thread-id": "123"
}
}
Server-side Swift Using Vapor
Video: https://academy.realm.io/posts/try-swift-nyc-tanner-nelson-server-side-swift-using-vapor/
Tanner started his talk with a general overview of the benefits to developing a server using server-side Swift technologies. He outlined the main downsides with the three most common solutions for backend development:
- CloudKit — built-in and easy to use, but not cross platform
- MBaaS (Firebase, Realm, etc.) — hard to be DRY across platforms since backend database update logic must be built-in to each client
- Existing solutions (Express.js, Ruby on Rails, etc.) — are well established and supported, but will likely require you to learn a new language and tooling
Compare this to server-side Swift, where you are working with a familiar language in your normal dev environment. Sharing models and business logic between the frontend and backend also helps you remain more DRY, and the compiler can help you type-check these interactions.
I toyed with Vapor about a year ago, but it was good to get a refresher on the main components of a Vapor server-side Swift application:
- Routing — sending HTTP request (and associated info) to your business logic handler
- Object-relational mapping (ORM) — Fluent, the ORM in Vapor, allows you to easily fetch and persist data in a database as well as create and migrate schema
- Leaf — templating language to render data to HTML (for creating web apps or sending emails)
Another exciting aspect about Vapor’s evolution that Tanner mentioned was the improvements that Swift 4 brings with regard to reducing the amount of “stringly typed” code that you need to write and maintain.
Modern RxSwift Architectures
Video: https://academy.realm.io/posts/try-swift-nyc-2017-krunoslav-zaher-modern-rxswift-architectures/
Code: github.com/kzaher/RxFeedback
While I must admit that I have only surface knowledge of reactive frameworks like RxSwift, I did enjoy Krunoslav’s talk on RxFeedback, even if I was a little lost at times. 😅
From what I understand, RxFeedback is a new architectural approach for reactive apps that use RxSwift. The main idea seems to be tying together an initial state, a reducer, and a “feedback loop” to help you build your app’s functionality in a standard, straightforward way.
One of the main benefits to using this architecture seems to be getting everyone on the same page and making it easy for developers to answer the question, “where do I need to put this code?”
- If it’s state/data → encode it into the main ‘state’ struct
- If it’s a way to modify state → create an Event/Command
- If it’s an effect → encode it into part of the state and then design a feedback loop
As an example, consider the following simple counter component:
The state changes and UI binding can be succinctly described using RxFeedback:
Observable.system(
initialState: 0,
reduce: { (state, event) -> State in
switch event {
case .increment:
return state + 1
case .decrement:
return state - 1
}
},
scheduler: MainScheduler.instance,
feedback:
// UI is user feedback
UI.bind { state in
([
state.map(String.init).bind(to: label.rx.text)
], [
plus.rx.tap.map { Event.increment },
minus.rx.tap.map { Event.decrement }
])
}
)
This looks promising if code like above can scale for a fully-fledged application. I’m definitely adding RxSwift/RxFeedback to my todo list to explore further in the coming months!
Error handling made easy
Helen Papanikolopoulou & Kostas Kremizas
Code: github.com/workable/swift-error-handler
Helen and Kostas showcased some great techniques to make error handling easier to manage with codebase growth. They first outlined the major problems with taking an adhoc, on-the-fly approach to error handling:
- Lots of boilerplate, repeated code (non-DRY)
- No standardized way of handling errors across the codebase — different engineers will solve the problems in different ways
- Complex code paths (e.g. multiple
return
statements) can lead to cognitive overload
I also really loved the list of bad error handling practices that you should try to avoid:
- Skipping cases and/or using generic error messages — don’t be in a hurry/lazy (“I’ll fix it later”) or make the assumption that errors are edge cases.
- Leaving duplicated/similar code everywhere
- Handling errors directly in the networking layer
On the contrary, some good practices for error handling include:
- Creating a set of default actions for common errors
- Having an easy way to customize defaults
Helen and Kostas introduced their ErrorHandler library and showcased how it can help bring sanity to your error handling. The general idea is to encapsulate all of your common error handling code into a default handler. Things like responding to no internet connection, 401 Unauthorized errors, and generic errors will typically be handled in the same way across your app. You can also specify actions that should always run any time an error is encountered, like sending the error to your logging mechanism.
extension ErrorHandler {
class var defaultHandler: ErrorHandler {
return ErrorHandler() .on(NSErrorMatcher(domain: NSURLErrorDomain, code: NSURLErrorNotConnectedToInternet) { (_) in
showErrorAlert("You are not connected to the Internet. Please check your connection and retry.")
return .continueMatching
}
// You can use the Alamofire extensions to easily handle responses with invalid http status
.onAFError(withStatus: 401, do: { (_) in
showLoginScreen()
return .continueMatching
})
// Handle unknown errors.
.onNoMatch(do: { (_) in
showErrorAlert("An error occurred! Please try again. ")
return .continueMatching
})
// Add actions - like logging - that you want to perform each time - whether the error was matched or not
.always(do: { (error) in
Logger.log(error)
return .continueMatching
})
}
}}
Then, in the caller (typically your view controller), you have much less boilerplate code to deal with. You can even override the error handling routines if you need custom behavior.
sendMessage(message) { (response, error) in
if let error = error {
ErrorHandler.defaultHandler
.on(ValidationError.invalidEmail, do: { (_) in
updateEmailTextFieldForValidationError()
return .continueMatching
})
.onAFError(withStatus: 404, do: { (_) in
doSomethingSpecificFor404()
return .stopMatching
})
.onNoMatch(do: { (_) in
// In the context of the current screen we can provide a better message.
showErrorAlert("An error occurred! The message has not been sent.")
// We want to override the default onNoMatch handling so we stop searching for other matches.
return .stopMatching
})
.handle(error)
}
}
Everyone is Your User
Slides: speakerdeck.com/dev_jac/accessibility-everyone-is-your-user
Code: github.com/Julioacarrettoni/tryswiftnycAccessibilityDemo
In the final talk of the conference, Julio did an exceptional job showcasing a poor voice-over experience and the steps needed to make it better. Julio then kicked things up a notch by putting himself in the shoes of an accessibility user and performing his demo while blindfolded!
There were some great accessibility tips given during this presentation:
- Use native elements when possible (don’t try to make a “look-alike” yourself).
- Don’t rely on overlays to block interactivity. This doesn’t play well with the screen reader.
- Don’t use “transparent” buttons on top of UI elements. This also doesn’t play well with the screen reader (although iOS 11 is a little more forgiving and will try to help).
- Pay attention when using UIGestureRecognizers.
- Watch out for the naming of image assets. If no accessibility description is given, the system will read the file name of the asset itself.
- When in doubt, look to Apple’s apps for tips on how to adopt accessibility best-practices.
Other Cool Stuff at try! Swift
Machine Ethics and Emerging Technologies
Video: https://academy.realm.io/posts/try-swift-nyc-2017-paul-fenwick-machine-ethics-emerging-technology/
While this talk wasn’t iOS or Swift related, it was one of my favorite talks of the conference! Paul provided great food for thought that we, as software engineers, need to keep in mind as the world continues to evolve with technological progress. Paul highlighted how ethics will become more important when designing autonomous systems like self-driving cars. At what point would it be okay for the self-driving car to sacrifice its occupant in order to save a pedestrian’s life? Would it ever be okay? Will we have two “types” of self-driving cars in the future — those that act with the “greater good” in mind and those that exclusively prioritize the safety of their occupants at all times?
Buddybuild demo
Video: https://academy.realm.io/posts/try-swift-nyc-2017-dennis-pilarinos-buddybuild/
While I’ve heard of Buddybuild, I’ve never used it before. I generally prefer to have complete control over my signing and build process, but Buddybuild is definitely on to something with how easy they’ve made it setup a new project, onboard testers, and allow them to provide feedback! It only took about 10 minutes to get an app onto the Buddybuild platform and deploy it to a random audience member.
James Dempsey and the Breakpoints
James, who presented on the first day of the conference, helped to close out the show by performing some of his iOS development anthems. Armed with his ukulele and some clever lyrics, James’ tunes were a great way to end the conference.
Thanks, try! Swift!
A quick thanks to NatashaTheRobot for organizing the conference and all of the volunteers for making it happen! Also thanks to all of the try! Swift NYC 2017 sponsors! I had a great time at the conference and was able to soak in a lot of great material. I hope to be able to attend next year and am excited to see this conference continue to grow over the coming years!