swift编程_swift编程语言 - CSDN
精华内容
参与话题
  • "Swift"编程语言

    千次阅读 2014-06-07 17:58:53
    来自英文文档及没过4级的渣渣英语功底,为了自己以后

    来自英文文档、百度翻译以及自己没过4级的渣渣英语功底,为了自己以后看起来方便


    About Swift

    关于"海燕"


    IMPORTANT

    重要


    This is a preliminary document for an API or technology in development. Apple is supplying this information to help you plan for the adoption of the technologies and programming interfaces described herein for use on Apple-branded products. This information is subject to change, and software implemented according to this document should be tested with final operating system software and final documentation. Newer versions of this document may be provided with future seeds of the API or technology.

    这是一个用于开发的API和技术的初期文档。苹果公司正在提供这些信息来帮助你把这项技术和编程接口应用到你的苹果品牌产品中。这些信息是随时变化的,依据这个文档实现的软件需要在最终的操作系统软件和最终文档上测试。新版本的文档将会提供API和这项技术的未来种子(= =没翻译明白)。


    Swift is a new programming language for iOS and OS X apps that builds on the best of C and Objective-C, without the constraints of C compatibility. Swift adopts safe programming patterns and adds modern features to make programming easier, more flexible, and more fun. Swift’s clean slate, backed by the mature and much-loved Cocoa and Cocoa Touch frameworks, is an opportunity to reimagine how software development works.

    "海燕"是一个建立在C和Objective-C基础上,没有C语言兼容性约束的用于开发IOS和OS X操作系统应用的新语言。"海燕"采用安全编程方式,添加了现代特征来使编程变得更简单,更灵活,更有趣。"海燕"清白的历史,在成熟的受欢迎的Cocoa和Cocoa Touch框架的支持下,这在软件开发工作中是一个多么充满机遇的构想。


    Swift has been years in the making. Apple laid the foundation for Swift by advancing our existing compiler, debugger, and framework infrastructure. We simplified memory management with Automatic Reference Counting (ARC). Our framework stack, built on the solid base of Foundation and Cocoa, has been modernized and standardized throughout. Objective-C itself has evolved to support blocks, collection literals, and modules, enabling framework adoption of modern language technologies without disruption. Thanks to this groundwork, we can now introduce a new language for the future of Apple software development.

    "海燕"已经酝酿多年。苹果公司提出这个"海燕"语言基础来推进已经存在的编译器,调试器和基础架构。我们使用ARC来使内存管理变得简单。我们建立在Foundation和Cocoa基础上的框架层,已经现代化和规范化。Objective-C本身已经发展到支持代码块,容器,单元模块,这使不间断的采用现代语言成为可能。(是这个意思吧?= =)多亏于这个基础,我们现在可以为苹果软件开发的将来引入这样一个新语言。


    Swift feels familiar to Objective-C developers. It adopts the readability of Objective-C’s named parameters and the power of Objective-C’s dynamic object model. It provides seamless access to existing Cocoa frameworks and mix-and-match interoperability with Objective-C code. Building from this common ground, Swift introduces many new features and unifies the procedural and object-oriented portions of the language.

    Objective-C的开发者会对于"雨燕"感到熟悉。"雨燕"基于易读的Objective-C的命名参数和Objective-C动态对象模式的动力。它可以无缝的连接到已经存在的Cocoa框架并支持和Objective-C的混编。基于这些共同点,"雨燕"引入了许多特性、结合程序和语言的面向对象部分。(这里断句断不明白了= =)


    Swift is friendly to new programmers. It is the first industrial-quality systems programming language that is as expressive and enjoyable as a scripting language. It supports playgrounds, an innovative feature that allows programmers to experiment with Swift code and see the results immediately, without the overhead of building and running an app.

    "雨燕"(以下直接称为"swift")对新的编程人员是友善的。这是第一个工业质量(不懂= =)级别的系统编程语言,它像一个脚本语言一样富有表现力和有趣味。它支持的playgrounds,是一个革新性的特性,它允许程序员在编写swift代码的同时立刻看到那些结果,没有建立和运行一个应用程序的开销。


    Swift combines the best in modern language thinking with wisdom from the wider Apple engineering culture. The compiler is optimized for performance, and the language is optimized for development, without compromising on either. It’s designed to scale from “hello, world” to an entire operating system. All this makes Swift a sound future investment for developers and for Apple.

    swift运用最好的现代语言思想来思考苹果编程文化中的智慧。编译器的性能更优,语言的开发更优,这两者的提升不放弃其中一项。它的设计从"hello,world"一直衡量到整个操作系统。所有这些使得swift成为一个对于开发者和对于苹果来说都是一个健康的未来。(应该就是你选择它不会错的意思= =)


    Swift is a fantastic way to write iOS and OS X apps, and will continue to evolve with new features and capabilities. Our goals for Swift are ambitious. We can’t wait to see what you create with it.

    swift是一个作为开发IOS和 OS X应用程序很好的方式,并且它会继续开发新的特性和能力。我们的目标是雄心壮志的swift,我们迫不及待的想看到你创建出一个什么样的它。


    A Swift Tour

    一次雨燕之旅


    Tradition suggests that the first program in a new language should print the words “Hello, world” on the screen. In Swift, this can be done in a single line:
    传统惯例,一个新语言的第一个程序应该在屏幕上打印"Hello, wordld"。在swift中,这个工作可以用一行来完成:
    println(Hello, world)

    If you have written code in C or Objective-C, this syntax looks familiar to you—in Swift, this line of code is a complete program. You don’t need to import a separate library for functionality like input/output or string handling. Code written at global scope is used as the entry point for the program, so you don’t need a mainfunction. You also don’t need to write semicolons at the end of every statement.
    如果你曾经是写C或者Objective-C代码的,这语法你看起来一定会非常熟悉。在swift中,这一行代码就是一个完整的程序。你不需要导入单独功能(像IO或者字符串处理)的库。写在全局范围内的代码即是程序的入口,所以你并不需要main函数。你同样不需要在每个语句后面写分号。

    This tour gives you enough information to start writing code in Swift by showing you how to accomplish a variety of programming tasks. Don’t worry if you don’t understand something—everything introduced in this tour is explained in detail in the rest of this book.
    本节会给你足够的信息来让你开始编写swifit代码,并教你如何完成各种编程任务。如果你看不懂其中的一些,(没关系,)在本节中引出的所有东西,都会在这本书的其余部分详细解释。

    NOTE
    提示

    For the best experience, open this chapter as a playground in Xcode. Playgrounds allow you to edit the code listings and see the result immediately.
    为了获得更好的一眼,在Xcode中打开本章提到的playground。它将允许你编辑代码列表并立即看到结果。

    Simple Values

    简单的值

    Use let to make a constant and var to make a variable. The value of a constant doesn’t need to be known at compile time, but you must assign it a value exactly once. This means you can use constants to name a value that you determine once but use in many places.
    使用let来声明一个常量,使用var来声明一个变量。一个常量的值不需要在编译的时候被知道,但它必须被赋值过一次。这意味着你可以只将常量赋值一次但可以在多处使用。

    var myVariable = 42
    myVariable = 50
    let myConstant = 42

    A constant or variable must have the same type as the value you want to assign to it. However, you don’t always have to write the type explicitly. Providing a value when you create a constant or variable lets the compiler infer its type. In the example above, the compiler infers that myVariable is an integer because its initial value is a integer.
    一个常量或变量的的类型必须与你想给予它的值的类型一致。然后,你不用一定要明确的写出类型。当你建立一个常量或变量时,你提供一个值来让编译器推断它的类型。在上面的例子中,编译器会推断出myVariable是一个整形,因为它被赋值了一个整形。

    If the initial value doesn’t provide enough information (or if there is no initial value), specify the type by writing it after the variable, separated by a colon.
    如果一个初始化的值并不能提供足够的信息(或者他根本就没有初始值),将类型写在这个变量的后面,并用冒号隔
    开。
    let implicitInteger = 70
    let implicitDouble = 70.0
    let explicitDouble: Double = 70

    EXPERIMENT
    实验

    Create a constant with an explicit type of Float and a value of 4.
    创建一个值为4的显式浮点类型的常量。

    Values are never implicitly converted to another type. If you need to convert a value to a different type, explicitly make an instance of the desired type.
    值从来不会隐式的转化为另一种类型。如果你需要把一个值转换成另外的类型,明确的创造一个所需类型的实例。
    let label = "The width is "
    let width = 94
    let widthLabel = label + String(width)

    EXPERIMENT
    实验

    Try removing the conversion to String from the last line. What error do you get?

    在上一行中,尝试移除到String的转换,你会得到什么错误?

    There’s an even simpler way to include values in strings: Write the value in parentheses, and write a backslash (\) before the parentheses. For example:
    有一个更简单的办法去在字符串中包含一个值,就是将值写在括号中,并在括号的前面加\,例如:
    let apples = 3
    let oranges = 5
    let appleSummary = "I have \(apples) apples."
    let fruitSummary = "I have \(apples + oranges) pieces of fruit."

    EXPERIMENT
    实验


    Use \() to include a floating-point calculation in a string and to include someone’s name in a greeting.
    使用\()来在字符串中包含一个浮点运算,再包含一个问候某人的名字。

    Create arrays and dictionaries using brackets ([]), and access their elements by writing the index or key in 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 initializer syntax.
    使用初始化语法来构建一个空的数组或字典。

    let emptyArray = String[]()
    let emptyDictionary = Dictionary<String, Float>()

     type information can be inferred, you can write an empty array as [] and an empty dictionary as [:]—for example, when you set a new value for a variable or pass an argument to a function.
    类型信息可以被推断出来,你可以写一个空的数组像[]和一个空的字典像[:]--例如,当你给变量设置一个新值或传递参数时。
    shoppingList = []   // Went shopping and bought everything.

    Control Flow

    控制流

    Use if and switch to make conditionals, and use for-inforwhile, and do-while to make loops. Parentheses around the condition or loop variable are optional. Braces around the body are required.
    使用if和switch生成条件句,使用for-in,for,while和do-while生成循环语句。包围条件或者循环变量的圆括号是可选的。身体周围的大括号是必须的。
    let individualScores = [75, 43, 103, 87, 12]
    var teamScore = 0
    for score in individualScores {
        if score > 50 {
            teamScore += 3
        } else {
            teamScore += 1
        }
    }
    teamScore

    In an if statement, the conditional must be a Boolean expression—this means that code such as if score { ... } is an error, not an implicit comparison to zero.
    在if语句中,条件必须是一个boolean表达式,这意味着这样的代码if score{...}是一个错误,没有隐含的对零的比较。(就是说"非零是真"在swift中不存在)

    You can use if and let together to work with values that might be missing. These values are represented as optionals. An optional value either contains a value or contains nil to indicate that the value is missing. Write a question mark (?) after the type of a value to mark the value as optional.
    你可以同时使用if和let与那些可能会丢失的值连在一起。(是这么翻译吧?个人理解就是初始化的值)这些值表现为可变,一个可变值可能包含一个值或一个nil来代表该值丢失。在值的类型后面写一个问号标记(?)该值的类型可选。
    var optionalString: String? = "Hello"
    optionalString == nil
     
    var optionalName: String? = "John Appleseed"
    var greeting = "Hello!"
    if let name = optionalName {
        greeting = "Hello, \(name)"
    }
    

    EXPERIMENT
    实验


    Change optionalName to nil. What greeting do you get? Add an else clause that sets a different greeting if optionalName is nil.
    改变optionalName的值为nil。greeting会变成什么?如果optionalName为空,添加一个else分句来设置不同的greeting。

    If the optional value is nil, the conditional is false and the code in braces is skipped. Otherwise, the optional value is unwrapped and assigned to the constant after let, which makes the unwrapped value available inside the block of code.
    如果一个可变值为nil,条件是false,则大括号中的代码被跳过。否则,let后面的指定的可变值被赋值为这个常量,这使得被指定的值可用并进入大括号中的代码。

    Switches support any kind of data and a wide variety of comparison operations—they aren’t limited to integers and tests for equality.
    switch语句支持任意类型的数据和各种各样的比较操作,它们不限于整数和仅仅是为了测试相等。
    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:
        let vegetableComment = "Everything tastes good in soup."
    }

    EXPERIMENT
    实验


    Try removing the default case. What error do you get?
    试着移除default分句,看看会报什么错?

    After executing the code inside the switch case that matched, the program exits from the switch statement. Execution doesn’t continue to the next case, so there is no need to explicitly break out of the switch at the end of each case’s code.
    在执行了switch case匹配成功的分支代码后,程序从switch声明中退出。执行的状态不会继续到下一个分支,所以不需要在每一个case代码的后面确切的标注退出switch。

    You use for-in to iterate over items in a dictionary by providing a pair of names to use for each key-value pair.
    通过提供一个键值对的名字使用for-in叠代字典中的每一个元素。
    let interestingNumbers = [
        "Prime": [2, 3, 5, 7, 11, 13],
        "Fibonacci": [1, 1, 2, 3, 5, 8],
        "Square": [1, 4, 9, 16, 25],
    ]
    var largest = 0
    for (kind, numbers) in interestingNumbers {
        for number in numbers {
            if number > largest {
                largest = number
            }
        }
    }
    largest

    EXPERIMENT
    实验


    Add another variable to keep track of which kind of number was the largest, as well as what that largest number was.
    添加其他变量使这与那种数最大无关,也就是数最大是什么。(这句完全没翻译明白)

    Use while to repeat a block of code until a condition changes. The condition of a loop can be at the end instead, ensuring that the loop is run at least once.
    使用while来重复一段代码知道条件改变,这个循环的条件可以在结尾处替换,来确保这个循环至少执行一次。
    var n = 2
    while n < 100 {
        n = n * 2
    }
    n
     
    var m = 2
    do {
        m = m * 2
    } while m < 100
    m

    You can keep an index in a loop—either by using .. to make a range of indexes or by writing an explicit initialization, condition, and increment. These two loops do the same thing:
    你可以保持一个索引在循环中,或者使用..来确立一个索引的范围或者使用明确的初始值,条件和增量。下面的两个循环做了同样的事情:
    var firstForLoop = 0
    for i in 0..3 {
        firstForLoop += i
    }
    firstForLoop
     
    var secondForLoop = 0
    for var i = 0; i < 3; ++i {
        secondForLoop += 1
    }
    secondForLoop
    Use .. to make a range that omits its upper value, and use ... to make a range that includes both values.
    使用..来确定一个不包含最大值的范围,使用...确定一个包括所有值的范围。

    Functions and Closures

    函数和闭包(Closures怎么翻译?)

    Use func to declare a function. Call a function by following its name with a list of arguments in parentheses. Use -> to separate the parameter names and types from the function’s return type.
    使用func来描述一个函数。通过跟在名字后面括号中的一个参数列表调用函数。使用->来分割参数名称和函数返回值类型。
    func greet(name: String, day: String) -> String {
        return "Hello \(name), today is \(day)."
    }
    greet("Bob", "Tuesday")

    EXPERIMENT
    实验

    Remove the day parameter. Add a parameter to include today’s lunch special in the greeting.
    移除day参数,添加一个参数来包含今天午餐特别的问候。

    Use a tuple to return multiple values from a function.
    使用数组从一个函数中返回多值。

    func getGasPrices() -> (Double, Double, Double) {
        return (3.59, 3.69, 3.79)
    }
    getGasPrices()

    Functions can also take a variable number of arguments, collecting 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)

    EXPERIMENT
    实验

    Write a function that calculates the average of its arguments.
    写一个函数,要求计算传入参数的平均值。

    Functions can be nested. Nested functions have access to variables that were declared in the outer function. You can use nested functions to organize the code in a function that is long or complex.
    函数可以嵌套,嵌套函数可以访问在外部函数声明的变量。在函数过长或者很复杂的时候,你可以使用嵌套函数来组织代码。

    func returnFifteen() -> Int {
        var y = 10
        func add() {
            y += 5
        }
        add()
        return y
    }
    returnFifteen()

    Functions are a first-class type. This means that a function can return another function as its value.
    函数是一个first-class类型。这意味着一个函数可以返回另一个函数作为它的值。
    func makeIncrementer() -> (Int -> Int) {
        func addOne(number: Int) -> Int {
            return 1 + number
        }
        return addOne
    }
    var increment = makeIncrementer()
    increment(7)

    A function can take another function as one of its arguments.
    一个函数可以把另一个函数作为它其中一个参数。
    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)

    Functions are actually a special case of closures. You can write a closure without a name by surrounding code with braces ({}). Use in to separate the arguments and return type from the body.
    函数实际上是一个特殊情况下的闭包。你可以写一个被大括号{}包裹着的没有名字的匿名方法。在函数体中使用in来分隔参数和返回值。

    numbers.map({
        (number: Int) -> Int in
        let result = 3 * number
        return result
        })

    EXPERIMENT
    实验

    Rewrite the closure to return zero for all odd numbers.
    重写这个匿名方法来返回所有的奇数。

    You have several options for writing closures more concisely. When a closure’s type is already known, such as the callback for a delegate, you can omit the type of its parameters, its return type, or both. Single statement closures implicitly return the value of their only statement.
    你有几个选项来使你的书写那些闭包更简介。当一个闭包的类型已知时,就像一个代理的回调,你可以省略它们的参数类型,它们的返回值,或者都省略。一个简单的闭包声明仅仅隐式的返回它们声明的返回值。
    numbers.map({ number in 3 * number })

    You can refer to parameters by number instead of by name—this approach is especially useful in very short closures. A closure passed as the last argument to a function can appear immediately after the parentheses.
    你可以参考参数的数量而不是名字,在一个间断的闭包中这是非常有用的的方法。一个匿名函数把最后一个参数传递给一个函数,可以立刻出现在圆括号后面。(有点懵。。。)
    sort([1, 5, 3, 12, 2]) { $0 > $1 }

    Objects and Classes

    对象和类

    Use class followed by the class’s name to create a class. A property declaration in a class is written the same way as a constant or variable declaration, except that it is in the context of a class. Likewise, method and function declarations are written the same way.
    使用class在类名前面来建立一个类。类中的属性的声明方式和一个变量或常量的声明一样,除非它在类的上下文中。同样的,方法和函数的声明也都相同。
    class Shape {
        var numberOfSides = 0
        func simpleDescription() -> String {
            return "A shape with \(numberOfSides) sides."
        }
    }

    EXPERIMENT
    实验

    Add a constant property with let, and add another method that takes an argument.
    使用let添加一个常量属性,再添加一个接收一个参数的方法。

    Create an instance of a class by putting parentheses after the class name. Use dot syntax to access the properties and methods of the instance.
    通过在类名后面加上圆括号来创建一个类的实例。使用点语法来访问该实例的属性和方法。
    var shape = Shape()
    shape.numberOfSides = 7
    var shapeDescription = shape.simpleDescription()

    This version of the Shape class is missing something important: an initializer to set up the class when an instance is created. Use init to create one.
    这个版本的Shape类缺失了一些重要的东西:当实例被创建时候的初始化该类。使用init来创建一个。
    class NamedShape {
        var numberOfSides: Int = 0
        var name: String
        
        init(name: String) {
            self.name = name
        }
        
        func simpleDescription() -> String {
            return "A shape with \(numberOfSides) sides."
        }
    }

    Notice how self is used to distinguish the name property from the name argument to the initializer. The arguments to the initializer are passed like a function call when you create an instance of the class. Every property needs a value assigned—either in its declaration (as with numberOfSides) or in the initializer (as with name).
    注意,使用self如何来区分属性名字和初始化函数中的参数名字。当你创建一个类的实例时,这些参数对于构造器像一个函数一样被调用。每一个属性需要被数值,在它被声明的时候(像numberOfSides)或该类初始化的时候(像name)。

    Use deinit to create a deinitializer if you need to perform some cleanup before the object is deallocated.
    如果你需要在对象被销毁前做一些清楚工作,使用deinit来创建一个释放器。

    Subclasses include their superclass name after their class name, separated by a colon. There is no requirement for classes to subclass any standard root class, so you can include or omit a superclass as needed.
    子类包含他们父类的名在在他们的名字后面,用一个冒号分开。不要求子类必须继承一个标准的根类。所以你可以按需包含一个父类或省略它。

    Methods on a subclass that override the superclass’s implementation are marked with override—overriding a method by accident, without override, is detected by the compiler as an error. The compiler also detects methods with override that don’t actually override any method in the superclass.
    当子类的方法覆盖父类的实现时,使用override。如果没有override,编译器会检测报错。编译器也会检测override没有覆盖到任何一个父类的方法。

    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()

    Make another subclass of NamedShape called Circle that takes a radius and a name as arguments to its initializer. Implement an area and a describe method on the Circle class.
    创建另一个名字叫Circle子类,继承于NamedSpace,使用半径和名称作为它的初始化参数。在Circle类里实现一个area和describe方法。

    In addition to simple properties that are stored, properties can have a getter and a setter.
    除了简单的属性被载入外,属性可以有一个getting和一个setting。
    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 triagle with sides of length \(sideLength)."
        }
    }
    var triangle = EquilateralTriangle(sideLength: 3.1, name: "a triangle")
    triangle.perimeter
    triangle.perimeter = 9.9
    triangle.sideLength

    In the setter for perimeter, the new value has the implicit name newValue. You can provide an explicit name in parentheses after set.
    在perimeter的setter中,这个新的值有一个隐式的名字newValue。你可以在set后面的括号中提供一个确切的名字。

    Notice that the initializer for the EquilateralTriangle class has three different steps:

    1. Setting the value of properties that the subclass declares.

    2. Calling the superclass’s initializer.

    3. Changing the value of properties defined by the superclass. Any additional setup work that uses methods, getters, or setters can also be done at this point.

    注意,EquilateralTriangle在初始化的时候有三个不同的步骤:
    1.设置子类声明的属性的值。
    2.调用父类的构造方法。
    3.改变父类定义的属性的值。任何格外的设置工作,getters或者setters都会在这一步完成。

    If you don’t need to compute the property but still need to provide code that is run before and after setting a new value, use willSet and didSet. For example, the class below ensures that the side length of its triangle is always the same as the side length of its square.
    如果你不需要计算性能但仍需提供运行之前和之后设置新值的代码,使用willset和didset。下面的类保证这个三角形的编程一直和正方形的边长相等。

    class TriangleAndSquare {
        var triangle: EquilateralTriangle {
        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 = EquilateralTriangle(sideLength: size, name: name)
        }
    }
    var triangleAndSquare = TriangleAndSquare(size: 10, name: "another test shape")
    triangleAndSquare.square.sideLength
    triangleAndSquare.triangle.sideLength
    triangleAndSquare.square = Square(sideLength: 50, name: "larger square")
    triangleAndSquare.triangle.sideLength

    Methods on classes have one important difference from functions. Parameter names in functions are used only within the function, but parameters names in methods are also used when you call the method (except for the first parameter). By default, a method has the same name for its parameters when you call it and within the method itself. You can specify a second name, which is used 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 ? before operations like methods, properties, and subscripting. If the value before the ? is nil, everything after the ? is ignored and the value of the whole expression is nil. Otherwise, the optional value is unwrapped, and everything after the ? acts on the unwrapped value. In both cases, the value of the whole expression is an optional value.
    当操作可变值的时候,你可以在方法,属性和下标的操作前加上?。如果在?前面的值是空,则?之后的一切东西会被忽略,整个表达式为空。否则,如果这个可变值已经被赋值,则在?之后的所有操作都将被执行。无论怎样,这个表达式的值都是一个可变值。

    let optionalSquare: Square? = Square(sideLength: 2.5, name: "optional square")
    let sideLength = optionalSquare?.sideLength

    Enumerations and Structures

    枚举和结构

    Use enum to create an enumeration. Like classes and all other named types, enumerations can have methods associated with them.
    使用enum来创建一个枚举类型。就像类和所有其他命名类型一样,枚举类型也有方法和他们联系起来。
    enum Rank: Int {
        case Ace = 1
        case Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten
        case Jack, Queen, King
        func simpleDescription() -> 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
    let aceRawValue = ace.toRaw()

    EXPERIMENT
    实验

    Write a function that compares two Rank values by comparing their raw values.
    写一个函数通过比较两个Rank的初始值来比较他们。

    In the example above, the raw value type of the enumeration is Int, so you only have to specify the first raw value. The rest of the raw values are assigned in order. You can also use strings or floating-point numbers as the raw type of an enumeration.
    在上一个例子中,枚举类型的初始值类型是Int,那么你只需指定第一个初始值。其余的初始值会依次分配。你也可以使用字符串或者浮点数作为枚举的原始类型。

    Use the toRaw and fromRaw functions to convert between the raw value and the enumeration value.
    使用toRaw和fromRaw函数在初始值和枚举值之间转换。

    if let convertedRank = Rank.fromRaw(3) {
        let threeDescription = convertedRank.simpleDescription()
    }

    The member values of an enumeration are actual values, not just another way of writing their raw values. In fact, in cases where there isn’t a meaningful raw value, you don’t have to provide one.
    枚举成员的值是实际值。不仅仅是他们原始值的另一种表达方式。事实上,没有一个有意义的原始值,你不需要提供一个。
    enum Suit {
        case Spades, Hearts, Diamonds, Clubs
        func simpleDescription() -> String {
            switch self {
            case .Spades:
                return "spades"
            case .Hearts:
                return "hearts"
            case .Diamonds:
                return "diamonds"
            case .Clubs:
                return "clubs"
            }
        }
    }
    let hearts = Suit.Hearts
    let heartsDescription = hearts.simpleDescription()

    EXPERIMENT
    实验


    Add a color method to Suit that returns “black” for spades and clubs, and returns “red” for hearts and diamonds.
    给Suit添加一个color方法,如果是spadesclubs返回black,如果是hearts和diamonds返回red。

    Notice the two ways that the Hearts member of the enumeration is referred to above: When assigning a value to the hearts constant, the enumeration member Suit.Hearts is referred to by its full name because the constant doesn’t have an explicit type specified. Inside the switch, the enumeration is referred to by the abbreviated form .Hearts because the value of self is already known to be a suit. You can use the abbreviated form anytime the value’s type is already known.

    注意,上面提到的枚举的Hearts成员的两种方式:
    当给hearts常量赋值的时候,枚举成员Suit.Hearts被列出全名,因为常量没有被显式的指定类型。在switch中,枚举被简写成.Hearts因为self的值已经知道是Suit类型。你可以使用缩写形式在任何值类型已知的情况下。

    Use struct to create a structure. Structures support many of the same behaviors as classes, including methods and initializers. One of the most important differences between structures and classes is that structures are always copied when they are passed around in your code, but classes are passed by reference.
    使用struct来创建一个结构体。结构体同类一样支持很多的行为,包括方法和构造器。结构体和类的一个最大的区别在于当结构体被调用到你的代码时,他们都是复制过来的,而类只是传递引用。

    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()

    EXPERIMENT
    实验

    Add a method to Card that creates a full deck of cards, with one card of each combination of rank and suit.
    添加一个方法到Card来创建一个全套的卡牌,用一套全花色的卡牌。(这里扑克牌和花色这里翻译不好)

    An instance of an enumeration member can have values associated with the instance. Instances of the same enumeration member can have different values associated with them. You provide the associated values when you create the instance. Associated values and raw values are different: The raw value of an enumeration member is the same for all of its instances, and you provide the raw value when you define the enumeration.
    一个枚举成员的实例可以有一个与实例相关联的值。这些相同的枚举成员的实例已经有了不同的值赋给他们。当你创建这个实例时提供相关值。相关值和初始值是不同的,一个枚举成员的初始值对于所有它的实例都是相同的,并且是你在定义这个枚举类型时提供的。

    For example, consider the case of requesting the sunrise and sunset time from a server. The server either responds with the information or it responds with some error information.
    例如,考虑从服务器请求的日出和日落时间的情况。服务器响应信息回应一些错误信息

    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)"
    }

    EXPERIMENT
    实验

    Add a third case to ServerResponse and to the switch.
    添加第三个分支给ServerResponse,并使用。

    Notice how the sunrise and sunset times are extracted from the ServerResponse value as part of matching the value against the switch cases.
    注意,日落和日出时间是如何从匹配switch case的一部分ServerResponse的值中获取的。

    Protocols and Extensions

    协议和拓展

    Use protocol to declare a protocol.
    使用protocol来声明一个协议。

    protocol ExampleProtocol {
        var simpleDescription: String { get }
        mutating func adjust()
    }

    Classes, enumerations, and structs can all adopt protocols.
    类,枚举,和结构体都可以使用协议。

    class SimpleClass: ExampleProtocol {
        var simpleDescription: String = "A very simple class."
        var anotherProperty: Int = 69105
        func adjust() {
            simpleDescription += "  Now 100% adjusted."
        }
    }
    var a = SimpleClass()
    a.adjust()
    let aDescription = a.simpleDescription
     
    struct SimpleStructure: ExampleProtocol {
        var simpleDescription: String = "A simple structure"
        mutating func adjust() {
            simpleDescription += " (adjusted)"
        }
    }
    var b = SimpleStructure()
    b.adjust()
    let bDescription = b.simpleDescription

    EXPERIMENT
    实验

    Write an enumeration that conforms to this protocol.
    写一个符合本协议的枚举。

    Notice the use of the mutating keyword in the declaration of SimpleStructure to mark a method that modifies the structure. The declaration of SimpleClass doesn’t need any of its methods marked as mutating because methods on a class can always modify the class.
    注意,mutating关键字的使用为了声明在SimpleStructure中修改了这个方法。SimpleClass不需要声明它的任何一种方法的变化因为类中的方法始终可以修改类。

    Use extension to add functionality to an existing type, such as new methods and computed properties. You can use an extension to add protocol conformance to a type that is declared elsewhere, or even to a type that you imported from a library or framework.
    使用extension来添加一个功能给已经存在的类型,就像新的方法和计算性能。你可以使用一个拓展去添加一个一致性的协议对于任何一种情况,甚至是你从一个库或框架导入进来的一个类型。

    extension Int: ExampleProtocol {
        var simpleDescription: String {
        return "The number \(self)"
        }
        mutating func adjust() {
            self += 42
        }
    }
    7.simpleDescription

    Write an extension for the Double type that adds an absoluteValue property.
    给Double类型写一个拓展,添加一个absoluteValue属性。

    You can use a protocol name just like any other named type—for example, to create a collection of objects that have different types but that all conform to a single protocol. When you work with values whose type is a protocol type, methods outside the protocol definition are not available.
    你可以像其他任何一种命名类型一样使用一个协议名称,例如,创建一个有不同类型的对象的集合,但是这些对象都符合单一的协议。当你使用一种被定义为协议类型的类型的值时,那么定义在协议外面的方法将不可用。

    let protocolValue: ExampleProtocol = a
    protocolValue.simpleDescription
    // protocolValue.anotherProperty  // Uncomment to see the error

    Even though the variable protocolValue has a runtime type of SimpleClass, the compiler treats it as the given type of ExampleProtocol. This means that you can’t accidentally access methods or properties that the class implements in addition to its protocol conformance.
    尽管变量protocolValue在SimpleClass中有一个可变类型,编译器将把它的类型给定为ExampleProtocol。这意味着你不能意外的访问到除了类实现的一致的协议之外的方法和属性。

    Generics

    泛型

    Write a name inside angle brackets to make a generic function or type.
    在尖括号里写一个名字来定义一种泛型函数或类型。
    func repeat<ItemType>(item: ItemType, times: Int) -> ItemType[] {
        var result = ItemType[]()
        for i in 0..times {
            result += item
        }
        return result
    }
    repeat("knock", 4)

    You can make generic forms of functions and methods, as well as classes, enumerations, and structures.
    你可以想类,枚举和结构体那样,定义一个方法和函数的泛型形式。
    // Reimplement the Swift standard library's optional type
    enum OptionalValue<T> {
        case None
        case Some(T)
    }
    var possibleInteger: OptionalValue<Int> = .None
    possibleInteger = .Some(100)

    Use where after the type name to specify a list of requirements—for example, to require the type to implement a protocol, to require two types to be the same, or to require a class to have a particular superclass.
    在类型名称后面加上where来指定一系列的需求,例如,或要求一个类型实现一个协议,或要求两个类型必须相同,或要求一个类有一个特别的基类。

    func anyCommonElements <T, U where T: Sequence, U: Sequence, T.GeneratorType.Element: Equatable, T.GeneratorType.Element == U.GeneratorType.Element> (lhs: T, rhs: U) -> Bool {
        for lhsItem in lhs {
            for rhsItem in rhs {
                if lhsItem == rhsItem {
                    return true
                }
            }
        }
        return false
    }
    anyCommonElements([1, 2, 3], [3])

    EXPERIMENT
    实验

    Modify the anyCommonElements function to make a function that returns an array of the elements that any two sequences have in common.
    修改anyCommonElements函数使得函数返回元素的数组为普通的有任意两列的数组。

    In the simple cases, you can omit where and simply write the protocol or class name after a colon. Writing<T: Equatable> is the same as writing <T where T: Equatable>.
    在简单的情况下,你可以省略where,只在冒号后面写协议或者类的名称。书写<T : Equatable>和<T where T : Equatable>是一样的。

    The Basics
    基本知识

    Swift is a new programming language for iOS and OS X app development. Nonetheless, many parts of Swift will be familiar from your experience of developing in C and Objective-C.
    swift是一个作为开发IOS和OS X应用开发的一款新语言。尽管如此,swift的许多部分将会和你所掌握的C和Objective-C语言很相似。

    Swift provides its own versions of all fundamental C and Objective-C types, including Int for integers; Doubleand Float for floating-point values; Bool for Boolean values; and String for textual data. Swift also provides powerful versions of the two primary collection types, Array and Dictionary, as described in Collection Types.
    swift提供了自己的所有C和Objective-C基本类型。包括Int来对应整数。Double和Float对应浮点值。Bool对应Boolean值,和String对应文本数据。swift同样提供了强有力的版本对应两个主要的集合类型,Array和Dictionary。

    Like C, Swift uses variables to store and refer to values by an identifying name. Swift also makes extensive use of variables whose values cannot be changed. These are known as constants, and are much more powerful than constants in C. Constants are used throughout Swift to make code safer and clearer in intent when you work with values that do not need to change.
    像C,通过一个识别名称来使用变量来存储和引用一个值。swift同样广泛的使用那些不能被改变值的变量。这些被叫做常量,并且不在C中更加的强大。当你使用一个值单并不需要改变它时,常量被贯穿始终使的代码更加的安全和干净。

    In addition to familiar types, Swift introduces advanced types not found in Objective-C. These include tuples, which enable you to create and pass around groupings of values. Tuples can return multiple values from a function as a single compound value.
    除了常见的类型,swift引进了Objective-C里没有的先进类型。这些包括可以使你建立和归类那些值的元组。元组可以从一个函数中返回多个值就像一个单独的复合的值。

    Swift also introduces optional types, which handle the absence of a value. Optionals say either “there is a value, and it equals x” or “there isn’t a value at all”. Optionals are similar to using nil with pointers in Objective-C, but they work for any type, not just classes. Optionals are safer and more expressive than nilpointers in Objective-C and are at the heart of many of Swift’s most powerful features.
    swift还介绍了可选类型,可以处理一个缺省的类型。可选或者表示“这是一个值,它等价于XXX”或者表示“这里没有一个值”。可选就像在Objective-C使用一个nil型的指针,但是他们可以使任意类型,不仅仅是类。可选比Objective-C中中得指向nil的指针更安全和更有表现力,他是swift最强大的功能的核心所在。

    Optionals are an example of the fact that Swift is a type safe language. Swift helps you to be clear about the types of values your code can work with. If part of your code expects a String, type safety prevents you from passing it an Int by mistake. This enables you to catch and fix errors as early as possible in the development process.
    自选可以看出swift是一个类型安全的语言。它帮助你去明确你代码中使用的值的类型。如果你的代码中存在String,类型安全的机制会帮助你防止把它当成一个Int使用。这可以帮助你在开发工程中尽早的找到和修复错误。

    展开全文
  • https://www.cnswift.org/ 内容pdf版, 已更新至Swift 5.1版本,全文带有目录,方便查看
  • 过去的五年时间里,苹果全新 Swift 编程语言的普及速度超过了所有人的预期。 在去年3月的 TIOBE 编程语言排名中,Swift 的受欢迎程度首次进入第10位。值得注意的是,在前10名中的编程语言推出时间都超过了20年,而 ...

    Swift是苹果于2014年WWDC(苹果开发者大会)发布的新开发语言,可与Objective-C共同运行于Mac OS和iOS平台,用于搭建基于苹果平台的应用程序。过去的五年时间里,苹果全新 Swift 编程语言的普及速度超过了所有人的预期。

    在去年3月的 TIOBE 编程语言排名中,Swift 的受欢迎程度首次进入第10位。值得注意的是,在前10名中的编程语言推出时间都超过了20年,而 Swift 才刚刚推出几年的时间。根据观察,排行榜中 TOP 9 的编程语言已基本稳定,唯独第 10 名每个月都会有变化。按照 TIOBE 的说法,“Swift 正在敲开 TIOBE 排行榜前 10 名的大门,且试图成为 TIOBE TOP 10 的固定成员。”

     

    那么Swift究竟凭什么能快速杀入前10?

    码宝宝觉得有以下7点:

    1. Swift 简洁的语法

    Swift方法和函数的调用使用十分简化,使之看起来更像是自然的英语,语言也很有表现力,所以Swift 比起 OC 相对容易懂。

    1. Swift 的安全性

    Swift的语法和语言结构排除了Objective-C中可能出现的几种类型的错误,额外的质量控制层,使错误减少发生,bug更早的被修复。

    1. Swift 代码更少

    Swift 减少了重复性语句和字符串操作所需要的代码量。

    4.Swift 更快

    根据时下流行的 GeekBench 性能工具的创造者的调查, 2014年12月中使用曼德尔布罗算法(Mandelbrot algorithm)进行计算密集型任务的性能上,Swift已经逼近C++的表现。

    5.Swift的开源

    这意味着学习Swift的底层本质更加方便和简单了,Swift也会变得更加完善,全球的开发者都会为Swift贡献自己的代码和力量。

    6.Swift 鼓励交互式编码

    Swift 新引入的 Playgrounds 是有经验的开发者的福音。苹果公司已经将内联代码执行操作加入到了 Playgrounds 中,以帮助程序员创建代码块或者编写某种算法时获得反馈。这样的反馈循环可以提升代码编写的速度。

    1. Swift 的战略意义

    其实,可以把Swift看做苹果公司的一项新的商业战略,这种简单好用还安全的编程语言吸引了越来越多的软件爱好者加入,让该生态圈更加繁荣发展。

    最近Swift5也在 WWDC 2019 开发者大会上亮相,Swift5是Swift发展的里程碑,此版本终于迎来了 ABI 稳定,因此 Swift 运行时现在可以引入到 Apple各类操作系统的不同版本中,包括 macOS、iOS、tvOS 与 watchOS。Swift 5 还引入了构建块的新功能,包括重新实现 String、在运行时对执行内存的独占访问与新数据类型,以及对动态可调用类型的支持。

    可以说,Swift必将是未来主流的iOS编程语言,所以如果你有志于长期从事iOS的开发,那么选择学习Swift一定不会错!

    而小码哥教育一直以来的目标就是帮助更多有需要的同学真正学到有价值的知识,学员想要将Swift知识轻松运用在工作实践中、提升技术实力,一定不能错过下面有趣又惊喜的信息!!!

     

    大家看到这个趣味长图的重点木有?重要的事情多说几遍,就是:最近小码哥教育推出由明杰老师主讲的Swift课程,从入门、进阶、实战以及底层全面介绍Swift,带你从入门到精通(经过码宝宝力争),超值优惠活动即将来袭!

    2019年4月19日00:002019年4月22日24:00

    两人拼团333元+10%分销

    搜索“腾讯课堂”输入“小码哥教育”或者“从入门到精通Swift”即可购买!

    展开全文
  • 使用 Swift 语言编程的优缺点

    万次阅读 2017-10-20 23:15:27
    总的来说,我认为使用 Swift 来作为编程语言的优点还是要远远大于缺点的,而且很多缺点苹果也在逐渐改善。 优点####简洁的语法 ####更强的类型安全 函数式编程的支持Swift 语言本身提供了对函数式编程的支持。 Objc...

    我们的 Swift 项目上线已经有一段时间了。结合目前 Swift 的使用情况,总结下其与 Objective-C 相比的优缺点。

    总的来说,我认为使用 Swift 来作为编程语言的优点还是要远远大于缺点的,而且很多缺点苹果也在逐渐改善。

    • 优点

      • 简洁的语法

      • 更强的类型安全

      • 函数式编程的支持

        Swift 语言本身提供了对函数式编程的支持。
        Objc 本身是不支持的,但是可以通过引入 ReactiveCocoa 这个库来支持函数式编程。

      • 编写 OS X 下的自动化脚本

    • 缺点

      • App体积变大

        使用 Swift 后, App 体积大概增加 5-8 M 左右,对体积大小敏感的慎用。

        体积变大的原因是因为 Swift 还在变化,所以 Apple 没有在 iOS 系统里放入 Swift 的运行库,反而是每个 App 里都要包含其对应的 Swift 运行库。

      • Xcode 支持不够好

        如果你是使用 Xcode经常卡住或者崩溃想必你是肯定碰到过了,这个是目前使用 Swift 最让人头疼的事情,即使是到现在XCode 9, 有时候也会遇到这种问题,所以要看你的承受力了……

      • 第三方库的支持不够多

        目前确实 Swift 编写的第三方库确实不多,但可以通过桥接的方式来使用 Objc 的三方库,基本上没有太大问题。现在已经改善很多了…

      • 语言版本更新带来的编译问题

        Swift 语言本身还在发展,所以每次版本更新后都会出现编译不过的情况(至少到目前为止还是),但是自从 4.0 版本发布后,改动没有 beta 时候那么大了,而且根据 Xcode 提示基本就可以解决语法变动导致的编译问题了。

    展开全文
  • Swift 编程语言入门教程

    万次阅读 多人点赞 2014-06-07 17:02:03
    今天在网上看到一篇非常好的教程,分享给大家 ... ...1 简介2 Swift入门3 简单值4 控制流5 函数与闭包6 对象与类7 枚举与结构 ...今天凌晨Apple刚刚发布了Swift编程语言,本文从其发布的书籍《The Swift Prog

    今天在网上看到一篇非常好的教程,分享给大家

    原文地址:http://gashero.iteye.com/blog/2075324

    1   简介

    今天凌晨Apple刚刚发布了Swift编程语言,本文从其发布的书籍《The Swift Programming Language》中摘录和提取而成。希望对各位的iOS&OSX开发有所帮助。

    Swift是供iOS和OS X应用编程的新编程语言,基于C和Objective-C,而却没有C的一些兼容约束。Swift采用了安全的编程模式和添加现代的功能来是的编程更加简单、灵活和有趣。界面则基于广受人民群众爱戴的Cocoa和Cocoa Touch框架,展示了软件开发的新方向。

    Swift已经存在了多年。Apple基于已有的编译器、调试器、框架作为其基础架构。通过ARC(Automatic Reference Counting,自动引用计数)来简化内存管理。我们的框架栈则一直基于Cocoa。Objective-C进化支持了块、collection literal和模块,允许现代语言的框架无需深入即可使用。(by gashero)感谢这些基础工作,才使得可以在Apple软件开发中引入新的编程语言。

    Objective-C开发者会感到Swift的似曾相识。Swift采用了Objective-C的命名参数和动态对象模型。提供了对Cocoa框架和mix-and-match的互操作性。基于这些基础,Swift引入了很多新功能和结合面向过程和面向对象的功能。

    Swift对新的程序员也是友好的。他是工业级品质的系统编程语言,却又像脚本语言一样的友好。他支持playground,允许程序员实验一段Swift代码功能并立即看到结果,而无需麻烦的构建和运行一个应用。

    Swift集成了现代编程语言思想,以及Apple工程文化的智慧。编译器是按照性能优化的,而语言是为开发优化的,无需互相折中。(by gashero)可以从"Hello, world"开始学起并过渡到整个系统。所有这些使得Swift成为Apple软件开发者创新的源泉。

    Swift是编写iOS和OSX应用的梦幻方式,并且会持续推进新功能的引入。我们迫不及待的看到你用他来做点什么。

    2   Swift入门

    一个新语言的学习应该从打印"Hello, world"开始。在Swift,就是一行:

    println("Hello, world")
    

    如果你写过C或Objective-C代码,这个语法看起来很熟悉,在Swift,这就是完整的程序了。你无需导入(import)一个单独的库供输入输出和字符串处理。全局范围的代码就是用于程序的入口,所以你无需编写一个 main() 函数。你也无需在每个语句后写分号。

    这个入门会给出足够的信息教你完成一个编程任务。无需担心你还不理解一些东西,所有没解释清楚的,会在本书后续详细讲解。

    Note

    作为最佳实践,可以将本章在Xcode的playground中打开。Playground允许你编辑代码并立即看到结果。

    3   简单值

    使用 let 来定义常量, var 定义变量。常量的值无需在编译时指定,但是至少要赋值一次。这意味着你可以使用常量来命名一个值,你发现只需一次确定,却用在多个地方。

    var myVariable = 42
    myVariable = 50
    let myConstant = 42
    

    Note

    gashero注记

    这里的常量定义类似于函数式编程语言中的变量,一次赋值后就无法修改。多多使用有益健康。

    一个常量或变量必须与赋值时拥有相同的类型。因此你不用严格定义类型。提供一个值就可以创建常量或变量,并让编译器推断其类型。在上面例子中,编译其会推断myVariable是一个整数类型,因为其初始化值就是个整数。

    Note

    gashero注记

    类型与变量名绑定,属于静态类型语言。有助于静态优化。与Python、JavaScript等有所区别。

    如果初始化值没有提供足够的信息(或没有初始化值),可以在变量名后写类型,以冒号分隔。

    let imlicitInteger = 70
    let imlicitDouble = 70.0
    let explicitDouble: Double = 70
    

    Note

    练习

    创建一个常量,类型为Float,值为4。

    值永远不会隐含转换到其他类型。如果你需要转换一个值到不同类型,明确的构造一个所需类型的实例。

    let label = "The width is "
    let width = 94
    let widthLabel = label + String(width)
    

    Note

    练习

    尝试删除最后一行的String转换,你会得到什么错误?

    还有更简单的方法来在字符串中包含值:以小括号来写值,并用反斜线("")放在小括号之前。例如:

    let apples = 3
    let oranges = 5     //by gashero
    let appleSummary = "I have \(apples) apples."
    let fruitSummary = "I have \(apples + oranges) pieces of fruit."
    

    Note

    练习

    使用 () 来包含一个浮点数计算到字符串,并包含某人的名字来问候。

    创建一个数组和字典使用方括号 "[]" ,访问其元素则是通过方括号中的索引或键。

    var shoppingList = ["catfish", "water", "tulips", "blue paint"]
    shoppingList[1] = "bottle of water"
    
    var occupations = [
       "Malcolm": "Captain",
       "Kaylee": "Mechanic",
    ]
    occupations["Jayne"] = "Public Relations"
    

    要创建一个空的数组或字典,使用初始化语法:

    let emptyArray = String[]()
    let emptyDictionary = Dictionary<String, Float>()
    

    如果类型信息无法推断,你可以写空的数组为 "[]" 和空的字典为 "[:]",例如你设置一个知道变量并传入参数到函数:

    shoppingList = []   //去购物并买些东西 by gashero
    

    4   控制流

    使用 if 和 switch 作为条件控制。使用 for-in 、 for 、 while 、 do-while 作为循环。小括号不是必须的,但主体的大括号是必需的。

    let individualScores = [75, 43, 103, 87, 12]
    var teamScore = 0
    for score in individualScores {
        if score > 50 {
            teamScores += 3
        } else {
            teamScores += 1
        }
    }
    teamScore
    

    在 if 语句中,条件必须是布尔表达式,这意味着 if score { ... } 是错误的,不能隐含的与0比较。

    你可以一起使用 if 和 let 来防止值的丢失。这些值是可选的。可选值可以包含一个值或包含一个 nil 来指定值还不存在。写一个问号 "?" 在类型后表示值是可选的。

    var optionalString: String? = "Hello"
    optionalString == nil
    
    var optionalName: String? = "John Appleseed"
    var greeting = "Hello!"
    if let name = optionalName {
        greeting = "Hello, \(name)"
    }
    

    Note

    练习

    改变 optionalName 为 nil 。在问候时会发生什么?添加一个 else 子句在 optionalName 为 nil 时设置一个不同的值。

    如果可选值为 nil ,条件就是 false 大括号中的代码会被跳过。否则可选值未包装并赋值为一个常量,会是的未包装值的变量到代码块中。

    switch 支持多种数据以及多种比较,不限制必须是整数和测试相等。

    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

    练习

    尝试去掉 default ,看看得到什么错误。

    在执行匹配的情况后,程序会从 switch 跳出,而不是继续执行下一个情况。所以不再需要 break 跳出 switch 。

    可使用 for-in 来迭代字典中的每个元素,提供一对名字来使用每个键值对。

    let interestingNumbers = [
        "Prime": [2, 3, 5, 7, 11, 13],
        "Fibonacci": [1, 1, 2, 3, 5, 8],
        "Square": [1, 4, 9, 16, 25],
    ]
    var largest = 0
    for (kind, numbers) in interestingNumbers {
        for number in numbers {
            if number > largest {
                largest = number
            }
        }
    }
    

    Note

    练习

    添加另一个变量来跟踪哪个种类中的数字最大,也就是最大的数字所在的。

    使用 while 来重复执行代码块直到条件改变。循环的条件可以放在末尾来确保循环至少执行一次。

    var n = 2
    while n < 100 {
        n = n * 2
    }
    n
    
    var m = 2
    do {
        m = m * 2
    } while m < 100
    m
    

    你可以在循环中保持一个索引,通过 ".." 来表示索引范围或明确声明一个初始值、条件、增量。这两个循环做相同的事情:

    var firstForLoop = 0
    for i in 0..3 {
        firstForLoop += i
    }
    firstForLoop
    
    var secondForLoop = 0
    for var i = 0; i < 3; ++i {
        secondForLoop += 1
    }
    secondForLoop
    

    使用 .. 构造范围忽略最高值,而用 ... 构造的范围则包含两个值。

    5   函数与闭包

    使用 func 声明一个函数。调用函数使用他的名字加上小括号中的参数列表。使用 -> 分隔参数的名字和返回值类型。

    func greet(name: String, day: String) -> String {
        return "Hello \(name), today is \(day)."
    }
    greet("Bob", "Tuesday")
    

    Note

    练习

    去掉 day 参数,添加一个参数包含今天的午餐选择。

    使用元组(tuple)来返回多个值。

    func getGasPrices() -> (Double, Double, Double) {
        return (3.59, 3.69, 3.79)
    }
    getGasPrices()
    

    函数可以接受可变参数个数,收集到一个数组中。

    func sumOf(numbers: Int...) -> Int {
        var sum = 0
        for number in numbers {
            sum += number
        }
        return sum
    }
    sumOf()
    sumOf(42, 597, 12)
    

    Note

    练习

    编写一个函数计算其参数的平均值。

    函数可以嵌套。内嵌函数可以访问其定义所在函数的变量。你可以使用内嵌函数来组织代码,避免过长和过于复杂。

    func returnFifteen() -> Int {
        var y = 10
        func add() {
            y += 5
        }
        add()
        return y
    }   //by gashero
    returnFifteen()
    

    函数是第一类型的。这意味着函数可以返回另一个函数。

    func makeIncrementer() -> (Int -> Int) {
        func addOne(number: Int) -> Int {
            return 1 + number
        }
        return addOne
    }
    var increment = makeIncrementer()
    increment(7)
    

    一个函数可以接受其他函数作为参数。

    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)
    

    函数实际是闭包的特殊情况。你可以写一个闭包而无需名字,只需要放在大括号中即可。使用 in 到特定参数和主体的返回值。

    numbers.map({
        (number: Int) -> Int in
        let result = 3 * number
        return result
        })
    

    Note

    练习

    重写一个闭包来对所有奇数返回0。

    编写闭包时有多种选项。当一个闭包的类型是已知时,例如代表回调,你可以忽略其参数和返回值,或两者。单一语句的闭包可以直接返回值。

    numbers.map({number in 3 * number})
    

    你可以通过数字而不是名字来引用一个参数,这对于很短的闭包很有用。一个闭包传递其最后一个参数到函数作为返回值。

    sort([1, 5, 3, 12, 2]) { $0 > $1 }
    

    6   对象与类

    使用 class 可以创建一个类。一个属性的声明则是在类里作为常量或变量声明的,除了是在类的上下文中。方法和函数也是这么写的。

    class Shape {
        var numberOfSides = 0
        func simpleDescription() -> String {
            return "A shape with \(numberOfSides) sides."
        }
    }
    

    Note

    练习

    通过 "let" 添加一个常量属性,以及添加另一个方法能接受参数。

    通过在类名后加小括号来创建类的实例。使用点语法来访问实例的属性和方法。

    var shape = Shape()
    shape.numberOfSides = 7
    var shapeDescription = shape.simpleDescription()
    

    这个版本的 Shape 类有些重要的东西不在:一个构造器来在创建实例时设置类。使用 init 来创建一个。

    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."
        }
    }
    

    注意 self 用来区分 name 属性和 name 参数。构造器的生命跟函数一样,除了会创建类的实例。每个属性都需要赋值,无论在声明里还是在构造器里。

    使用 deinit 来创建一个析构器,来执行对象销毁时的清理工作。

    子类包括其超类的名字,以冒号分隔。在继承标准根类时无需声明,所以你可以忽略超类。

    子类的方法可以通过标记 override 重载超类中的实现,而没有 override 的会被编译器看作是错误。编译器也会检查那些没有被重载的方法。

    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

    练习

    编写另一个 NamedShape 的子类叫做 Circle ,接受半径和名字到其构造器。实现 area 和 describe 方法。

    属性可以有 getter 和 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.perimeter
    triangle.perimeter = 9.9
    triangle.sideLength
    

    在 perimeter 的 setter 中,新的值的名字就是 newValue 。你可以提供一个在 set 之后提供一个不冲突的名字。

    注意 EquilateralTriangle 的构造器有3个不同的步骤:

    1. 设置属性的值
    2. 调用超类的构造器
    3. 改变超类定义的属性的值,添加附加的工作来使用方法、getter、setter也可以在这里

    如果你不需要计算属性,但是仍然要提供在设置值之后执行工作,使用 willSet 和 didSet 。例如,下面的类要保证其三角的边长等于矩形的变长。

    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.sideLength
    triangleAndSquare.triangle.sideLength
    triangleAndSquare.square = Square(sideLength: 50, name: "larger square")
    triangleAndSquare.triangle.sideLength
    

    类的方法与函数有个重要的区别。函数的参数名仅用与函数,但方法的参数名也可以用于调用方法(除了第一个参数)。缺省时,一个方法有一个同名的参数,调用时就是参数本身。你可以指定第二个名字,在方法内部使用。

    class Counter {
        var count: Int = 0
        func incrementBy(amount: Int, numberOfTimes times: Int) {
            count += amount * times
        }
    }
    var counter = Counter()
    counter.incrementBy(2, numberOfTimes: 7)
    

    当与可选值一起工作时,你可以写 "?" 到操作符之前类似于方法属性。如果值在"?"之前就已经是 nil ,所有在 "?" 之后的都会自动忽略,而整个表达式是 nil 。另外,可选值是未包装的,所有 "?" 之后的都作为未包装的值。在两种情况中,整个表达式的值是可选值。

    let optionalSquare: Square? = Square(sideLength: 2.5, name: "optional square")
    let sideLength = optionalSquare?.sideLength
    

    7   枚举与结构

    使用 enum 来创建枚举。有如类和其他命名类型,枚举可以有方法。

    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 gashero
    let aceRawValue = ace.toRaw()
    

    Note

    练习

    编写一个函数比较两个 Rank 的值,通过比较其原始值。

    在如上例子中,原始值的类型是 Int 所以可以只指定第一个原始值。其后的原始值都是按照顺序赋值的。也可以使用字符串或浮点数作为枚举的原始值。

    使用 toRaw 和 fromRaw 函数可以转换原始值和枚举值。

    if let convertedRank = Rank.fromRaw(3) {
        let threeDescription = convertedRank.simpleDescription()
    }
    

    枚举的成员值就是实际值,而不是其他方式写的原始值。实际上,有些情况是原始值,就是你不提供的时候。

    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 gashero
    let heartsDescription = hearts.simpleDescription()
    

    Note

    练习

    添加一个 color 方法到 Suit 并在 spades 和 clubs 时返回 "black" ,并且给 hearts 和 diamounds 返回 "red" 。

    注意上面引用Hearts成员的两种方法:当赋值到 hearts 常量时,枚举成员 Suit.Hearts 通过全名引用,因为常量没有明确的类型。在 switch 中,枚举通过 .Hearts 引用,因为 self 的值是已知的。你可以在任何时候使用方便的方法。

    使用 struct 创建结构体。结构体支持多个与类相同的行为,包括方法和构造器。一大重要的区别是代码之间的传递总是用拷贝(值传递),而类则是传递引用。

    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

    练习

    添加方法到 Card 类来创建一桌的纸牌,每个纸牌都有合并的rank和suit。(就是个打字员的活二,by gashero)。

    一个枚举的实例成员可以拥有实例的值。相同枚举成员实例可以有不同的值。你在创建实例时赋值。指定值和原始值的区别:枚举的原始值与其实例相同,你在定义枚举时提供原始值。

    例如,假设情况需要从服务器获取太阳升起和降落时间。服务器可以响应相同的信息或一些错误信息。

    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)"
    }
    

    Note

    练习

    给 ServerResponse 添加第三种情况来选择。

    注意日出和日落时间实际上来自于对 ServerResponse 的部分匹配来选择的。


    展开全文
  • Swift 编程语言

    2014-06-11 15:37:19
    Swift (苹果于WWDC 2014发布的编程语言)      前言  在这里我认为有必要提一下 Brec Victor 的Inventing on Principle,Swift 编程环境的大部分概念都源自于Brec 这个演讲。  接下来进入正题。  Swift...
  • Swift代码语言教程:在刚刚过去的WWDC2014大会上,苹果公司新发布了一种编程语言...希望苹果Swift编程语言入门教程【中文版】,能助你更迅速掌握好它。 注:本文从苹果官方所发布的书籍《The Swift Programming Lang
  • Swift编程(中文版)

    2020-07-29 14:20:13
    Swift编程(中文版) .
  • Swift编程权威指南(第2版) 虽然有点落后,但是值得一看
  • Swift编程实战 iOS应用开发实例及完整解决方案 pdf 清晰版本
  • 资源名称:Swift编程语言实战苹果iOS应用开发 闪电入门视频教程教程内容:Swift是Apple在WWDC2014所发布的一门编程语言,用来撰写OS X和IOS应用程序[1]。在设计Swift时.就有意和Objective-C共存,Objective-C是...
  • Swift编程语言(Swift 5)

    2020-07-29 14:19:59
    介绍: 《Swift 编程语言》是苹果官方对 Swift 语言做的权威指南,很遗憾苹果公司并没有进行多语言支持。所以我独立发起了这个手册的翻译工作——与其他现存翻译不同的是:它同步更新苹果官方的 Swift 开发者预览版 ...
  • swift 编程权威指南(第二版)完整高清版本,同时有书中自带的学习代码,和总结的学习进度学习要领难点等。
  • Swift编程权威指南第二版 PDF高清版.是一款适合入门级 初级 中级程序员学习Swift的一本书.不管你有没有iOS开发经验均可学习.已有OC经验的 前5章可以跳过 后面实例看着案例需求去自己写 不要照着书敲.没有OC经验的...
  • 也提供了一本将近400页的 The Swift Programming Language(Swift编程语言)。 尽管我没有开发人员账号。没法实际上机练习Swift代码,但这不影响我阅读这本书,以及用铅笔在纸上执行这些小程序。 Apple的东西...
  • Swift编程语言(中文版)(8.8 %)

    千次阅读 2014-06-07 08:48:51
    今天Apple发布了新的编程语言Swift,也提供了一本将近400页的The Swift Programming Language(Swift编程语言)。 虽然我没有开发者账号,没法实际上机练习Swift代码,但这不影响我阅读这本书,以及用铅笔在纸上运行...
  • Swift编程语言教程-中文版两大官方文档汇总 Swift是适用于iOS和OS X应用的全新编程语言,基于C和Objective-C语言,并采用安全的编程模式,更容易、更零活、更有趣。Swift以Cocoa和Cocoa Touch框架为支撑,给...
  • 学习最新swift编程语言 课程目标:学习到手机编程的最新语言 课程特色:源于清华的高品质swift教学 适用人群:适用于学习swift语言的人们 ~第1章 欢迎来到Swift语言的世界 1.1 起源 1.2 什么是Swift...
  • swift优缺点 截至2016年1月 ,iOS的使用设备超过10亿个,它是全球第二大最受欢迎的移动平台。 在某些地区,包括美国,英国和法国,苹果设备的智能手机销量继续超过Android。 这就是为什么如此多的企业将其软件...
  • Apple Swift编程语言入门教程(转)

    千次阅读 2017-11-03 18:42:35
    苹果2014 WWDC中发布了一种新的编程语言--swift。这个语言初一看有点像python一样简洁。看了一下教程,总体上来说,在使用这个语言进行编程时,是比使用OC快很多。开发人员不用再为各种没有用的符号来打很多字符...
1 2 3 4 5 ... 20
收藏数 29,977
精华内容 11,990
关键字:

swift编程