4.0翻译 swift_openstack swift 2.20.0 2.21.0 - CSDN
精华内容
参与话题
  • Swift4.0】属性

    2017-12-28 15:19:36
    翻译能力有限,如有不对的地方,还请见谅!希望对Swift的学习者有所帮助,使用的编写工具:JQNote  InNote(iPhone) 属性是把值和某个类,结构体或者枚举联系在一起。存储型属性存储一个实例的常量和变量...

    翻译能力有限,如有不对的地方,还请见谅!希望对Swift的学习者有所帮助,使用的编写工具:JQNote    InNote(iPhone)


    属性是把值和某个类,结构体或者枚举联系在一起。存储型属性存储一个实例的常量和变量值部分,然而计算型属性会计算出(而不是存储)一个值。类,结构体和枚举都支持计算型属性,而存储型属性只有类和结构体支持。这两种属性通常跟某个类型的实例关联。然而,属性也可以跟类型本身关联起来,这种属性称之为类型属性。另外,你可以定义一个属性观察者来检测该属性值的改变。


    存储属性

    一个存储属性是一个常量或者变量,被存储作为一个类或者结构体实例的一部分。你可以在定义它的时候给它一个缺省值,也可以在初始化方法中设置和修改存储属性的初始化值,即便是该存储属性是常量。如果你创建了一个常量结构体实例,那么就不能修改该实例的属性,即使属性被声明为变量。


    let rangeOfFourItems = FixedLengthRange(firstValue: 0, length: 4)

    // this range represents integer values 0, 1, 2, and 3

    rangeOfFourItems.firstValue = 6

    // this will report an error, even though firstValue is a variable property”


    因为结构体是值类型,当一个结构体实例被声明为常量,那么它的所有属性都不能被改变。但是对于类来说,是引用类型,如果类实例被声明为常量,你还可以改变它的变量属性的。


    懒存储属性

    这种属性直到它第一次被使用才会初始化。在声明存储属性前面加上lazy关键字就表示为懒存储属性。


    你必须总是声明懒存储属性为变量(var),因为直到实例初始化完成之后,它的初始化值可能不能被获取,而常量属性必须总是在实例初始化完成之前有一个值。


    class DataImporter {

        /*DataImporter is a class to import data from an external ”

    “file.

         The class is assumed to take a non-trivial amount of time to initialize.

         */


        var filename = "data.txt"

        // the DataImporter class would provide data importing functionality here

    }

     

    class DataManager {

        lazy var importer = DataImporter()

        var data = [String]()

        // the DataManager class would provide data management functionality here

    }

     

    let manager = DataManager()

    manager.data.append("Some data")

    manager.data.append("Some more data")”


    如上面的例子,因为importer 被声明为一个lazy 属性,DataImporter实例仅仅是当 importer属性第一次被调用获取的时候,才会创建。

    print(manager.importer.filename)

    // the DataImporter instance for the importer property has now been created

    // Prints "data.txt”


    计算型属性

    计算型属性实际上不会存储一个值,相反,它们提供了一个getter和一个可选的setter方法来直接获取或者设置其它属性的值。

    struct Point {

        var x = 0.0, y = 0.0

    }


    struct Size {

        var width = 0.0, height = 0.0

    }


    struct Rect {

        var origin = Point()

        var size = Size()

        var center: Point {

            get {

                let centerX = origin.x + (size.width / 2)

                let centerY = origin.y + (size.height / 2)

                return Point(x: centerX, y: centerY)

            }

            set(newCenter) {

                origin.x = newCenter.x - (size.width / 2)

                origin.y = newCenter.y - (size.height / 2)

            }

        }

    }


    var square = Rect(origin: Point(x: 0.0, y: 0.0),

                      size: Size(width: 10.0, height: 10.0))

    let initialSquareCenter = square.center

    square.center = Point(x: 15.0, y: 15.0)


    只读的计算型属性

    一个计算型的属性,如果只有getter方法,没有setter方法,那就被认为是一个只读的计算属性。你可以声明一个简单的只读计算属性,不需要get关键字:

    struct Cuboid {

        var width = 0.0, height = 0.0, depth = 0.0

        var volume: Double {

            return width * height * depth

        }

    }


    let fourByFiveByTwo = Cuboid(width: 4.0, height: 5.0, depth: 2.0)

    print("the volume of fourByFiveByTwo is \(fourByFiveByTwo.volume)")

    // Prints "the volume of fourByFiveByTwo is 40.0”


    属性观察者

    属性观察者观察和响应一个属性值的改变。当属性值每次被set的时候,观察者都会被调用,即使新的值和当前的值相同。除了lazy属性,你可以将属性观察者添加到任何存储属性:


    >> willSet :值被存储之前调用

    >> didSet :新值被存储之后调用


    当你实现了willSet,它会传递一个新的值作为一个常量参数。你也可以给这个参数特定一个名字。如果你没有写这个参数名,那么默认newValue可以被使用。类似,如果实现了didSet,你也可以特定一个参数名或者使用默认的oldValue。

    class StepCounter {

        var totalSteps: Int = 0 {

            willSet(newTotalSteps) {

                print("About to set totalSteps to \(newTotalSteps)")

            }

            didSet {

                if totalSteps > oldValue  {

                    print("Added \(totalSteps - oldValue) steps")

                }

            }

        }

    }


    类型属性

    实例属性属于某个类型的实例,每次在创建实例的时候,它有自己的一系列属性。与其它实例是分开的。

    你也可以定义属于类型自己的属性,而不属于每个该类型的实例。类型属性只会拷贝一次,无论该类型被创建了多少个实例。

    不像存储实例属性,存储类型属性必须赋一个缺省值,这是因为类型自己没有一个初始化器可以在初始化的时候给类型属性设置值。

    定义一个类型属性,使用staic关键字:

    struct SomeStructure {

        static var storedTypeProperty = "Some value."

        static var computedTypeProperty: Int {

            return 1

        }

    }

    enum SomeEnumeration {

        static var storedTypeProperty = "Some value."

        static var computedTypeProperty: Int {

            return 6

        }

    }

    class SomeClass {

        static var storedTypeProperty = "Some value."

        static var computedTypeProperty: Int {

            return 27

        }

        class var overrideableComputedTypeProperty: Int {

             return 107

        }

    }


    获取和设置类型属性:

    print(SomeStructure.storedTypeProperty)

    // Prints "Some value."

    SomeStructure.storedTypeProperty = "Another value."

    print(SomeStructure.storedTypeProperty)

    // Prints "Another value."

    print(SomeEnumeration.computedTypeProperty)

    // Prints "6"

    print(SomeClass.computedTypeProperty)

    // Prints "27”



    展开全文
  • Swift 4.0 更新合集、新功能汇总

    万次阅读 2017-06-10 11:48:24
    Swift 4是苹果计划于2017年秋季推出的最新版本,其主要重点是提供与Swift 3代码的源兼容性,并努力实现ABI稳定性。 本文重点介绍对Swift的更改将对您的代码产生最大的影响。 而且,让我们开始吧!

    本文由陈云峰翻译,转载请注明。

    注意:本教程将使用Swift 4版本捆绑在Xcode 9 beta 1中。

    Swift 4

    Swift 4是苹果计划于2017年秋季推出的最新版本,其主要重点是提供与Swift 3代码的源兼容性,并努力实现ABI稳定性。

    本文重点介绍对Swift的更改将对您的代码产生最大的影响。 而且,让我们开始吧!

    入门

    Swift 4包含在Xcode 9中。您可以从Apple的开发者门户下载最新版本的Xcode 9(您必须拥有一个活跃的开发者帐户)。 每个Xcode测试版将在发布时捆绑最新的Swift 4快照。

    在阅读时,您会注意到[SE-xxxx]格式的链接。 这些链接将带您到相关的Swift Evolution提案。 如果您想了解有关任何主题的更多信息,请务必查看。

    我建议您在操场上尝试每个Swift 4功能或更新。 这将有助于巩固您的头脑中的知识,并使您有能力深入了解每个主题。 试图扩大/打破他们的例子来玩弄这些例子。 玩得开心!

    注意:本文将针对每个Xcode测试版进行更新。 如果您使用不同的Swift快照,这里的代码不能保证工作。

    迁移到Swift 4

    从Swift 3迁移到4将比从2.2到3更麻烦。一般来说, 大多数变化是相加的,不应该需要大量的个人感觉。 因此,Swift迁移工具将为您处理大部分更改。

    Xcode 9同时支持Swift 4以及Swift 3.2中的Swift 3中间版本。 您的项目中的每个目标可以是Swift 3.2或Swift 4,如果需要,您可以逐个迁移。 然而,转换为Swift 3.2并不是完全免费的 – 您可能需要更新代码部分才能与新SDK兼容,并且由于Swift尚未ABI稳定,因此您将需要使用Xcode 9重新编译依赖项。

    当您准备迁移到Swift 4时,Xcode再次提供了一个迁移工具来帮助您。 在Xcode中,您可以导航到编辑/转换/到当前Swift语法…以启动转换工具。

    选择要转换的目标后,Xcode将提示您对Objective-C推理的偏好。 选择推荐的选项通过限制引用来减少二进制大小(有关此主题的更多信息,请查看下面的限制@objc推断 )

    为了更好地了解您的代码中期望的更改,我们将首先介绍Swift 4中的API更改。

    API更改

    在跳转到Swift 4中介绍的补充之前,我们先来看看现有API所做的更改/改进。

    字符串

    String在Swift 4中获得了很多很好的爱。这个提案包含很多变化,所以让我们分解最大的。 [SE-0163] :

    如果你感觉怀旧,字符串再次收藏,就像他们是Swift 2.0之前一样。 此更改消除了对String上的String数组的需求。 您现在可以直接在String对象上进行迭代:

    let galaxy = "Milky Way "
    for char in galaxy {
      print(char)
    }

    是!

    您不仅可以通过String逻辑迭代,还可以从SequenceCollection获取所有的响铃和口哨:

    galaxy.count       // 11
    galaxy.isEmpty     // false
    galaxy.dropFirst() // "ilky Way "
    String(galaxy.reversed()) // " yaW ykliM"
    
    // Filter out any none ASCII characters
    galaxy.filter { char in
      let isASCII = char.unicodeScalars.reduce(true, { $0 && $1.isASCII })
      return isASCII
    } // "Milky Way "

    上面的ASCII示例显示了对Character 。 您现在可以直接从Character访问Character 。 以前,您需要实例化一个新的String [SE-0178] 。

    另外还有一个是StringProtocol 。 它声明了以前在String上声明的大部分功能。 这种变化的原因是改善切片如何工作。 Swift 4添加了Substring类型,用于引用String上的子序列。

    StringSubstring实现了StringProtocol使它们具有几乎相同的功能:

    // Grab a subsequence of String
    let endIndex = galaxy.index(galaxy.startIndex, offsetBy: 3)
    var milkSubstring = galaxy[galaxy.startIndex...endIndex]   // "Milk"
    type(of: milkSubstring)   // Substring.Type
    
    // Concatenate a String onto a Substring
    milkSubstring += ""     // "Milk"
    
    // Create a String from a Substring
    let milkString = String(milkSubstring) // "Milk"

    另一个很大的改进是String如何解释图形集合。 此解决方案来自于Unicode 9的改编。以前,由多个代码点组成的Unicode字符会导致count大于1.常见的情况是具有所选肤色的表情符号。 以下是几个示例,显示前后行为:

    "‍".count // Now: 1, Before: 2
    "".count // Now: 1, Before: 2
    "‍❤️‍‍".count // Now: 1, Before, 4

    这只是“ 字符串宣言”中提到的更改的一个子集。 您可以阅读有关将来希望看到的原始动机和提出的解决方案。

    词典和集合

    至于Collection类型, SetDictionary并不总是最直观的。 幸运的是,斯威夫特队给了他们一些非常需要的爱[SE-0165] 。

    基于序列的初始化
    列表首先是从一系列键值对(元组)创建一个字典的能力:

    let nearestStarNames = ["Proxima Centauri", "Alpha Centauri A", "Alpha Centauri B", "Barnard's Star", "Wolf 359"]
    let nearestStarDistances = [4.24, 4.37, 4.37, 5.96, 7.78]
    
    // Dictionary from sequence of keys-values
    let starDistanceDict = Dictionary(uniqueKeysWithValues: zip(nearestStarNames, nearestStarDistances)) 
    // ["Wolf 359": 7.78, "Alpha Centauri B": 4.37, "Proxima Centauri": 4.24, "Alpha Centauri A": 4.37, "Barnard's Star": 5.96]

    重复键处理
    您现在可以使用重复的键来处理初始化字典的任何方式。 这有助于避免覆盖键值对,而不会有任何问题:

    // Random vote of people's favorite stars
    let favoriteStarVotes = ["Alpha Centauri A", "Wolf 359", "Alpha Centauri A", "Barnard's Star"]
    
    // Merging keys with closure for conflicts
    let mergedKeysAndValues = Dictionary(zip(favoriteStarVotes, repeatElement(1, count: favoriteStarVotes.count)), uniquingKeysWith: +) // ["Barnard's Star": 1, "Alpha Centauri A": 2, "Wolf 359": 1]

    上面的代码使用zip和速记+来通过添加两个冲突的值来解析重复的键。

    注意:如果您不熟悉zip ,您可以在Apple的Swift文档中快速了解它

    过滤
    DictionarySet现在都可以将结果过滤到原始类型的新对象中:

    // Filtering results into dictionary rather than array of tuples
    let closeStars = starDistanceDict.filter { $0.value < 5.0 }
    closeStars // Dictionary: ["Proxima Centauri": 4.24, "Alpha Centauri A": 4.37, "Alpha Centauri B": 4.37]

    字典映射
    Dictionary获得了一个非常有用的方法来直接映射其值:

    // Mapping values directly resulting in a dictionary
    let mappedCloseStars = closeStars.mapValues { "\($0)" }
    mappedCloseStars // ["Proxima Centauri": "4.24", "Alpha Centauri A": "4.37", "Alpha Centauri B": "4.37"]

    字典默认值
    在Dictionary上访问某个值时,常见的做法是使用nil coalescing运算符给出默认值,以防数值为nil 。 在Swift 4中,这变得更加清洁,并允许您在线突变中做一些真棒:

    // Subscript with a default value
    let siriusDistance = mappedCloseStars["Wolf 359", default: "unknown"] // "unknown"
    
    // Subscript with a default value used for mutating
    var starWordsCount: [String: Int] = [:]
    for starName in nearestStarNames {
      let numWords = starName.split(separator: " ").count
      starWordsCount[starName, default: 0] += numWords // Amazing 
    }
    starWordsCount // ["Wolf 359": 2, "Alpha Centauri B": 3, "Proxima Centauri": 2, "Alpha Centauri A": 3, "Barnard's Star": 2]

    以前,这种类型的突变将需要在一个blo肿的if-let语句中包装。 在Swift 4中,可能是一条线!

    字典分组
    另一个令人惊讶的有用的补充是从Sequence Dictionary并将它们分组到桶中的能力:

    // Grouping sequences by computed key
    let starsByFirstLetter = Dictionary(grouping: nearestStarNames) { $0.first! }
    
    // ["B": ["Barnard's Star"], "A": ["Alpha Centauri A", "Alpha Centauri B"], "W": ["Wolf 359"], "P": ["Proxima Centauri"]]

    当通过特定模式对数据进行分组时,这很方便。

    预留容量
    SequenceDictionary现在都具有明确保留容量的能力。

    // Improved Set/Dictionary capacity reservation
    starWordsCount.capacity  // 6
    starWordsCount.reserveCapacity(20) // reserves at _least_ 20 elements of capacity
    starWordsCount.capacity // 24
    

    这些类型的重新分配可能是一项昂贵的任务。 使用reserveCapacity(_:)是一个简单的方法来提高性能,当您了解需要存储多少数据时。

    这是一大堆信息,所以绝对检查这两种类型,并寻找使用这些添加剂来调整代码的方法。

    私有访问修饰符

    Swift 3的一个元素,一些不太喜欢的是添加fileprivate 。 从理论上讲,这是非常好的,但实际上它的使用往往会令人困惑。 目标是在成员本身中使用private的,并且在您想要在同一文件中的成员共享访问的情况下很少使用fileprivate 。

    问题是Swift鼓励使用扩展将代码分解成逻辑组。 扩展被认为在原始成员声明范围之外,这导致对fileprivate的广泛需求。

    Swift 4通过在类型和所述类型的任何扩展之间共享相同的访问控制范围来实现原始意图。 这只适用于相同的源文件[SE-0169] :

    struct SpaceCraft {
      private let warpCode: String
    
      init(warpCode: String) {
        self.warpCode = warpCode
      }
    }
    
    extension SpaceCraft {
      func goToWarpSpeed(warpCode: String) {
        if warpCode == self.warpCode { // Error in Swift 3 unless warpCode is fileprivate
          print("Do it Scotty!")
        }
      }
    }
    
    let enterprise = SpaceCraft(warpCode: "KirkIsCool")
    //enterprise.warpCode  // error: 'warpCode' is inaccessible due to 'private' protection level
    enterprise.goToWarpSpeed(warpCode: "KirkIsCool") // "Do it Scotty!"

    这允许您使用fileprivate作为其预期目的,而不是作为带状编码组织。

    新增API

    现在让我们来看看Swift 4的新功能。这些更改不应该打破你现有的代码,因为它们是简单的加法。

    归档和序列化

    谷物人

    到目前为止,在Swift中,为了序列化和归档您的自定义类型,您必须跳过一些环。对于class类型,您需要对NSObject进行子类化并实现NSCoding协议。

    structenum这样的值类型需要许多hacks,例如创建一个可以扩展NSObjectNSCoding的子对象。

    Swift 4通过将序列化到所有三种Swift类型[SE-0166]来解决这个问题:

    struct CuriosityLog: Codable {
      enum Discovery: String, Codable {
        case rock, water, martian
      }
    
      var sol: Int
      var discoveries: [Discovery]
    }
    
    // Create a log entry for Mars sol 42
    let logSol42 = CuriosityLog(sol: 42, discoveries: [.rock, .rock, .rock, .rock])

    在这个例子中,您可以看到,使Swift类型可Encodable和可Decodable所需的唯一Decodable是实现可编Codable协议。 如果所有属性都是Codable ,则协议实现由编译器自动生成。

    本文由陈云峰翻译,转载请注明。

    要实际编码对象,您需要将其传递给编码器。 Swift编码器正在Swift 4中积极实施。每个编码器根据不同的方案对您的对象进行编码[SE-0167] ( 注意:此提案的一部分仍在开发中):

    let jsonEncoder = JSONEncoder() // One currently available encoder
    
    // Encode the data
    let jsonData = try jsonEncoder.encode(logSol42)
    // Create a String from the data
    let jsonString = String(data: jsonData, encoding: .utf8) // "{"sol":42,"discoveries":["rock","rock","rock","rock"]}"

    这采取了一个对象,并自动将其编码为JSON对象。 确保查看JSONEncoder暴露的属性来自定义其输出。

    该过程的最后一部分是将数据解码为具体对象:

    let jsonDecoder = JSONDecoder() // Pair decoder to JSONEncoder
    
    // Attempt to decode the data to a CuriosityLog object
    let decodedLog = try jsonDecoder.decode(CuriosityLog.self, from: jsonData)
    decodedLog.sol         // 42
    decodedLog.discoveries // [rock, rock, rock, rock]

    使用Swift 4编码/解码,您可以在Swift中获得预期的类型安全性,而不依赖于@objc协议的开销和限制。

    键值编码

    到目前为止,您可以参考函数而不调用它们,因为函数是Swift中的闭包。 你不能做的是保持对属性的引用,而不实际访问属性保存的底层数据。

    对Swift 4来说,令人兴奋的补充是能够引用类型的关键路径来获取/设置实例的基础值[SE-0161] :

    struct Lightsaber {
      enum Color {
        case blue, green, red
      }
      let color: Color
    }
    
    class ForceUser {
      var name: String
      var lightsaber: Lightsaber
      var master: ForceUser?
    
      init(name: String, lightsaber: Lightsaber, master: ForceUser? = nil) {
        self.name = name
        self.lightsaber = lightsaber
        self.master = master
      }
    }
    
    let sidious = ForceUser(name: "Darth Sidious", lightsaber: Lightsaber(color: .red))
    let obiwan = ForceUser(name: "Obi-Wan Kenobi", lightsaber: Lightsaber(color: .blue))
    let anakin = ForceUser(name: "Anakin Skywalker", lightsaber: Lightsaber(color: .blue), master: obiwan)

    在这里,您将通过设置他们的名字,光剑和主人来创建强制用户的几个实例。 要创建一个关键路径,您只需使用一个反斜杠后跟您感兴趣的属性:

    // Create reference to the ForceUser.name key path
    let nameKeyPath = \ForceUser.name
    
    // Access the value from key path on instance
    let obiwanName = obiwan[keyPath: nameKeyPath]  // "Obi-Wan Kenobi"

    在这种情况下,您正在为ForceUsername属性创建一个关键路径。 然后,通过将其传递给新的下标keyPath来使用此键路径。 默认情况下,此下标现在可用于每种类型。

    以下是使用关键路径深入到子对象,设置属性和构建关键路径引用的更多示例:

    // Use keypath directly inline and to drill down to sub objects
    let anakinSaberColor = anakin[keyPath: \ForceUser.lightsaber.color]  // blue
    
    // Access a property on the object returned by key path
    let masterKeyPath = \ForceUser.master
    let anakinMasterName = anakin[keyPath: masterKeyPath]?.name  // "Obi-Wan Kenobi"
    
    // Change Anakin to the dark side using key path as a setter
    anakin[keyPath: masterKeyPath] = sidious
    anakin.master?.name // Darth Sidious
    
    // Note: not currently working, but works in some situations
    // Append a key path to an existing path
    //let masterNameKeyPath = masterKeyPath.appending(path: \ForceUser.name)
    //anakin[keyPath: masterKeyPath] // "Darth Sidious"

    Swift的关键路径的美丽在于它们是强类型的! 没有更多的Objective-C字符串风格混乱!

    多行字符串文字

    许多编程语言的一个非常常见的特征是能够创建多行字符串文字。 Swift 4通过在三个引号[SE-0168]中包装文本来添加这个简单而有用的语法:

    let star = "⭐️"
    let introString = """
      A long time ago in a galaxy far,
      far away....
    
      You could write multi-lined strings
      without "escaping" single quotes.
    
      The indentation of the closing quotes
           below deside where the text line
      begins.
    
      You can even dynamically add values
      from properties: \(star)
      """
    print(introString) // prints the string exactly as written above with the value of star

    这在构建XML / JSON消息或构建长格式的文本以在UI中显示时非常有用。

    单面范围

    为了减少冗长度并提高可读性,标准库现在可以使用单面范围[SE-0172]来推断起始和终点索引。

    派上用场的一种方法是创建一个从索引到集合的开始或结束索引的范围:

    / Collection Subscript
    var planets = ["Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune"]
    let outsideAsteroidBelt = planets[4...] // Before: planets[4..<planets.endIndex]
    let firstThree = planets[..<4]          // Before: planets[planets.startIndex..<4]

    如您所见,单面范围减少了明确指定开始索引或结束索引的需要。

    无限序列
    当起始索引为可数类型时,它们还允许您定义无限Sequence :

    // Infinite range: 1...infinity
    var numberedPlanets = Array(zip(1..., planets))
    print(numberedPlanets) // [(1, "Mercury"), (2, "Venus"), ..., (8, "Neptune")]
    
    planets.append("Pluto")
    numberedPlanets = Array(zip(1..., planets))
    print(numberedPlanets) // [(1, "Mercury"), (2, "Venus"), ..., (9, "Pluto")]

    模式匹配
    单面范围的另一个很好的用途是模式匹配:

    // Pattern matching
    
    func temperature(planetNumber: Int) {
      switch planetNumber {
      case ...2: // anything less than or equal to 2
        print("Too hot")
      case 4...: // anything greater than or equal to 4
        print("Too cold")
      default:
        print("Justtttt right")
      }
    }
    
    temperature(planetNumber: 3) // Earth

    通用下标

    下标是使数据类型以简洁方式可访问的重要组成部分。 为了提高其有用性,下标现在可以是通用的[SE-0148] :

    struct GenericDictionary<Key: Hashable, Value> {
      private var data: [Key: Value]
    
      init(data: [Key: Value]) {
        self.data = data
      }
    
      subscript<T>(key: Key) -> T? {
        return data[key] as? T
      }
    }

    在这个例子中,返回类型是通用的。 你可以使用这个通用的下标,如下所示:

    // Dictionary of type: [String: Any]
    var earthData = GenericDictionary(data: ["name": "Earth", "population": 7500000000, "moons": 1])
    
    // Automatically infers return type without "as? String"
    let name: String? = earthData["name"]
    
    // Automatically infers return type without "as? Int"
    let population: Int? = earthData["population"]

    返回类型不仅可以是通用的,而且实际的下标类型也可以是通用的:

    extension GenericDictionary {
      subscript<Keys: Sequence>(keys: Keys) -> [Value] where Keys.Iterator.Element == Key {
        var values: [Value] = []
        for key in keys {
          if let value = data[key] {
            values.append(value)
          }
        }
        return values
      }
    }
    
    // Array subscript value
    let nameAndMoons = earthData[["moons", "name"]]        // [1, "Earth"]
    // Set subscript value
    let nameAndMoons2 = earthData[Set(["moons", "name"])]  // [1, "Earth"]

    在这个例子中,你可以看到,传递两个不同的Sequence类型( ArraySet )会导致一个数组的各自的值。

    更多更新

    它处理了Swift 4中最大的变化。现在让我们通过一些较小的位和块来更快速地进行一些。

    MutableCollection.swapAt(_:_ )

    MutableCollection现在具有mutate方法swapAt(_:_:) ,就像它的声音一样; 交换给定索引值[SE-0173] :

    // Very basic bubble sort with an in-place swap
    func bubbleSort<T: Comparable>(_ array: [T]) -> [T] {
      var sortedArray = array
      for i in 0..<sortedArray.count - 1 {
        for j in 1..<sortedArray.count {
          if sortedArray[j-1] > sortedArray[j] {
            sortedArray.swapAt(j-1, j) // New MutableCollection method
          }
        }
      }
      return sortedArray
    }
    
    bubbleSort([4, 3, 2, 1, 0]) // [0, 1, 2, 3, 4]

    相关类型限制

    您现在可以使用where子句来限制关联类型[SE-0142] :

    protocol MyProtocol {
      associatedtype Element
      associatedtype SubSequence : Sequence where SubSequence.Iterator.Element == Iterator.Element
    }

    使用协议约束,许多associatedtype声明可以直接约束其值,而不必跳过环。

    类和协议存在

    最终将其从Objective-C转换为Swift的功能是定义符合类和一组协议的类型的能力[SE-0156] :

    protocol MyProtocol { }
    class View { }
    class ViewSubclass: View, MyProtocol { }
    
    class MyClass {
      var delegate: (View & MyProtocol)?
    }
    
    let myClass = MyClass()
    //myClass.delegate = View() // error: cannot assign value of type 'View' to type '(View & MyProtocol)?'
    myClass.delegate = ViewSubclass()

    限制@objc推论

    要将Objective-C或Swift API公开,请使用@objc编译器属性。 在许多情况下,Swift编译器为您推断出这一点。 质量推理的三个主要问题是:

      1. 潜在的二进制大小显着增加
      2. 知道何时@objc

    被推断不明显

    1. 不经意间创建Objective-C选择器碰撞的机会增加。

    Swift 4通过限制@objc [SE-0160]的推论来解决这个问题。 这意味着在需要Objective-C的完整动态调度功能的情况下,您需要使用@objc 。

    您需要进行这些更改的几个示例包括private方法, dynamic声明和NSObject子类的任何方法。

    NSNumber桥接

    NSNumber和Swift数字之间已经有很多时髦的行为,这些行为一直困扰着语言太久。 幸运的是,Swift 4压缩了这些错误[SE-0170] 。

    以下是一个示例演示示例:

    let n = NSNumber(value: 999)
    let v = n as? UInt8 // Swift 4: nil, Swift 3: 231

    Swift 3中的奇怪行为表明,如果数字溢出,则从0开始。在此示例中,999%2 ^ 8 = 231。

    Swift 4通过强制可选的转换来解决问题,只有当数字可以在包含类型中被安全地表达时才返回值。

    Swift包管理器

    在过去几个月里,Swift Package Manager已经有了一些更新。 一些最大的变化包括:

    • 从分支或提交哈希采购依赖关系
    • 更多控制可接受的包版本
    • 用更为常见的解决方案替代非直观的钉扎命令
    • 能够定义用于编译的Swift版本
    • 指定每个目标的源文件的位置

    这些都是获得SPM所需要的重大步骤。 SPM还有很长的路要走,但是我们可以通过保持积极的建议来帮助形成一个。

    有关最近解决的提案的全面了解,请查看“ Swift 4软件包管理器更新” 。

    从哪里走?

    还在举行视频
    想要更快学习吗?节省时间与我们的视频课程

    Swift语言多年来一直在增长和成熟。 提案过程和社区参与使得跟踪管道中出现的变化非常容易。 它也使东方任何一个人直接影响演变。

    随着Swift 4中的这些变化,我们终于到了一个ABI稳定性就在拐角处的地方。 升级Swift版本的痛苦越来越小。 构建性能和工具大大提高。 在苹果生态系统之外使用Swift变得越来越可行。 并且想一想,我们可能只是从一个直观的实现中完全重写String的一些;]。

    斯威夫特还有更多的东西。 要保持最新的所有更改,请确保查看以下资源:

    你对Swift 4有什么想法? 你最喜欢的变化是什么? 你还想从语言中看到什么? 你有没有找到新的和令人兴奋的东西,这里没有涵盖? 让我们在下面的评论中知道!

    本文由陈云峰翻译,转载请注明。原文地址

    展开全文
  • 翻译能力有限,如有不对的地方,还请见谅!希望对Swift的学习者有所帮助,使用的编写工具:JQNote 常量和变量关联一个名称(比如:maximumNumberOfLoginAttempts 和 welcomeMessage)和一个特殊类型的值(比如:...

    翻译能力有限,如有不对的地方,还请见谅!希望对Swift的学习者有所帮助微笑,使用的编写工具:JQNote


    常量和变量关联一个名称(比如:maximumNumberOfLoginAttempts 和 welcomeMessage)和一个特殊类型的值(比如:数字10和字符串“Hello”)。一个常量一旦被赋值后就不能再改变,一个变量可以再次被赋予不同的值。


    声明常量和变量

    常量和变量在使用前必须要声明。你可以使用关键字let来声明一个常量,使用关键字var来声明一个变量。下面是一个如何声明变量和常量的例子:


    let maximumNumberOfLoginAttempts = 10


    var currentLoginAttempt = 0


    这段代码表示:“声明了一个新的常量maximumNumberOfLoginAttempts,并且给它赋值10. 然后声明了一个新的变量currentLoginAttempt,并且设置了一个初始化的值0.” 在这个例子中,最大的登录次数被声明为一个常量,因为最大值不会再改变。当前登录的次数被声明为一个变量,是因为这个值在每次尝试登录失败后必须增加。你可以在一行声明多个变量或者常量,用逗号隔开:


    var x = 0.0, y = 0.0,z =0.0


    【注意】 如果代码中一个存储值不会发生改变,那么总是使用关键字let声明它为常量,如果存储值需要被改变,那么就使用变量。


    类型注释

    当你声明一个常量或者变量时,为了该常量或者变量可以存储值的类型更清晰明确,你可以这样添加一个类型注释:在变量或者常量名称后添加一个冒号,空格,然后再加上类型名称。下面的例子为一个变量welcomeMessage提供了一个类型注释,表示该变量可以存储String类型的值:


    var welcomeMessageString


    这段代码表示:“声明了一个String类型的变量welcomeMessage”,这意味着“可以存储任何String类型的值”。可以把它看作是可以存储的“数据的类型”(或者“类似的数据类型”)。现在变量welcomeMessage可以被设置任何字符串值:welcomeMessage=“Hello”。你可以在一行定义多个相同类型的变量,用逗号隔开,只在最后一个变量名称后添加一个单独的类型注释:


    var red,green,blue: Double


    【注意】 很少需要在实际中编写类型注释,如果你在定义一个常量或者变量的时候给它设置了初始化值,Swift总是会自动推断出该变量或常量的类型。在后续的类型安全和类型推断中会有介绍。在上面的例子中,welcomeMessage没有设置初始化值,因此它的类型就是特别声明的类型注释String,而不是根据初始化值推断的类型。


    命名常量和变量

    常量和变量的名称可以包含几乎任何字符,包括Unicode字符:


    letπ =3.14159

    let你好 ="你好世界"

    常量和变量名不能包含空格字符、数学符号、箭头、私有(或无效)Unicode代码,或者行-和画的字符。也不能以数字开头,尽管数字可能被包括在名字的其他地方。一旦你声明了一个确定类型的常量或者变量,就不能再次使用相同的名称来声明它,或者存储一个不同类型的值给它。也不能把一个常量变为为变量,或者把一个变量变为常量。


    【注意】 如果你使用了与Swift关键字一样的名称来命名一个常量或者变量,用引号(`)把该关键字括起来。然而,尽量避免这样使用,除非你别无选择。


    打印常量和变量

    你可以打印一个常量或者变量的值,通过print(_:separator:terminator:)方法:


    print(friendlyWelcome)   


    print(_:separator:terminator:)是一个全局函数,可以打印一个或多个值到合适的输出端。例如,在Xode中,print(_:separator:terminator:)函数打印它的输出到“console”面板中。separator和terminator参数有默认值,因此调用的时候,可以忽略它们。缺省的,该函数通过添加换行符来终止一行的打印,如果没有换行符,传一个空字符串给terminator参数,例如:print(someValue, terminator: “”)。


    Swift使用字符串插值来包含一个变量或者常量名称作为一个长字符串中的占位符,提示swift用该常量或者变量的值来替换它。如下:


    var friendlyWelcome = "Bonjour!"


    print("The current value of friendlyWelcome is \(friendlyWelcome)")




    展开全文
  • 该文章翻译自apple官方文档:The Swift Programming Language(Swift 4.1)Swift 4.0 版本相对于前面几个版本来说,已经比较稳定,也终于可以利用下班时间关注和学习它了,鉴于官方文档是英文的,自己翻译过后也需要...

    该文章翻译自apple官方文档:The Swift Programming Language(Swift 4.1)

    Swift 4.0 版本相对于前面几个版本来说,已经比较稳定,也终于可以利用下班时间关注和学习它了,鉴于官方文档是英文的,自己翻译过后也需要记录下来,那就一起分享吧,一定有理解不充分和不足的部分,请斧正!

    既然不知从哪里开始合适,那就一页页来吧~

    About Swift

    Swift is a fantastic way to write software, whether it’s for phones, desktops, servers, or anything else that runs code. It’s a safe, fast, and interactive programming language that combines the best in modern language thinking with wisdom from the wider Apple engineering culture and the diverse contributions from its open-source community. The compiler is optimized for performance and the language is optimized for development, without compromising on either.

    Swift is friendly to new programmers. It’s an industrial-quality programming language that’s as expressive and enjoyable as a scripting language. Writing Swift code in a playground lets you experiment with code and see the results immediately, without the overhead of building and running an app.

    Swift defines away large classes of common programming errors by adopting modern programming patterns:

    • Variables are always initialized before use.

    • Array indices are checked for out-of-bounds errors.

    • Integers are checked for overflow.

    • Optionals ensure that nil values are handled explicitly.

    • Memory is managed automatically.

    • Error handling allows controlled recovery from unexpected failures.

    Swift code is compiled and optimized to get the most out of modern hardware. The syntax and standard library have been designed based on the guiding principle that the obvious way to write your code should also perform the best. Its combination of safety and speed make Swift an excellent choice for everything from “Hello, world!” to an entire operating system.

    Swift combines powerful type inference and pattern matching with a modern, lightweight syntax, allowing complex ideas to be expressed in a clear and concise manner. As a result, code is not just easier to write, but easier to read and maintain as well.

    Swift has been years in the making, and it continues 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 是一门写软件很好用的语言,不管是对于手机端,前端,后台还是任何一个可以运行代码的平台,它都是一门安全,快速,能相互影响的编程语言,它结合了最好的现代化语言思维和来自更广的苹果工程文化的智慧以及来自开源社区的多种多样的贡献。这编译器在性能方面做了优化,并且这语言在开发上做了优化,不妥协。

    Swift 对于初学者是很友好的,是一门既满足工业标准又脚本语言一样充满表现力趣味编程语言

    Swift通过接受现代化编程模式定义了大量的常用的编程错误的类

             变量在用之前要被初始化

             检查数组时候越界

             检查整数是否溢出

             确保nil 明确地被处理过

             自动管理内存

             错误处理允许从异常失败中控制恢复。

    Swift 代码充分利用现代硬件编译和优化。它的语法和标准库是基于‘写代码很显然的方式也应该运行的最好’的指导原则设计的。

    安全和快速的结合使得Swift 无论从最简单的‘hello world’还是对于开发整个操作系统,都成为一个杰出的选择

    Swift 结合了强大的类型推断和模式匹配与现代的,轻量级的语法,使复杂的想法,以明确和简明的方式表达。因此,代码不仅容易编写,而且更易于阅读和维护。

    Swift 已经发展多年,并且在继续发展新的特点和功能。我们的目标远大,我们已经迫不及待地想看看你能用它创造出什么了。




    展开全文
  • Swift4.0】基础部分

    2017-12-04 13:52:37
    翻译能力有限,如有不对的地方,还请见谅!希望对Swift的学习者有所帮助,使用的编写工具:JQNote Swift是一门新的编程语言,用于iOS,macOS,watchOS以及tvOS系统平台上应用程序的开发。尽管如此,如果有C和...
  • Swift4.0新特性之String、Array和Dictionary 推荐: Swift 编程语言 原文链接: What’s New in Swift 4? Guards翻译组: 中文地址 Swift 4是苹果计划在2017年秋季推出的最新版本,值得关注的是其提供了与Swift...
  • Swift 是苹果遵循 Apache 开源授权协议开源的一门编程语言 Swift 3 源代码不兼容旧版本,主要是因为 SE-0005 和 SE-0006 的改进,这些改进不仅影响 Standard Library APIs 命名,还会完全改变 Objective-C APIs ...
  • 该文章翻译自apple官方文档:The Swift Programming Language(Swift 5.0)   原文: This book describes Swift 5, the default version of Swift that’s included in Xcode 10.2. You can use Xcode 10.2 to ...
  • Swift4.0】可选类型

    2017-12-18 18:34:16
    在一个值可能缺失的情况下,你可以使用可选类型。一个可选类型代表两种可能:要么有一个值,并且你可以展开获取该可选类型的值。要么根本没有值。 可选的概念在C和Objective-C语言中是不存在。...
  • 该文章翻译自apple官方文档:The Swift Programming Language(Swift 4.1) A Swift Tour -- 一个Swift 旅行 Tradition suggests that the first program in a new language should print the words “Hello, world!...
  • 关于 Swift Swift 是一种新的编程语言,用于编写 iOS 和 OS X 应用程序。Swift 结合了 C 和 Objective-C 的优点并且不受C的兼容性的限制。Swift 使用安全的编程模式并添加了很多新特性,这将使编程更简单,扩展性更...
  • Swift4.0】类和结构体

    千次阅读 2017-12-28 15:23:00
    翻译能力有限,如有不对的地方,还请见谅!希望对Swift的学习者有所帮助,使用的编写工具:JQNote InNote(iPhone) 存储属性 一个存储属性是一个常量或者变量,被存储作为一个类或者结构体实例的一部分。...
  • ios -- 教你如何轻松学习Swift语法

    千次阅读 2016-08-21 17:44:37
    目前随着公司开发模式的变更,swift也显得越发重要,相对来说,swift语言更加简洁,严谨.但对于我来说,感觉swift细节的处理很繁琐,可能是还没适应的缘故吧.基本每写一句代码,都要对变量的数据类型进行判断,还要进行强转...
  • Swift 是一门类型安全的语言。鼓励程序员在代码中清楚明确值的类型。如果代码中使用一个字符串String,那么你不能错误的传递一个整型Int给它。因为Swift是类型安全的,它会在代码编译的时候做类型检查,并且把所有不...
  • iOS开发之swift资料大全

    千次阅读 2017-09-18 17:46:06
    版本:Swift github排名 https://github.com/trending,github搜索:https://github.com/search 主要工作说明:  1. 将Swift从Objective-C混合的md文件中抽出(正在进行…) 使用方法:根据目录关键字...
  • 1. 代码格式 1.1 使用四个空格进行缩进。1.2 每行最多160个字符,这样可以避免一行过长。 (Xcode->Preferences->Text Editing->Page guide at column: 设置成160即可)1.3 确保每个文件结尾都有空白行。...
  • 如何在Ubuntu 16.04上安装Swift和Vapor

    千次阅读 2018-02-01 11:34:08
    翻译自:How to Install Swift and Vapor on Ubuntu 16.04 介绍 Swift是Apple开发的一种编程语言,特点是快,安全和现代化,它有一个支持语言的庞大社区。Swift主要用于开发iOS和Mac OS应用程序,但从Swift 3开始...
  • Swift学习之路1

    2018-06-03 22:38:07
    自己算是半个果粉吧,几年前看到Apple发布...语言的基础学习:http://www.swift51.com/swift4.0/ 中文版本iOS学习资源:2本经典入门书,国内有针对性的翻译版:精通iOS开发第8版,英文最新版,作者准备不再更新,...
  • Dictionary是一个字典,存储的是键值对,也是无序的。每一个值对应唯一的key。写作Dictionary, 其中key是Dictionary中一个键的类型,Value是Dictionary中与键对应的存储值的类型。Dictionary简写形式为 ...
  • 用了几分钟做的简单翻译 一个例子 直接贴代码,不过多解释 //这是我们的model class imageFile { var fileName = String() var fileID = Int() } //使用 var images : [imageFile] = [] images.sort({ $0....
1 2 3 4 5 ... 20
收藏数 921
精华内容 368
关键字:

4.0翻译 swift