Apple Swift programming language tutorial
Directory
- 1 Overview
- 2 Swift getting started
- 3 simple value
- 4 control flow
- 5. Functions and closures
- 6 objects and Classes
- 7 enumeration and Structure
1 Overview
Apple just released The Swift Programming Language early this morning. This article extracts and extracts it from its book The Swift Programming Language. I hope it will be helpful for iOS & OSX development.
Swift is a new programming language for iOS and OS X application programming. Based on C and Objective-C, Swift has no compatibility constraints for C. Swift adopts a secure programming mode and adds modern functions to make programming simpler, more flexible, and more interesting. The interface is based on the Cocoa and Cocoa Touch frameworks widely loved by the masses, demonstrating the new direction of software development.
Swift has existed for many years. Apple uses existing compilers, debuggers, and frameworks as its infrastructure. Using ARC (Automatic Reference Counting, Automatic Reference Counting) to simplify memory management. Our framework stack is always based on Cocoa. Objective-C evolved to support blocks, collection literal, and modules, allowing modern language frameworks to be used without going deep. (By gashero) thanks to these basic work, we can introduce new programming languages in Apple software development.
Objective-C developers may feel familiar with Swift. Swift uses Objective-C named parameters and dynamic object models. Provides interoperability between the Cocoa framework and mix-and-match. Based on these foundations, Swift introduces many new features and combines process-oriented and object-oriented features.
Swift is also friendly to new programmers. He is an industrial-level system programming language, but as friendly as a scripting language. He supports playground, allowing programmers to experiment with a piece of Swift code and immediately see the results without having to bother building and running an application.
Swift integrates modern programming language ideas and the wisdom of Apple's engineering culture. The compiler is optimized based on performance, while the language is optimized for development without compromise between each other. (By gashero) You can start learning from "Hello, world" and transition to the entire system. All these make Swift a source of innovation for Apple software developers.
Swift is a fantastic way to write iOS and OSX applications, and will continue to introduce new features. We can't wait to see what you want to do with him.
2 Swift getting started
Learning a new language starts with printing "Hello, world. In Swift, there is a line:
println("Hello, world")
If you have written C or Objective-C code, this syntax looks familiar. In Swift, This is the complete program. You do not need to import a separate library for input/output and string processing. Global code is used for program entry, so you do not need to writeMain ()Function. You do not need to write a semicolon after each statement.
This will give you enough information to complete a programming task. You don't have to worry about something you don't understand. Anything you haven't explained clearly will be explained in detail later in this book.
Note
As a best practice, you can open this chapter in playground of Xcode. Playground allows you to edit the code and view the result immediately.
3 simple value
UseLetTo define constants,VarDefine variables. The constant value does not need to be specified during compilation, but must be assigned at least once. This means that you can use constants to name a value. You find that only one confirmation is required, but it is used in multiple places.
var myVariable = 42myVariable = 50let myConstant = 42
Note
The constant definition here is similar to the variable in functional programming languages. It cannot be modified after a value assignment. It is beneficial to use more.
A constant or variable must belong to the same type as the value assignment. Therefore, you do not need to strictly define the type. A constant or variable can be created by providing a value, and the compiler can infer its type. In the above example, the compilation will infer that myVariable is an integer type, because its initial value is an integer.
Note
The type is bound to the variable name and belongs to the static type language. It facilitates static optimization. It is different from Python and JavaScript.
If the initialization value does not provide enough information (or there is no initialization value), you can write the type after the variable name, separated by a colon.
let imlicitInteger = 70let imlicitDouble = 70.0let explicitDouble: Double = 70
Note
Exercise
Create a constant of the Float type and the value is 4.
Values are never implicitly converted to other types. If you want to convert a value to a different type, you must construct an instance of the desired type.
let label = "The width is "let width = 94let widthLabel = label + String(width)
Note
Exercise
What error will you get when you try to delete the String Conversion of the last row?
There is also a simpler way to include a value in a string: Write the value in parentheses and place it in front of parentheses with a backslash. For example:
let apples = 3let oranges = 5 //by gasherolet appleSummary = "I have \(apples) apples."let fruitSummary = "I have \(apples + oranges) pieces of fruit."
Note
Exercise
Use()To include a floating point number to calculate the string, and contain someone's name to greet.
Create an array and dictionary using square brackets "[]", and access its elements through the index or key in square brackets.
var shoppingList = ["catfish", "water", "tulips", "blue paint"]shoppingList[1] = "bottle of water"var occupations = [ "Malcolm": "Captain", "Kaylee": "Mechanic",]occupations["Jayne"] = "Public Relations"
To create an empty array or dictionary, use the initialization syntax:
let emptyArray = String[]()let emptyDictionary = Dictionary<String, Float>()
If the type information cannot be inferred, you can write an empty array as "[]" and an empty dictionary as "[:]". For example, you can set a variable to be known and input parameters to the function:
ShoppingList = [] // go shopping and buy something by gashero
4 control flow
UseIfAndSwitchAs a condition control. UseFor-in,For,While,Do-whileAs a loop. Parentheses are not mandatory, but the braces of the subject are required.
let individualScores = [75, 43, 103, 87, 12]var teamScore = 0for score in individualScores { if score > 50 { teamScores += 3 } else { teamScores += 1 }}teamScore
InIfStatement, the condition must be a Boolean expression, which meansIf score {...}It is incorrect and cannot be implicitly compared with 0.
You can use it togetherIfAndLetTo prevent value loss. These values are optional. An optional value can contain a value orNilThe specified value does not exist. Write a question mark "? "After the type, the value is optional.
var optionalString: String? = "Hello"optionalString == nilvar optionalName: String? = "John Appleseed"var greeting = "Hello!"if let name = optionalName { greeting = "Hello, \(name)"}
Note
Exercise
Change optionalName to nil. What will happen when greeting? Add an else clause to set a different value when optionalName is nil.
If the value is nil, the code in the braces false will be skipped. Otherwise, the optional value is not packaged and assigned as a constant, and the unwrapped value variable will be included in the code block.
SwitchMultiple types of data and comparison are supported. The value must be an integer equal to the value of the test.
let vegetable = "red pepper"switch vegetable {case "celery": let vegetableComment = "Add some raisins and make ants on a log."case "cucumber", "watercress": let vegetableComment = "That would make a good tea sandwich."case let x where x.hasSuffix("pepper"): let vegetableComment = "Is it a spicy \(x)?"default: //by gashero let vegetableComment = "Everything tastes good in soup."}
Note
Exercise
Try to Remove default and see what errors are returned.
After matching is executed, the program starts fromSwitchJump out, instead of continuing to execute the next situation. Therefore, you no longer need to jump out of the breakSwitch.
AvailableFor-inTo iterate each element in the dictionary and provide a pair of names to use each key-value pair.
let interestingNumbers = [ "Prime": [2, 3, 5, 7, 11, 13], "Fibonacci": [1, 1, 2, 3, 5, 8], "Square": [1, 4, 9, 16, 25],]var largest = 0for (kind, numbers) in interestingNumbers { for number in numbers { if number > largest { largest = number } }}
Note
Exercise
Add another variable to track which type of number is the largest, that is, the largest number.
UseWhileTo repeatedly execute the code block until the condition changes. Loop conditions can be placed at the end to ensure that the loop is executed at least once.
var n = 2while n < 100 { n = n * 2}nvar m = 2do { m = m * 2} while m < 100m
You can maintain an index in the loop, and use "..." to indicate the index range or explicitly declare an initial value, condition, or increment. These two loops do the same thing:
var firstForLoop = 0for i in 0..3 { firstForLoop += i}firstForLoopvar secondForLoop = 0for var i = 0; i < 3; ++i { secondForLoop += 1}secondForLoop
Use..The maximum value is ignored in the Construction range....The constructed range contains two values.
5. Functions and closures
UseFuncDeclare a function. Call the function to add the parameter list in parentheses with its name. Use->Separate the parameter names and return value types.
func greet(name: String, day: String) -> String { return "Hello \(name), today is \(day)."}greet("Bob", "Tuesday")
Note
Exercise
Remove the day parameter and add a parameter that contains today's lunch selections.
Use tuple to return multiple values.
func getGasPrices() -> (Double, Double, Double) { return (3.59, 3.69, 3.79)}getGasPrices()
The function can accept the number of variable parameters and collect them into an array.
func sumOf(numbers: Int...) -> Int { var sum = 0 for number in numbers { sum += number } return sum}sumOf()sumOf(42, 597, 12)
Note
Exercise
Compile a function to calculate the average value of its parameters.
Functions can be nested. Embedded functions can access the variables of the functions in which they are defined. You can use nested functions to organize code to avoid overlength and complexity.
func returnFifteen() -> Int { var y = 10 func add() { y += 5 } add() return y} //by gasheroreturnFifteen()
Function is the first type. This means that the function can return another function.
func makeIncrementer() -> (Int -> Int) { func addOne(number: Int) -> Int { return 1 + number } return addOne}var increment = makeIncrementer()increment(7)
A function can take other functions as parameters.
func hasAnyMatches(list: Int[], condition: Int -> Bool) -> Bool { for item in list { if condition(item) { return true } } return false}func lessThanTen(number: Int) -> Bool { return number < 10}var numbers = [20, 19, 7, 12]hasAnyMatches(numbers, lessThanTen)
The function is actually a special case of closure. You can write a closure without a name. You just need to put it in braces. UseInTo the return values of specific parameters and subjects.
numbers.map({ (number: Int) -> Int in let result = 3 * number return result })
Note
Exercise
Override a closure to return 0 for all odd numbers.
There are multiple options for writing closures. When the type of a closure is known, such as Callback, you can ignore its parameters and return values, or both. Closure of a single statement can return values directly.
numbers.map({number in 3 * number})
You can reference a parameter by number rather than name, which is useful for very short closures. A closure transmits its last parameter to the function as the return value.
sort([1, 5, 3, 12, 2]) { $0 > $1 }
6 objects and Classes
UseClassYou can create a class. An Attribute declaration is declared as a constant or variable in the class, except in the context of the class. The same is true for methods and functions.
class Shape { var numberOfSides = 0 func simpleDescription() -> String { return "A shape with \(numberOfSides) sides." }}
Note
Exercise
Use "let" to add a constant attribute and add another method to accept parameters.
Create a class instance by adding parentheses after the class name. Use the dot syntax to access instance attributes and methods.
var shape = Shape()shape.numberOfSides = 7var shapeDescription = shape.simpleDescription()
Some important things of the Shape class in this version are not: A constructor sets the class when creating an instance. UseInitCreate one.
class NamedShape { var numberOfSides: Int = 0 var name: String init(name: String) { self.name = name } //by gashero func simpleDescription() -> String { return "A Shape with \(numberOfSides) sides." }}
Note:SelfUsed to distinguish the name attribute from the name parameter. The life of the constructor is the same as that of a function, except that the class instance is created. Each attribute must be assigned a value, either in the Declaration or in the constructor.
UseDeinitCreate a destructor to clean up objects during destruction.
Child classes include the names of their superclasses, separated by colons. You do not need to declare the standard root class, so you can ignore the superclass.
Subclass methods can be markedOverrideOverload the implementation of the superclassOverrideWill be considered as an error by the compiler. The compiler also checks methods that are not overloaded.
class Square: NamedShape { var sideLength: Double init(sideLength: Double, name: String) { self.sideLength = sideLength super.init(name: name) numberOfSides = 4 } func area() -> Double { return sideLength * sideLength } override func simpleDescription() -> String { return "A square with sides of length \(sideLength)." }}let test = Square(sideLength: 5.2, name: "my test square")test.area()test.simpleDescription()
Note
Exercise
The subclass of writing another NamedShape is called Circle, which accepts the radius and name to its constructor. Implement the area and describe methods.
Attributes can include getter and setter.
class EquilateralTriangle: NamedShape { var sideLength: Double = 0.0 init(sideLength: Double, name: String) { self.sideLength = sideLength super.init(name: name) numberOfSides = 3 } var perimeter: Double { get { return 3.0 * sideLength } set { sideLength = newValue / 3.0 } } override func simpleDescription() -> String { return "An equilateral triangle with sides of length \(sideLength)." }}var triangle = EquilateralTriangle(sideLength: 3.1, name: "a triangle")triangle.perimetertriangle.perimeter = 9.9triangle.sideLength
In the setter of perimeter, the new value is named newValue. You can provide a non-conflicting name after set.
Note that the constructor of EquilateralTriangle has three different steps:
- Set attribute values
- Call the hyperclass Constructor
- Change the attribute value of the superclass, and add additional work to use methods, getter, and setter.
If you do not need to calculate the attribute, but you still need to perform the work after setting the value, useWillSetAndDidSet. For example, the following class must ensure that the side length of the triangle is equal to the length of the rectangle.
class TriangleAndSquare { var triangle: EquilaterTriangle { willSet { square.sideLength = newValue.sideLength } } var square: Square { willSet { triangle.sideLength = newValue.sideLength } } init(size: Double, name: String) { square = Square(sideLength: size, name: name) triangle = EquilaterTriangle(sideLength: size, name: name) }}var triangleAndSquare = TriangleAndSquare(size: 10, name: "another test shape")triangleAndSquare.square.sideLengthtriangleAndSquare.triangle.sideLengthtriangleAndSquare.square = Square(sideLength: 50, name: "larger square")triangleAndSquare.triangle.sideLength
There is an important difference between class methods and functions. The Parameter Name of the function is only used with the function, but the parameter name of the method can also be used to call the method (except the first parameter ). There is a parameter with the same name in a method, and the parameter itself is called. You can specify the second name and use it inside the method.
class Counter { var count: Int = 0 func incrementBy(amount: Int, numberOfTimes times: Int) { count += amount * times }}var counter = Counter()counter.incrementBy(2, numberOfTimes: 7)
When working with optional values, you can write "? "Similar to the method property before the operator. If the value is "? "Previously nil, all in "? "Will be automatically ignored later, and the entire expression is nil. In addition, the optional values are unpackaged, all "? "All subsequent values are unpackaged values. In either case, the value of the entire expression is optional.
let optionalSquare: Square? = Square(sideLength: 2.5, name: "optional square")let sideLength = optionalSquare?.sideLength
7 enumeration and Structure
UseEnumTo create an enumeration. For classes and other Naming types, you can use enumeration methods.
enum Rank: Int { case Ace = 1 case Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten case Jack, Queen, King func simpleDescrition() -> String { switch self { case .Ace: return "ace" case .Jack: return "jack" case .Queen: return "queen" case .King: return "king" default: return String(self.toRaw()) } }}let ace = Rank.Ace //by gasherolet aceRawValue = ace.toRaw()
Note
Exercise
Compile a function to compare the values of two Rank values by comparing their original values.
In the above example, the type of the original value is Int, so you can only specify the first original value. The original values are assigned values in sequence. You can also use a string or floating point number as the original enumerated value.
UseToRawAndFromRawThe function can convert the original and enumerated values.
if let convertedRank = Rank.fromRaw(3) { let threeDescription = convertedRank.simpleDescription()}
The enumerated member value is the actual value, rather than the original value written in other ways. In fact, in some cases, the original value is not provided.
enum Suit { case Spades, Hearts, Diamonds, Clubs func simpleDescription() -> String { switch self { case .Spades: return "spades" case .Hearts: return "hearts" case .Diamonds: return "dismonds" case .Clubs: return "clubs" } }}let hearts = Suit.Hearts //by gasherolet heartsDescription = hearts.simpleDescription()
Note
Exercise
Add a color method to Suit and return "black" When spades and clubs, and return "red" to hearts and diamounds ".
Note the two methods for referencing the Hearts member above: When the value is assigned to the hearts constant, the enumerated member Suit. Hearts is referenced by the full name, because the constant does not have a clear type. In the switch, enumeration is referenced through. Hearts, because the value of self is known. You can use the convenient method at any time.
UseStructCreate struct. Struct supports multiple actions that are the same as the class, including methods and constructors. A major difference is that the transfer between codes always uses a copy (value transfer), while the class is a transfer reference.
struct Card { var rank: Rank var suit: Suit func simpleDescription() -> String { return "The \(rank.simpleDescription()) of \ (suit.simpleDescription())" }}let threeOfSpades = Card(rank: .Three, suit: .Spades)let threeOfSpadesDescription = threeOfSpades.simpleDescription()
Note
Exercise
Add a method to the Card class to create a table of cards. Each Card has a combined rank and suit. (By gashero ).
An enumerated instance Member can own the Instance value. Instances of the same enumeration member can have different values. You assign a value when creating an instance. The difference between the specified value and the original value: the original value of the enumeration is the same as that of the instance. You provide the original value when defining the enumeration.
For example, assume that you need to obtain the sunrise and landing time from the server. The server can respond to the same information or some error messages.
enum ServerResponse { case Result(String, String) case Error(String)}let success = ServerResponse.Result("6:00 am", "8:09 pm")let failure = ServerResponse.Error("Out of cheese.")switch success {case let .Result(sunrise, sunset): let serverResponse = "Sunrise is at \(sunrise) and sunset is at \(sunset)."case let .Error(error): let serverResponse = "Failure... \(error)"}