Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Lessons Learned From Porting To Swift And Kotli...

Lessons Learned From Porting To Swift And Kotlin - Mobile Era Oslo, October 2017

Video:
https://vimeo.com/237875498

Abstract:
SpotHero has been moving its entire iOS application to Swift and started moving its Android app to Kotlin. Here's some lessons learned in the process in terms of selling management on using a new languages, how to get started, and some tips on things you should do along the way.

(Big thanks to my old crew at SpotHero!)

Ellen Shapiro

October 05, 2017
Tweet

More Decks by Ellen Shapiro

Other Decks in Technology

Transcript

  1. Lessons learned from porting to Swift and Kotlin by Ellen

    Shapiro Mobile Era | Oslo, Norway | October 2017 @designatednerd | justhum.com | designatednerd.com
  2. !

  3. !

  4. !""

  5. !"#

  6. !"#

  7. !

  8. !

  9. iOS

  10. Objective-C NSMutableArray *capitalizedStrings = [NSMutableArray array]; for (NSString *string in

    arrayOfStrings) { NSString *thing = [string capitalized]; [capitalizedStrings addObject: thing]; }
  11. Objective-C, but written in Swift var capitalizedStrings = [String]() for

    string in arrayOfStrings { let thing = string.capitalized capitalizedStrings.append(thing) }
  12. Swiftier let capitalizedStrings = arrayOfStrings.map { string in let thing

    = string.capitalized return thing } Swiftiest let capitalizedStrings = arrayOfStrings.map { $0.capitalized }
  13. NPE

  14. Objective-C JSON Parsing - (instancetype)fromJSONData:(NSData *)data { NSDictionary* jsonObject =

    [NSJSONSerialization jsonObjectWithData:data error:nil]; if (jsonObject == nil]) { return nil; } user.firstName = dictionary[@"first_name"]; user.lastName = dictionary[@"last_name"]; user.age = [dictionary[@"age"] integerValue]; return user; }
  15. Objective-C JSON Parsing - (instancetype)fromJSONData:(NSData *)data { NSDictionary* jsonObject =

    [NSJSONSerialization jsonObjectWithData:data error:nil]; if (jsonObject == nil || ![jsonObject isKindOfClass:[NSDictionary class]]) { return nil; } if ([dictionary[@"first_name"] isKindOfClass: [NSString class]]) { user.firstName = dictionary[@"first_name"]; } else { return nil; } if ([dictionary[@"last_name"] isKindOfClass: [NSString class]]) { user.lastName = dictionary[@"last_name"]; } else { return nil; } if ([dictionary[@"age"] isKindOfClass: [NSNumber class]]) { user.age = [dictionary[@"age"] integerValue]; } else { return nil; } return user; }
  16. Swift 4 JSON Parsing static func from(jsonData: Data) -> User?

    { let decoder = JSONDecoder() return try? decoder.decode(User.self, for: jsonData) }
  17. (This does require some setup) struct User: Codable { let

    firstName: String let lastName: String let age: Int enum CodingKeys: String, CodingKey { case firstName = "first_name", lastName = "last_name", age } }
  18. activity_profile.xml <TextView android:id="@+id/textview_username" android:layout_width="fill_parent" android:layout_height="wrap_content" /> ProfileActivity.java TextView mUsernameTextView; @Override

    public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.profile_activity); mUsernameTextView = (TextView) findViewById(R.id.textview_username); mUsernameTextView.setText("Hello, User"); }
  19. activity_profile.xml <TextView android:id="@+id/textview_username" android:layout_width="fill_parent" android:layout_height="wrap_content" /> ProfileActivity.java @BindView(R.id.textview_username) TextView mUsernameTextView;

    @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.profile_activity); mUsernameTextView.setText("Hello, User"); }
  20. activity_profile.xml <TextView android:id="@+id/textview_username" android:layout_width="fill_parent" android:layout_height="wrap_content" /> ProfileActivity.kt import kotlinx.android.synthetic.main.activity_profile.* public

    override fun onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_profile) textview_username.text = "Hello, User" }
  21. activity_profile.xml <TextView android:id="@+id/usernameTextView" android:layout_width="fill_parent" android:layout_height="wrap_content" /> ProfileActivity.kt import kotlinx.android.synthetic.main.activity_profile.* public

    override fun onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_profile) usernameTextView = "Hello, User" }
  22. Unnecessarily One-Liniest let studentNames = students.reduce("") { $0 + "\n"

    + ($1.firstName ?? "") + " " + ($1.lastName ?? "") }
  23. ! Borderline Incomprehensible ! array.flatMap { $0 } .map {

    $0.doSomething() } .flatMap { $0 } .filter { $0.isSomething || $0.isSomethingElse } .reduce("") { $0 + $1.description }
  24. Obligatory Summary Slide → Honestly assess the pros and cons

    → Start small, then go bonkers once it works → Test the crap out of stuff in the new language → Share your code, your joy, and your pain → Resist desire to rewrite your whole app at once → Ship it!
  25. Links → Concurrency In Swift: One Approach https://gist.github.com/lattner/ 31ed37682ef1576b16bca1432ea9f782 →

    Apple's Swift Blog https://developer.apple.com/swift/blog/ → Jetbrains' Kotlin Blog https://blog.jetbrains.com/kotlin/
  26. Videos → Anything You Can Do, I Can Do Better

    (Kickstarter team on FP in Kotlin vs. Swift) https://www.youtube.com/watch? v=_DuGaAkQSnM → iOS & Android & Swift & Kotlin (Stuart Kent on Kotlin for iOS Devs) http://www.stkent.com/2017/07/27/ios-and- android-and-swift-and-kotlin.html