Share
Embed
From Objective-C to Swift - MOConf 2015
Talk made during the MOConf 2015 in Minsk, Belarus
Junior B.
July 13, 2015
Transcript
33 slides
-
–Terry Pratchett “It is important that we know where we
come from, because if you do not know where you come from, you don't know where you're going.” -
“Good” Old Times - 2008 - (void)dealloc { _delegate =
nil; [self.view.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)]; [_viewControllers release]; [_barButtonItem release]; [_hiddenPopoverController release]; [_dividerView release]; [_cornerViews release]; [super dealloc]; } source: MGSplitViewController -
“Good” Old Times - 2008 @implementation PageLoadOperation // NSOperation -
(void)main { NSString *webpageString = [[[NSString alloc] initWithContentsOfURL:[self targetURL]] autorelease]; NSError *error = nil; NSXMLDocument *document = [[NSXMLDocument alloc] initWithXMLString: …]; if (error) { return; } [[AppDelegate shared] performSelectorOnMainThread:@selector(pageLoaded:) withObject:document waitUntilDone:YES]; [document release]; } @end source: Cocoa Is My Girlfriend (2009) -
Today • We don’t need anymore release, autorelease or retain.
• NSOperation and related friends have been internally implemented using Grand Central Dispatch, the latter seems now generally preferred. • Objective-C has blocks, syntax can be learned on goshdarnblocksyntax.com (there’s a less polite version) • A lot more changed… and we have a new programming language! -
Why not Swift? • Compiler is new and “drama queen”
with generics • The number of libraries available is still low compared to Objective-C, but is growing • Objective-C is not going anywhere soon • Syntax keeps changing (1.2 -> 2.0) -
Why Swift? • Swift is a statically-typed language • Dynamic
Framework Support • It requires less code • Apple says is faster • Playgrounds • Less files, no more .h and .m, just one .swift file -
id has gone! • Finally isKindOfClass will not be required
anymore • We now have 2 new types class and struct, we can pick the one that suits best our design • The code is safer with casting “as” // passed by reference class SomeClass { var foo: String init(foo: String) { self.foo = foo } } // passed by value (copy) struct SomeStruct { var bar: String init(bar: String) { self.bar = bar } } -
When class, when struct? • class preserves identity • struct
preserves data • struct is easier to handle in a multi-thread environment • Apple suggests to use struct whenever is possible and to use class when is necessary (identity preservation or deinitializers) -
Statements sugar in 2.0 • guard has been added to
make conditional checks and to throw exceptions • defer will take care to run “cleaning” operations when leaving the scope, no matter what (f.e.: closing a file) • do, try, catch have been added to make the error handling system more powerful taking advantage of the type ErrorType • Availability check easier with #available(iOS 9, *) -
Defer func deferTest() { var string: NSString? = nil defer
{ if let s = string { print(s) } } string = "test" } deferTest() // This call will print "test" -
Guard enum PasswordError: ErrorType { case Empty case Short }
func encryptPassword(password: String) -> NSData { let count = password.characters.count guard count > 0 else { throw PasswordError.Empty } guard count > 5 else { throw PasswordError.Short } //Encrypt the password return ecryptedPassword } -
It’s required to catch every possible error, not just the
ones supposed to be thrown. In Swift 2.0, the error handling model is exhaustive and resilient. -
Error Handling enum BeerError: ErrorType { case TooMuch case NotAvailable
} do { let beer = try getAnAwesomeBeer(pub) print("I drink it \(beer)") } catch BeerError.TooMuch { print("Hmm... too much, bartender said NO!") } catch BeerError.NotAvailable { print("Let's find another place") } catch { // Catch must be exhaustive print("Ouch!") } -
Generics • Swift has Generics! • “Generic code enables you
to write flexible, reusable functions and types that can work with any type, subject to requirements that you define. You can write code that avoids duplication and expresses its intent in a clear, abstracted manner.” — The Swift Programming Language • A generic function uses a placeholder name, like “T” instead of an actual type, this means that the compiler will check that types are matching, throwing errors if something is wrong. -
Generics - Example func printIntFromArray(a: [Int]) { for i in
a { print(i) } } func printDoubleFromArray(a: [Double]) { for d in a { print(d) } } // both functions can be rewritten with a single one func printItemsInArray<T>(a: [T]) { for item in a { print(item) } } -
Take advantage of syntax • If a function’s final argument
is a closure, we can write it as “trailing closure”. • Closures in Swift are similar to blocks in Objective-C and to lambdas in other programming languages (ed: Java 7, C#, Scala, etc…) func someFunctionWithAClosure(closure: () -> ()) { // function body goes here } someFunctionWithAClosure(){ // closure's body goes here } -
In Swift there’s no KVO • Key Value Observing was
one of the most used features of Objective-C • Swift doesn’t have KVO, but the language is very powerful and offers some good alternatives -
Alternatives to KVO • Create a custom observer class and
use get and set to fire events • Consider binding abstraction and use frameworks like SwiftBond • Consider Functional Reactive Programming and implementations like RAC 3.0 or RxSwift -
SwiftBond var tableViewDataSourceBond: UITableViewDataSourceBond<UITableViewCell>! override func viewDidLoad() { super.viewDidLoad() //
create a data source bond for table view tableViewDataSourceBond = UITableViewDataSourceBond(tableView: self.tableView) // map repositories to cells and bind repositories.map { [unowned self] (repository: Repository) -> RepositoryTableViewCell in let cell = self.tableView.dequeueReusableCellWithIdentifier("cell") as RepositoryTableViewCell repository.name ->> cell.nameLabel repository.photo ->> cell.avatarImageView return cell } ->> tableViewDataSourceBond } source: SwiftBond documentation -
Functional Reactive Programming in Swift is a pleasant experience We
can also go Reactive! -
RxSwift override func viewDidLoad() { super.viewDidLoad() // ... let signingProcess
= combineLatest(username, password) { ($0, $1) } >- sampleLatest(signupSampler) >- map { (username, password) in return API.signup(username, password: password) } >- switchLatest >- startWith(.InitialState) >- variable // ... } source: RxSwift Example -
Still not sure about Swift? • Swift is the future
of Apple products, sooner or later it could be necessary to learn it • Learning Swift now will pay also in along term • Swift is going Open Source, we can influence its path -
Real World Example • Swift requires less code, some classes
have been rewritten with 20% less lines • Using Swift made our project less error-prone, we decreased the number of crashes by a consistent factor -
Resources • The Swift Programming Book • Hacking with Swift,
a complete Swift training course (online)