O slideshow foi denunciado.

Swift - Modern & Expressive, or Magical Unicorn?

0

Compartilhar

Carregando em…3
×
1 de 70
1 de 70

Swift - Modern & Expressive, or Magical Unicorn?

0

Compartilhar

Baixar para ler offline

Presentation on Swift 1.0 to give those coming from other languages a brief overview of the language. Presented first at Reasons to Be Creative, Brighton. 2015

Presentation on Swift 1.0 to give those coming from other languages a brief overview of the language. Presented first at Reasons to Be Creative, Brighton. 2015

Mais Conteúdo rRelacionado

Livros relacionados

Gratuito durante 30 dias do Scribd

Ver tudo

Audiolivros relacionados

Gratuito durante 30 dias do Scribd

Ver tudo

Swift - Modern & Expressive, or Magical Unicorn?

  1. 1. Modern & Expressive or Magical Unicorn? Mike Jones - @FlashGen Swift…
  2. 2. @flashgen | #reasonsto A point of reference, of sorts…
  3. 3. @flashgen | #reasonsto
  4. 4. @flashgen | #reasonsto var myNamevar = “Mike Jones”:String ;
  5. 5. @flashgen | #reasonsto var myName = “Mike Jones”
  6. 6. @flashgen | #reasonsto var myName:String = “Mike Jones”; var myName = “Mike Jones”
  7. 7. @flashgen | #reasonsto var myName = “Mike Jones” let myName = “Mike Jones”
  8. 8. @flashgen | #reasonsto Loops
  9. 9. Loops for var i = 0; i < 10; i++ { println(i) }
  10. 10. Loops for i in 0..<10 { println(i) }
  11. 11. Loops var myArray = [1,2,3,4,5] for item in myArray { println(item) }
  12. 12. Loops var i = 1 while i < 10 { println(i) i++ }
  13. 13. Loops var i = 10 do { println(i) i++ } while i < 10
  14. 14. @flashgen | #reasonsto Conditionals
  15. 15. If…else var num = 10 if num < 20 { println(“less than 20") } else { println("not less than 20") }
  16. 16. Switch…Case var value = 10 switch value { case 10: println("Yay! just right") case 20: println("a bit too high") default: println("Nothing to see here") }
  17. 17. Switch…Case var value = 6 switch value { case 1...9: println("Too low") case 10: println("Yay! just right") case 20: println("a bit too high") default: println("Nothing to see here") }
  18. 18. @flashgen | #reasonsto Optionals…
  19. 19. @flashgen | #reasonsto
  20. 20. Optionals var optionalInteger: Int? var optionalInteger: Optional<Int>
  21. 21. Optionals var impUnwrappedString:String! var impUnwrappedString:ImplicitlyUnwrappedOptional<String>
  22. 22. Optionals var myString = “hello” var myInt = myString.toInt()
  23. 23. Optionals var myString = “hello” var myInt = myString.toInt() // myInt = nil
  24. 24. Optionals var myString = “3” var myInt = myString.toInt()
  25. 25. Optionals var myString = “3” var myInt = myString.toInt() // myInt = 3
  26. 26. Optionals var myString = “3” var myInt:Int = myString.toInt()
  27. 27. Optionals var myString = “3” var myInt:Int = myString.toInt() // Object of type Optional is not unwrapped
  28. 28. Optionals var myString = “3” var myInt:Int = myString.toInt()!
  29. 29. Optionals var myString = “3” var myInt:Int = myString.toInt()! // myInt = 3
  30. 30. Optionals var myString = "hello" var myInt:Int = myString.toInt()!.advancedBy(5)
  31. 31. Optionals var myString = "hello" var myInt:Int = myString.toInt()!.advancedBy(5) // This fails
  32. 32. Optionals var myString = "5" var myOtherInt:Int = 0; if let myInt = myString.toInt()?.advancedBy(5) { myOtherInt = myInt; } else { println("It's nil") }
  33. 33. @flashgen | #reasonsto Functions & Closures
  34. 34. Functions func myFunc(valA:Int, valB:Int) -> Int { return valA + valB } var myInt = myFunc(4, 4);
  35. 35. Functions func myFunc(#valA:Int, #valB:Int) -> Int { return valA + valB } var myInt = myFunc(valA:4, valB:4);
  36. 36. Functions func myFunc(myAge valA:Int, yourAge valB:Int) -> Int { return valA + valB } var ourAgesCombined = myFunc(myAge:4, yourAge:4);
  37. 37. Tuples func sayHello(greeting:String, name:String) -> (String, String) { return (greeting + " " + name, “Pleased to meet you :)”) } var mygreeting = sayHello("Hello", "Reasons"); mygreeting.0; // Hello Reasons mygreeting.1; // Pleased to meet you :)
  38. 38. Tuples func sayHello(greeting:String, name:String) -> (fullGreeting:String, response:String) { return (greeting + " " + name, “Pleased to meet you :)”) } var mygreeting = sayHello("Hello", "Reasons"); mygreeting.fullGreeting; // Hello Reasons mygreeting.response; // Pleased to meet you :)
  39. 39. Tuples func sayHello(greeting:String, name:String) -> (String, String) { return (greeting + " " + name, "Pleased to meet you :)") } let (fullGreeting, response) = sayHello("Hello", "Reasons"); fullGreeting; // Hello Reasons response; // Pleased to meet you :)
  40. 40. Tuples func sayHello(greeting:String, name:String) -> (String, String) { return (greeting + " " + name, "Pleased to meet you :)") } let (fullGreeting, _) = sayHello("Hello", "Reasons"); fullGreeting; // Hello Reasons
  41. 41. Variadic Functions func addNumbers(numbers:Int...) -> Int { var total = 0; for num in numbers { total += num } return total; } addNumbers(1,2,3,4,5) // 15 addNumbers(1,2,3) // 6
  42. 42. Function Types func myFunc(valA:Int, valB:Int) -> Int { return valA + valB } var myIntFunc :(Int, Int) -> Int = myFunc myIntFunc(4,4)
  43. 43. Closures var namesArray = ["Mike", "Jason", "Dennis", "Darren", "John"]; func sortAlphabetically (s1:String, s2:String) -> Bool { return s1 < s2; } let myFriends = sorted(namesArray, sortAlphabetically)
  44. 44. Closures var namesArray = ["Mike", "Darren", "Dennis", "Jason", "Macca"]; let myFriends = sorted(namesArray, { (s1:String, s2:String) -> Bool in return s1 < s2; })
  45. 45. in…out var month = 9 var year = 2015 func swapTwoInts(inout a: Int, inout b: Int) { let tempA = a a = b b = tempA } swapTwoInts(&month, &year) // month = 2015, year = 9
  46. 46. @flashgen | #reasonsto Structs, Classes, Protocols & Extensions
  47. 47. @flashgen | #reasonsto Structs
  48. 48. Structs struct Person { var firstName: String = "Mike"; var lastName: String = "Jones"; } let myPerson = Person()
  49. 49. Classes class Person { var firstName: String; var lastName: String; init(fName:String, lName:String) { firstName = fName; lastName = lName; } } let myPerson = Person(fName:"Mike", lName:"Jones")
  50. 50. Classes class Person { var firstName: String; var lastName: String; init(fName:String="John", lName:String="Smith") { firstName = fName; lastName = lName; } } let myPerson = Person(fName:"Mike", lName:”Jones”) // fName = "Mike", lName = "Jones" let myDefaultPerson = Person() // fName = "John", lName = "Smith"
  51. 51. Classes class Person { var firstName: String; var lastName: String; init(fName:String, lName:String) { firstName = fName; lastName = lName; } convenience init() { self.init(fName: "John", lName: "Smith"); } } let myPerson = Person() // fName = "John", lName = "Smith"
  52. 52. Classes class Person { var firstName: String; var lastName: String; init(fName:String, lName:String) { firstName = fName; lastName = lName; } deinit { // Clean up here } }
  53. 53. Classes class Person { var firstName: String; var lastName: String; var fullName:String { get { return self.firstName + " " + self.lastName } } // … }
  54. 54. Inheritance class Employee: Person { var jobDescription :String = "I'm a developer"; func whatAreYouDoing() -> String { return "I'm working." } }
  55. 55. Inheritance public class Manager: Employee { override var jobDescription :String { get { return super.jobDescription } set(value) { super.jobDescription = value; } } override func whatAreYouDoing() -> String { return "Very little - I'm the boss!" } }
  56. 56. @flashgen | #reasonsto Protocols
  57. 57. Protocols protocol UnicornsProt { var unicornHerd:Int? { get set } func howManyUnicornsDoYouOwn() -> Int? }
  58. 58. Protocols class Person: UnicornsProt { var unicornHerd: Int?; func howManyUnicornsDoYouOwn() -> Int? { return unicornHerd; } }
  59. 59. @flashgen | #reasonsto Extensions
  60. 60. Extensions extension Person { public var unicorns:String { return "UNICORNS!" } public func moreUnicorns() -> String { return “MORE " + unicorns; } }
  61. 61. @flashgen | #reasonsto Generics…
  62. 62. Generics var myArray :Array<String> var myDict :Dictionary<String, Person> var myOptionalInt :Optional<Int>
  63. 63. Generics func swapTwoInts(inout a: Int, inout b: Int) { let tempA = a a = b b = tempA } func swapTwoStrings(inout a: String, inout b: String) { let tempA = a a = b b = tempA } func swapTwoDoubles(inout a: Double, inout b: Double) { let tempA = a a = b b = tempA }
  64. 64. Generics var month = 9 var year = 2015 var greeting = "Hello Reasons" var response = "Pleased to meet you :)" func swapTwoValues<T>(inout a: T, inout b: T) { let tempA = a a = b b = tempA } swapTwoValues(&month, &year) // month = 2015, year = 9 swapTwoValues(&greeting, &response) // greeting = "Pleased to meet you :) // response = "Hello Reasons
  65. 65. @flashgen | #reasonsto one more thing…
  66. 66. @flashgen | #reasonsto Swift 2.0
  67. 67. @flashgen | #reasonsto Open Source
  68. 68. @flashgen | #reasonsto Apple Developer Program http://developer.apple.com
  69. 69. @flashgen | #reasonsto Thank You
  70. 70. Mike Jones pixadecimal.com blog.flashgen.com @FlashGen

Notas do Editor

  • Let’s start off with a point of reference that we can use as a starting point
  • This is a Unicorn - in case there was some confusion. The rest of this presentation is about Swift!
  • This should look familiar to those ActionScript developers in the audience.
    Seriously though let’s just take a look at the anatomy of this line of code:
    It declares the property using the VAR keyword, and provides clear indication though TYPE ANNOTATION that it is expecting a STRING as a value.

    This is what we would all refer to as an example of a STRONGLY TYPED language
  • This on the other hand will be familiar to all the JavaScript developers in the house. Note the lack of a TYPE ANNOTATION and a terminating semi-colon.

    The type of data this variable can store is INFERRED by the value that is assigned to it. This is what you would usually refer to as a DYNAMIC LANGUAGE as the variable will happily store whatever you provide it with, a STRING one moment, a NUMERIC VALUE the next.
  • Now this may come as no surprise, but both of the preceding examples were in fact SWIFT. Swift uses TYPE INFERENCE to determine what a variables type is based on the initial value assigned to it.

    However, unlike JavaScript it is a STRONGLY TYPED language and through a process referred to as TYPE SAFETY it makes sure during development and compilation that you don’t try and assign a different data type to a previously declared variable. If you do you’ll get an exception!

    You can annotate your variables with a specific type at declaration (and include semi-colons if you wish), but they are not required.
  • One other thing before we move on is the difference between LET and VAR. LET is the CONSTANT keyword, so any value assigned to this type of variable is fixed and cannot be changed at a later time.
  • As with most languages SWIFT controls execution flow through the use of LOOPS & CONDITIONALS.

    However while they operate in a similar fashion to other LANGUAGES you may be familiar with, except that curly braces are mandatory while parentheses aren’t. Also be aware that unlike a lot of WEB LANGUAGES, you can create infinite loops.

    Loops available are FOR, FOR…IN, WHILE & DO…WHILE
  • Here we have the FOR loops. I’m not going to deep dive in to these. They are solely here to provide a point of reference where SWIFT offers differing implementations. For example CURLY BRACES are MANDATORY. PARENTHESES are not.
  • This is the equivalent of the previous FOR loop. In this case it is using the HALF RANGE (..<) to loop through the values 0-9. If you wanted the loop to include the value 10, use a full RANGE (…)
  • The more modern FOR…IN loop. This is the best practice approach advocated by Apple for iterating over ARRAYS etc.
  • The WHILE loop. Make sure to include the incrementation variable otherwise you can easily create an infinite loop!
  • Classic DO…WHILE. Again just to re-enforce, CURLY BRACES are required, PARENTHESES are not
  • Like LOOPS, CONDITIONALS require CURLY BRACES even if you are doing a single line evaluation.

    Conditionals include: IF…ELSE & SWITCH…CASE
  • Another thing to note is that SWITCH CASE statements do not support FALL THROUGH and you have to supply a ‘CATCH ALL’ should none of the CASE STATEMENTS fulfil the condition. BREAK statements are optional and are inferred - hence the lack of FALL THROUGH
  • If you do want to ‘emulate’ a FALL THROUGH and you value is an INT, then you can use a RANGE to achieve this as shown above.
  • Optionals, or SOME & NONE…
  • This is how most people feel on first encountering OPTIONALS…
  • Here we have the declaration of an OPTIONAL INT. Note the shorthand (and preferred) way of declaring the optional - Int?. Don’t confuse Int? with Int. Optionals are a separate type of their own that contain the property type you assign.

    The second line illustrates the ‘long form’ approach to declaring Optionals - and thus re-enforces that they are their own type.
  • As the second line type annotation implies, this is an implicitly unwrapped optional. That is on assignment it unwraps the optional and assigns the property value to the variable. Be aware this will error if the type cannot be converted - as shown in the next few slides.
  • As toInt() is an optional, myInt will have a type of Int? and the value of nil as myString cannot be converted to a number
  • This time myInt has the value of 3. Remember though this is still an Int? not an Int
  • This assigns the value of 3 to the variable myInt, but it sets it’s inferred type to Int? not Int as you may assume
  • Here we get an error as the OPTIONAL object hasn’t been force unwrapped and is still an Int? and not an Int
  • Here we get an error as the OPTIONAL object hasn’t been force unwrapped
  • To achieve this we just added an exclamation mark to the end of toInt()
  • Now the value of myInt is not only 3, but is also an Int not an Int?
  • Be careful doing this in this manner as you will get an error if you try and force unwrap an OPTIONAL and chain it at the same time - as nil doesn’t have an advancedBy() method - so throws an error.
  • Here we get an error as the OPTIONAL object has been force unwrapped and it is a nil value
  • A cleaner approach is to using CONDITIONAL UNWRAPPING of an optional (this slide also demonstrates the concept of chaining).

    Here the variable myInt is part of a conditional expression so if the resulting value is nil, the condition is then false and the ELSE is run. If the value isn’t nil, then it is TRUE and the first statement is run - setting the value of myOtherInt in this case.

    Note myInt is garbage collected after this condition finishes its execution
  • By default parameter names do not get displayed when invoking a function. While this can be fine in most instances you may want to display the parameters so you can give another developer an indication of what each value represents.
  • If you want to make it more explicit what the parameters are that are being called you can prefix them with a hash #. Then when invoking the function you have to include the parameter names
  • When using CONVENIENCE NAMES for PARAMETERS you still have to use the actual parameter name within your function. Using the convenience name will throw an error.
  • Tuples are simple objects that allow you to plass back multiple values from a Function / Method. By default they are 0 based
  • Tuples, like Function parameters, can have name parameters. In which case they can be accessed by the parameter names instead.
  • Instead of naming the TUPLE parameters you can just declare the names as variables - in this case constants - and do the assignment and initialisation all at once.
  • If there are any parameters you don’t require place an underscore _ in the position of the item you don’t require and it will not be created or assigned in this manner.
  • VARIADIC FUNCTIONS allow you to provide a simple parameter signature that allows an arbitrary amount of items of a certain type.

    Note the return of the RANGE
  • Here we can pass a function around and assign it to another variable by declaring the receiving variable as having the same FUNCTION TYPE as the function that is passed to it.

    So in this example we declare our variable as taking 2 INT PARAMETERS and returning 1 INT PARAMETER.
  • This slide is a lay-up showing a function being used as a parameter of the SORTED function - this will be replaced by a CLOSURE in the next slide…
  • CLOSURES or function literals are common in a lot of languages, but SWIFT has a specific way to declare a CLOSURE as you can see here.

    CURLY BRACES, then the parameters and the return type (if required). The all important IN keyword and then the actual closure code.

    In this example it just sorts the array alphabetically.
  • In-out parameters cannot have default values, and variadic parameters cannot be marked as inout. If you mark a parameter as inout, it cannot also be marked as var or let.

    An in-out parameter has a value that is passed in to the function, is modified by the function, and is passed back out of the function to replace the original value.
  • Structs are created using the STRUCT keyword and can contain both properties and methods.

    Structs are useful when you need to create a complex data transfer object on an ad-hoc basis within your application. Do not confuse these with an OBJECT LITERAL. STRUCTS can be instantiated like CLASSES.
  • While SWIFT does create an INITIALISER in the background, by default it only calls the SUPER CLASS if there is some form of INHERITANCE.

    To fix our class all we need to do is create an EXPLICIT INITIALIZER that assigns values to our properties on INSTANTIATION.

    Now we have another problem. In it’s current form a PERSON CLASS always has to have a value for FIRSTNAME & LASTNAME supplied on creation. We can resolve this in a few different ways.
  • Firstly we could supply defaults for those values. Or…
  • We can create a CONVENIENCE INITIALISER. These are as the name implies a way to set additional INITIALISERS that allow for increased configuration on INSTANTIATION.
  • With a CLASS you also have access to a deinitializer - DEINIT. This is when you destroy the object, either manually by setting it to NIL or as part of ARC.
  • Getters & Setters are computed values not stored values
  • Inheritance works the same as other languages except when dealing with variables
  • As JobDescription is a stored value we cannot override it in the Manager subclass. To achieve this though we can create a computed variable of the same name and set the value that way.

    Note we have to call back up to the SUPER version of the variable to actually store it.
  • PROTOCOLS are what a lot of languages refer to an INTERFACES. These are contract files that tell a class what METHODS and / or PROPERTIES they need to implement to fulfil that contract
  • EXTENSIONS allow you to ADD FUNCTIONALITY to a object that you may not have access to the source code. Think of this like adding properties and methods to a JavaScript object via the PROTOTYPE chain.
  • Not that they are actual implementations and have ACCESS MODIFIERS where required
  • GENERICS are the ability to create GENERIC FUNCTIONS & METHODS that allow for greater flexibility within your code without the necessity of REPETITION.
  • These are a few of the GENERIC TYPES in SWIFT - some we have already seen
  • Take this contrived example - these 3 functions are pretty much identical. However it would be more efficient if we could do the same thing with just one function. That’s where GENERICS come in.
  • Not the use of the token identifier <T>. The only requirement is that the type annotation <T> be the same as the parameters that are passed in
  • Try Catch
    Availability checking
    Error Types / Throws
  • This is a big deal as it allows the potential for iOS developers (initially) to build end to end applications solely in SWIFT - similar to the JS -> Node.js approach.
  • More info can be found here…
  • ×