0

0

Swift 3到5.1新特性整理

蓮花仙者

蓮花仙者

发布时间:2025-07-14 08:50:18

|

369人浏览过

|

来源于php中文网

原创

tocSwift 5.1Swift 5.0Result类型Raw string自定义字符串插值动态可调用类型处理未来的枚举值从try?抹平嵌套可选检查整数是否为偶数字典compactMapValues()方法撤回的功能: 带条件的计数Swift 4.2CaseIterable协议警告和错误指令动态查找成员有条件地遵循协议的增强随机数产生和shuffling更简单,安全的Hash检查列表是否满足条件原地字典的元素移除Boolean togglingSwift 4.1EquatableHashable协议Codable协议,Key值转化策略有条件地遵循协议关联类型中的递归限制canImport函数targetEnvironment函数flatMap改名为compactMapSwift 4.0Coodable协议多行字符串字面量改进Key-value编码中的keypaths改进字典函数字符串又变成了Collection类型单侧区间Swift 3.1扩展限制的优化嵌套类型支持泛型序列(Sequences)协议增加了prefix(while:), drop(while:)两个方法Swift 3.0函数调用必须使用参数标签移除多余代码枚举和属性从大驼峰替换为小驼峰更swift地改进C函数名次和动词Swift 5.1

swift 5.1的更新比较迟,单独成篇swift 5.1的变化。

Swift 5.0

Swift 5.0 最重要的自然是ABI Stability, 对此可以看这篇 Swift ABI 稳定对我们到底意味着什么 。

当然还有其他的更新。

Result类型

SE-0235提议的实现。用来在复杂对象中的错误处理。

Result类型有两个带泛型的枚举成员successfailure,而且failure的泛型必须遵循Swift的Error类型。

常规的使用

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">enum NetworkError: Error {    case badURL}import Foundationfunc fetchUnreadCount1(from urlString: String, completionHandler: @escaping (Result<Int, NetworkError>) -> Void)  {    guard let url = URL(string: urlString) else {        completionHandler(.failure(.badURL))        return    }    // complicated networking code here    print("Fetching (url.absoluteString)...")    completionHandler(.success(5))}fetchUnreadCount1(from: "https://www.hackingwithswift.com") { result in    switch result {    case .success(let count):        print("(count) unread messages.")    case .failure(let error):        print(error.localizedDescription)    }}</code>

首先,Result有个get()方法,要么返回成功值,要么抛出错误。那么可以这么使用。

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">fetchUnreadCount1(from: "https://www.hackingwithswift.com") { result in    if let count = try? result.get() {        print("(count) unread messages.")    }}</code>

再次,Result可以接受一个闭包来初始化,如果闭包成功返回,就会把它放到success的一边,如果抛出错误,就放到failure的一边。

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">let result = Result { try String(contentsOfFile: someFile) }</code>

最后,你可以使用你自己的错误枚举,但是Swift官方建议,你说用Swift.Error来作为Error的参数。

Raw string

SE-0200 引入了,使用#来包裹的Raw字符串,里面的字符不会做处理,特别是一些转义字符。

差值需要这样做

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">let answer = 42let dontpanic = #"The answer to life, the universe, and everything is #(answer)."#</code>

这个对于正则的特别好用

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">let regex1 = "\\[A-Z]+[A-Za-z]+\.[a-z]+"let regex2 = #"\[A-Z]+[A-Za-z]+.[a-z]+"#</code>
自定义字符串插值

SE-0228提案改进了Swift的字符串插值,让其更高效和自由。

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">struct User {    var name: String    var age: Int}extension String.StringInterpolation {    mutating func appendInterpolation(_ value: User) {        appendInterpolation("My name is (value.name) and I'm (value.age)")    }}let user = User(name: "Guybrush Threepwood", age: 33)print("User details: (user)")// User details: My name is Guybrush Threepwood and I'm 33,</code>

// TODO: 更多使用,需要多研究

动态可调用类型

SE-0216 增加了@dynamicCallable属性,来支持方法的动态调用,类似@dynamicMemberLookup

你可以将

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">struct RandomNumberGenerator {    func generate(numberOfZeroes: Int) -> Double {        let maximum = pow(10, Double(numberOfZeroes))        return Double.random(in: 0...maximum)    }}</code>

转变为

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">@dynamicCallablestruct RandomNumberGenerator {    func dynamicallyCall(withKeywordArguments args: KeyValuePairs<String, Int>) -> Double {        let numberOfZeroes = Double(args.first?.value ?? 0)        let maximum = pow(10, numberOfZeroes)        return Double.random(in: 0...maximum)    }}let random = RandomNumberGenerator()let result = random(numberOfZeroes: 0)</code>
@dynamicCallable参数 无参数标签withArguments,你可以使用任何遵循ExpressibleByArrayLiteral的类型,例如 数组,数组切片,set等有参数标签的withKeywordArguments,使用任何遵循ExpressibleByDictionaryLiteral的类型,例如,字典,和key value 对,更多KeyValuePairs可以的看这里,什么是KeyValuePairs?你可以将其用在结构体,枚举,类和协议上如果你使用withKeywordArguments而不是withArguments,你仍然按照无参数标签的方式使用,只是key是空字符串。如果withKeywordArguments或者withArguments标记为抛出错误,调用类型也会抛出错误。不能在扩展中使用@dynamicCallable你仍然可以添加属性和方法。处理未来的枚举值

SE_0192的实现。

有时候枚举的switch中使用default来防治出错,但不会真正的使用,但是如果未来加了新的case,那些处理地方就会遗漏。现在可以添加@unknkow来出触发Xcode的提示。

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">func showNew(error: PasswordError) {    switch error {    case .short:        print("Your password was too short.")    case .obvious:        print("Your password was too obvious.")    @unknown default:        print("Your password wasn't suitable.")    }}</code>

这样,如果如果代码中,没有处理干净PasswordError (switch block is no longer exhaustive),就会告警.

try?抹平嵌套可选代码语言:javascript代码运行次数:0运行复制
<code class="javascript">struct User {    var id: Int    init?(id: Int) {        if id < 1 {            return nil        }        self.id = id    }    func getMessages() throws -> String {        // complicated code here        return "No messages"    }}let user = User(id: 1)let messages = try? user?.getMessages()</code>

上面的例子中,Swift 4.2以及之前的,message会是 String??, 这样就不太合理,Swift 5中,就能返回抹平的String?

检查整数是否为偶数

SE-0225添加了, isMultiple(of:)来检查整数是否为偶数, 和if rowNumber % 2 == 0效果一样。

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">let rowNumber = 4if rowNumber.isMultiple(of: 2) {    print("Even")} else {    print("Odd")}</code>
字典compactMapValues()方法

SE-0218,为字典添加了compactMapValues()方法,这个就像结合了,数组compactMap()方法(遍历成员,判断可选的值,然后丢弃nil成员)和字典的mapValues()方法(只转换字典的value)。

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">let times = [    "Hudson": "38",    "Clarke": "42",    "Robinson": "35",    "Hartis": "DNF"]let finishers1 = times.compactMapValues { Int($0) }let finishers2 = times.compactMapValues(Int.init)let people6 = [    "Paul": 38,    "Sophie": 8,    "Charlotte": 5,    "William": nil]let knownAges = people6.compactMapValues { $0 }print("compactMapValues, (finishers1), (finishers2),(knownAges)")// compactMapValues, ["Clarke": 42, "Robinson": 35, "Hudson": 38], ["Robinson": 35, "Clarke": 42, "Hudson": 38],["Charlotte": 5, "Sophie": 8, "Paul": 38]</code>
撤回的功能: 带条件的计数

SE-0220, 引入了count(where:)函数,来计算遵循Sequence列表中满足条件成员的个数。

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">let scores = [100, 80, 85]let passCount = scores.count { $0 >= 85 }let pythons = ["Eric Idle", "Graham Chapman", "John Cleese", "Michael Palin", "Terry Gilliam", "Terry Jones"]let terryCount = pythons.count { $0.hasPrefix("Terry") }</code>

这个功能因为性能问题,被撤回了。


Swift 4.2CaseIterable协议

SE-0194提议的实现,Swift4.2 增加了CaseIterable协议,能够给枚举的allCases属性自动产生所有的枚举的数组。

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">enum Pasta: CaseIterable {    case cannelloni, fusilli, linguine, tagliatelle}for shape in Pasta.allCases {    print("I like eating (shape).")}</code>

当然还可以自行实现

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">enum Car: CaseIterable {    static var allCases: [Car] {        return [.ford, .toyota, .jaguar, .bmw, .porsche(convertible: false), .porsche(convertible: true)]    }    case ford, toyota, jaguar, bmw    case porsche(convertible: Bool)}</code>
警告和错误指令

SE-0196提议的实现。Swift 4.2提供这两个提示,来让Xcode在编译时候作出提示

#warning,警告,主要为了提示后续需要处理,Xcode可以编译通过#error, 常用在Library中,强制提示,需要修复,否则不会编译通过。代码语言:javascript代码运行次数:0运行复制
<code class="javascript">func encrypt(_ string: String, with password: String) -> String {    #warning("This is terrible method of encryption")    return password + String(string.reversed()) + password}struct Configuration {    var apiKey: String {        #error("Please enter your API key below then delete this line.")        return "Enter your key here"    }}    </code>

还可以和#if配合使用。

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">#if os(macOS)#error("MyLibrary is not supported on macOS.")#endif</code>
动态查找成员

SE-0195提议的实现。Swift 4.2提供了@dynamicMemberLookup的属性,和subscript(dynamicMember:)陪着使用,实现动态的属性的取值。

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">@dynamicMemberLookupstruct Person5 {    subscript(dynamicMember member: String) -> String {        let properties = ["name": "Tylor Swift", "city" : "Nashville"]        return properties[member, default: ""]    } }let person5 = Person5()print("person5.name: (person5.name)")print("person5.city: (person5.city)")print("person5.favoriteIceCream: (person5.favoriteIceCream)")// person5.name: Tylor Swift// person5.city: Nashville// person5.favoriteIceCream: </code>

当然也有类似多态的用法。

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">@dynamicMemberLookupstruct Person5 {    subscript(dynamicMember member: String) -> String {        let properties = ["name": "Tylor Swift", "city" : "Nashville"]        return properties[member, default: ""]    }        subscript(dynamicMember member: String) -> Int {        let properties = ["age": 26, "height": 178]        return properties[member, default: 0]    } }let person5 = Person5()print("person5.age: (person5.age)")let age: Int = person5.ageprint("person5.age2: (age)")// person5.age: // person5.age2: 26</code>

注意你需要指定明确指定类型,Swift才能正确使用。

而且如果已经有存在属性,动态属性将不会生效

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">struct Singer {    public var name = "Justin Bieber"    subscript(dynamicMember member: String) -> String {        return "Taylor Swift"    }}let singer = Singer()print(singer.name)// Justin Bieber</code>

@dynamicMemberLookup可以用在协议,结构体,枚举,类,甚至标注为@objc的类,以及它们的继承者。

例如,陪着协议的使用,你可以这样用

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">@dynamicMemberLookupprotocol Subscripting { }extension Subscripting {    subscript(dynamicMember member: String) -> String {        return "This is coming from the subscript"    }}extension String: Subscripting { }let str = "Hello, Swift"print(str.username)</code>

Chris Lattner提议中的例子很有意义,

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">@dynamicMemberLookupenum JSON {   case intValue(Int)   case stringValue(String)   case arrayValue(Array<JSON>)   case dictionaryValue(Dictionary<String, JSON>)   var stringValue: String? {      if case .stringValue(let str) = self {         return str      }      return nil   }   subscript(index: Int) -> JSON? {      if case .arrayValue(let arr) = self {         return index < arr.count ? arr[index] : nil      }      return nil   }   subscript(key: String) -> JSON? {      if case .dictionaryValue(let dict) = self {         return dict[key]      }      return nil   }   subscript(dynamicMember member: String) -> JSON? {      if case .dictionaryValue(let dict) = self {         return dict[member]      }      return nil   }}</code>

正常使用

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">let json = JSON.stringValue("Example")json[0]?["name"]?["first"]?.stringValue</code>

如果用上述的写法

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">json[0]?.name?.first?.stringValue</code>
有条件地遵循协议的增强

Swift 4.1引入了有条件地遵循协议

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">extension Array: Purchaseable where Element: Purchaseable {    func buy() {        for item in self {            item.buy()        }    }}</code>

但是在Swift 4.1中,如果你要确定对象是否遵循某个协议,会报错。Swift 4.2 修复了这个问题

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">let items: Any = [Book(), Book(), Book()]if let books = items as? Purchaseable {    books.buy()}</code>

还有,Swift 内置的类型,可选,数组,字典,区间,如果它们的成员遵循Hashable,那么它们也会自动遵循Hashable

随机数产生和shuffling

SE-0202提议的实现。Swift 4.2提供了原生的随机数方法。意味着你不需要使用arc4random_uniform()或者GameplayKit来实现了。

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">let randomInt = Int.random(in: 1..<5)let randomFloat = Float.random(in: 1..<10)let randomDouble = Double.random(in: 1...100)let randomCGFloat = CGFloat.random(in: 1...1000)let randomBool = Bool.random()</code>

SE-0202同样还提议了shuffle()shuffled()

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">var albums = ["Red", "1989", "Reputation"]// shuffle in placealbums.shuffle()// get a shuffled array backlet shuffled = albums.shuffled()</code>

还有randomElement()方法。

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">if let random = albums.randomElement() {    print("The random album is (random).")}</code>
更简单,安全的Hash

SE-0206的实现,让你更简单的为自建类型使用Hashable协议。

雾象
雾象

WaytoAGI推出的AI动画生成引擎

下载

Swift 4.1 能够为遵循Hashable协议的类型自动生成hash值。但是如果你需要自行实现仍然需要写不少代码。

Swift 4.2 引入了Hasher结构,提供了随机种子,和通用的hash函数来简化过程

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">struct iPad: Hashable {    var serialNumber: String    var capacity: Int    func hash(into hasher: inout Hasher) {        hasher.combine(serialNumber)    }}let first = iPad(serialNumber: "12345", capacity: 256)let second = iPad(serialNumber: "54321", capacity: 512)var hasher = Hasher()hasher.combine(first)hasher.combine(second)let hash = hasher.finalize()</code>
检查列表是否满足条件

SE-0207的实现,提供了allSatisfy()方法来检测数组中所有的元素是否都满足条件。

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">let scores = [85, 88, 95, 92]let passed = scores.allSatisfy { $0 >= 85 }</code>
原地字典的元素移除

SE-0197提供一个全新的removeAll(where:)方法,以此来提供一个更高效,会操作原数据的类似filter的方法。

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">var pythons = ["John", "Michael", "Graham", "Terry", "Eric", "Terry"]pythons.removeAll { $0.hasPrefix("Terry") }print(pythons)</code>
Boolean toggling

SE-0199提供了,对Booltoggle()方法,类似

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">extension Bool {   mutating func toggle() {      self = !self   }}</code>

Swift 4.2 你可以这样

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">var loggedIn = falseloggedIn.toggle()</code>

Swift 4.1EquatableHashable协议

类和结构体做可比较,需要自己手动实现。

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">struct Person: Equatable {    var firstName: String    var lastName: String    var age: Int    var city: String    static func ==(lhs: Person, rhs: Person) -> Bool {        return lhs.firstName == rhs.firstName && lhs.lastName == rhs.lastName && lhs.age == rhs.age && lhs.city == rhs.city    }}let person1 = Person(firstName: "hicc", lastName: "w", age: 20, city: "shenzhen")let person2 = Person(firstName: "hicc", lastName: "w", age: 20, city: "shenzhen")print("person1 1 == person2 : (person1 == person2)")// person1 1 == person2 : true</code>

Swift 4.1 提供了Equatable的协议,它会自动的生成==方法。

当然你还是可以自己实现==方法(例如,业务有id之类的属性)。

还有之前实现一个对象的hash值也是一件麻烦的事情,你可能需要手动实现类似:

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">var hashValue: Int {    return firstName.hashValue ^ lastName.hashValue &* 16777619}</code>

Swift 4.1 提供了Hashable的协议,可以自动生成hashValue,你也还是可以自行实现。

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">struct Person2: Equatable, Hashable {    var firstName: String    var lastName: String    var age: Int    var city: String}let person11 = Person2(firstName: "hicc", lastName: "w", age: 20, city: "shenzhen")let person22 = Person2(firstName: "hicc", lastName: "w", age: 20, city: "shenzhen")print("person11 1 == person22 : (person11 == person22), (person11.hashValue)")// person11 1 == person22 : true, 5419288582170212869</code>
Codable协议,Key值转化策略

Swift 4提供了很方便的Codable协议,但是它使用下划线snake_case而不是驼峰式的方式来转化Key,不太自由。

Swift 4.1 中针对这种情况,提供了keyDecodingStrategy,以及keyEncodingStrategy属性(默认.useDefaultKeys)来解决这些问题。

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">let decoder = JSONDecoder()decoder.keyDecodingStrategy = .convertFromSnakeCasedo {    let macs = try decoder.decode([Mac].self, from: jsonData)    print(macs)} catch {    print(error.localizedDescription)}let encoder = JSONEncoder()encoder.keyEncodingStrategy = .convertToSnakeCaselet encoded = try encoder.encode(someObject)</code>
有条件地遵循协议

Swift 4.1 实现了SE-0143的提议,容许你类型在某下情况下才遵循某个协议。

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">extension Array: Purchaseable where Element: Purchaseable {   func buy() {      for item in self {         item.buy()      }   }}</code>

这样会让你的代码,更加的安全。如下代码Swift中会拒绝编译,因为其未遵循Coodable协议.

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">import Foundationstruct Person {   var name = "Taylor"}var people = [Person()]var encoder = JSONEncoder()try encoder.encode(people)</code>
关联类型中的递归限制

Swift 4.1实现了SE-0157提议,在递归协议中,关联类型可以被定义它的协议所限制。

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">protocol Employee {   associatedtype Manager: Employee   var manager: Manager? { get set }}</code>

// TODO: 现在感受不太清楚,后续有深入了解在补充。

canImport函数

SE-0075提议的实现。Swift 4.1引入了canImport函数,让你可以检查某个模块能否被导入。

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">#if canImport(SpriteKit)   // this will be true for iOS, macOS, tvOS, and watchOS#else   // this will be true for other platforms, such as Linux#endif</code>

之前还有类似的方法

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">#if !os(Linux)   // Matches macOS, iOS, watchOS, tvOS, and any other future platforms#endif#if os(macOS) || os(iOS) || os(tvOS) || os(watchOS)   // Matches only Apple platforms, but needs to be kept up to date as new platforms are added#endif</code>
targetEnvironment函数

SE-0190提议的实现,Swift 4.1 提供了targetEnvironment函数,来检测是模拟器还是真实的硬件。

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">#if targetEnvironment(simulator)   // code for the simulator here#else   // code for real devices here#endif</code>
flatMap改名为compactMap

flatMap之前一个很有用的作用是能够过滤数组中为nil的元素,Swift 4.2重命名为指意明确,更强大的compactMap

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">let array = ["1", "2", "Fish"]let numbers = array.compactMap { Int($0) }// [1, 2]</code>

Swift 4.0Coodable协议

Swift 4之前使用NSCoding来做encoding和decoding的事情,但是需要一些模版代码,也容易出错,Swift 4中 Coodable协议就是为这个而存在。

使用起来简单到不可思议。

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">struct Language: Codable {    var name: String    var version: Int}let swift = Language(name: "Swift", version: 4)</code>

完整的使用

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">let encoder = JSONEncoder()if let encoded = try? encoder.encode(swift) {    if let json = String(data: encoded, encoding: .utf8) {        print("swift strng(json)")    }        let decoder = JSONDecoder()    if let decoded = try? decoder.decode(Language.self, from: encoded) {        print("Swift name: (decoded.name)")    }}</code>
多行字符串字面量

跨越多行的字符串可以使用"""来包裹。

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">let quotation = """The White Rabbit put on his spectacles. "Where shall I begin,please your Majesty?" he asked."Begin at the beginning," the King said gravely, "and go ontill you come to the end; then stop.""""</code>
改进Key-value编码中的keypaths

keypaths是指对属性的引用而不去真正读取属性的值。

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">struct Crew {    var name: String    var rank: String}struct Starship {    var name: String    var maxWarp: Double    var captain: Crew}let janeway = Crew(name: "Kathryn Janeway", rank: "Captain")let voyager = Starship(name: "Voyager", maxWarp: 9.975, captain: janeway)let nameKeyPath = Starship.namelet maxWarpKeyPath = Starship.maxWarplet captainName = Starship.captain.namelet starshipName = voyager[keyPath: nameKeyPath]let starshipMaxWarp = voyager[keyPath: maxWarpKeyPath]let starshipCaptain = voyager[keyPath: captainName]print("starshipName (starshipName),(starshipCaptain)")// starshipName Voyager, Kathryn Janeway</code>
改进字典函数

Swift 4改进了字典的诸多函数。

filter返回的是个字典map 返回的仍然是数组mapValues,返回的则是字典grouping初始化方法,可以将数组处理成字典default赋值和取值会比较方便。代码语言:javascript代码运行次数:0运行复制
<code class="javascript">let cities = ["Shanghai": 24_256_800, "Karachi": 23_500_000, "Beijing": 21_516_000, "Seoul": 9_995_000];let massiveCities = cities.filter { $0.value > 10_000_000 }let populations = cities.map { $0.value * 2 }let roundedCities = cities.mapValues { "($0 / 1_000_000) million people" }let groupedCities = Dictionary(grouping: cities.keys) { $0.first! }let groupedCities2 = Dictionary(grouping: cities.keys) { $0.count }var favoriteTVShows = ["Red Dwarf", "Blackadder", "Fawlty Towers", "Red Dwarf"]var favoriteCounts = [String: Int]()for show in favoriteTVShows {    favoriteCounts[show, default: 0] += 1}print("dic(massiveCities),
(populations),
(roundedCities),
(groupedCities),
(groupedCities2),
(favoriteCounts)")// dic["Shanghai": 24256800, "Beijing": 21516000, "Karachi": 23500000],// [43032000, 47000000, 19990000, 48513600],///["Beijing": "21 million people", "Karachi": "23 million people", "Seoul": "9 million people", "Shanghai": "24 million people"],// ["S": ["Seoul", "Shanghai"], "B": ["Beijing"], "K": ["Karachi"]],// [8: ["Shanghai"], 5: ["Seoul"], 7: ["Beijing", "Karachi"]],// ["Blackadder": 1, "Fawlty Towers": 1, "Red Dwarf": 2]</code>
字符串又变成了Collection类型

字符串是Collection类型,这样就有了诸多便利的方法。

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">let quote = "It is a truth universally acknowledged that new Swift versions bring new features."let reversed = quote.reversed()for letter in quote {    print(letter)}</code>
单侧区间

Swift 4 支持了单侧区间, 缺失的一边为0或者为集合的尽头

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">let characters = ["Dr Horrible", "Captain Hammer", "Penny", "Bad Horse", "Moist"]let bigParts = characters[..<3]let smallParts = characters[3...]print(bigParts)print(smallParts)// ["Dr Horrible", "Captain Hammer", "Penny"]// ["Bad Horse", "Moist"]</code>

Swift 3.1扩展限制的优化

Swift支持对扩展做限制。

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">extension Collection where Iterator.Element: Comparable {    func lessThanFirst() -> [Iterator.Element] {        guard let first = self.first else { return [] }        return self.filter { $0 < first }    }}let items = [5, 6, 10, 4, 110, 3].lessThanFirst()print(items)</code>
代码语言:javascript代码运行次数:0运行复制
<code class="javascript">extension Array where Element: Comparable {    func lessThanFirst() -> [Element] {        guard let first = self.first else { return [] }        return self.filter { $0 < first }    }}let items = [5, 6, 10, 4, 110, 3].lessThanFirst()print(items)</code>

上述3.0的对扩展的限制都是通过协议实现。Swift 3.1 支持使用类型来限制。

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">extension Array where Element == Int {    func lessThanFirst() -> [Int] {        guard let first = self.first else { return [] }        return self.filter { $0 < first }    }}let items = [5, 6, 10, 4, 110, 3].lessThanFirst()print(items)</code>
嵌套类型支持泛型

Swift 3.1支持了嵌套类型中使用泛型。

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">struct Message<T> {    struct Attachment {        var contents: T    }    var title: T    var attachment: Attachment}</code>
序列(Sequences)协议增加了prefix(while:), drop(while:)两个方法prefix(while:): 遍历所有元素,直到遇到不满足条件的元素 ,并且返回满足的元素drop(while:): 就是返回 prefix(while:)相反的就好。代码语言:javascript代码运行次数:0运行复制
<code class="javascript">let names = ["Michael Jackson", "Michael Jordan", "Michael Caine", "Taylor Swift", "Adele Adkins", "Michael Douglas"]let prefixed = names.prefix { $0.hasPrefix("Michael") }print(prefixed)let dropped = names.drop { $0.hasPrefix("Michael") }print(dropped)</code>

Swift 3.0函数调用必须使用参数标签

Swift特点是函数可以分别制定参数标签(argument label)和参数名称(parameter name)

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">func someFunction(argumentLabel parameterName: Int) {}// 使用必须带上参数标签someFunction(argumentLabel: 1)// 如果不指定,参数名称可以作为菜参数标签func someFunction(firstParameterName: Int, secondParameterName: Int) {}someFunction(firstParameterName: 1, secondParameterName: 2)</code>

如果你不想使用参数标签,可以使用_代替

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">func someFunction(_ firstParameterName: Int, secondParameterName: Int) {}someFunction(1, secondParameterName: 2)</code>
移除多余代码

主要是一些内置对象,以及和平台相关的精简,让代码更加易读。

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">// Swift 2.2let blue = UIColor.blueColor()let min = numbers.minElement()attributedString.appendAttributedString(anotherString)names.insert("Jane", atIndex: 0)UIDevice.currentDevice()// Swift 3let blue = UIColor.bluelet min = numbers.min()attributedString.append(anotherString)names.insert("Jane", at: 0)UIDevice.current</code>

以及

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">// 第一行是Swift 2.2// 迪尔汗是Swift 3"  Hello  ".stringByTrimmingCharactersInSet(.whitespaceAndNewlineCharacterSet())"  Hello  ".trimmingCharacters(in: .whitespacesAndNewlines)"Taylor".containsString("ayl")"Taylor".contains("ayl")"1,2,3,4,5".componentsSeparatedByString(",")"1,2,3,4,5".components(separatedBy: ",")myPath.stringByAppendingPathComponent("file.txt")myPath.appendingPathComponent("file.txt")"Hello, world".stringByReplacingOccurrencesOfString("Hello", withString: "Goodbye")"Hello, world".replacingOccurrences(of: "Hello", with: "Goodbye")"Hello, world".substringFromIndex(7)"Hello, world".substring(from: 7)"Hello, world".capitalizedString"Hello, world".capitalized</code>

以及, lowercaseString -> lowercased()uppercaseString ->uppercased()

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">dismissViewControllerAnimated(true, completion: nil)dismiss(animated: true, completion: nil)dismiss(animated: true)prepareForSegue()override func prepare(for segue: UIStoryboardSegue, sender: AnyObject?)</code>
枚举和属性从大驼峰替换为小驼峰

正如标题说的,一方面这是Swift推荐的用法,另外就是内置对象的变化

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">UIInterfaceOrientationMask.Portrait // oldUIInterfaceOrientationMask.portrait // newNSTextAlignment.Left // oldNSTextAlignment.left // newSKBlendMode.Replace // oldSKBlendMode.replace // new</code>

还有就是Swift可选类型是通过枚举来实现的

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">enum Optional {    case None    case Some(Wrapped)}</code>

如果使用.Some来处理可选,也需要更改

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">for case let .some(datum) in data {    print(datum)}for case let datum? in data {    print(datum)}</code>
更swift地改进C函数

大体来说就是让C函数使用更加的Swift

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">// Swift 2.2let ctx = UIGraphicsGetCurrentContext()let rectangle = CGRect(x: 0, y: 0, width: 512, height: 512)CGContextSetFillColorWithColor(ctx, UIColor.redColor().CGColor)CGContextSetStrokeColorWithColor(ctx, UIColor.blackColor().CGColor)CGContextSetLineWidth(ctx, 10)CGContextAddRect(ctx, rectangle)CGContextDrawPath(ctx, .FillStroke)UIGraphicsEndImageContext()// Swift 3if let ctx = UIGraphicsGetCurrentContext() {    let rectangle = CGRect(x: 0, y: 0, width: 512, height: 512)    ctx.setFillColor(UIColor.red.cgColor)    ctx.setStrokeColor(UIColor.black.cgColor)    ctx.setLineWidth(10)    ctx.addRect(rectangle)    ctx.drawPath(using: .fillStroke)    UIGraphicsEndImageContext()}</code>

以及

代码语言:javascript代码运行次数:0运行复制
<code class="javascript">// 第一行是Swift 2.2// 第二行是Swift 3CGAffineTransformIdentityCGAffineTransform.identityCGAffineTransformMakeScale(2, 2)CGAffineTransform(scaleX: 2, y: 2)CGAffineTransformMakeTranslation(128, 128)CGAffineTransform(translationX: 128, y: 128)CGAffineTransformMakeRotation(CGFloat(M_PI))CGAffineTransform(rotationAngle: CGFloat(M_PI))</code>
名次和动词

这部分属于Swift更加语义化的改进,到现在5.1的时候一直在改进,目前官网最近的规范Swift.org - API Design Guidelines方法的部分是:

按照它们的副作用来命名函数和方法 无副作用的按照名次来命名。x.distance(to: y)i.successor()有副作用的按照动词来命名。print(x)x.sort()x.append(y)有修改和无修改命名 动词的方法中,无修改的使用过去时ed(通常是,不修改原数据,而是返回新的),有修改的使用现在时ing。名词的方法中,无修改的使用名词,有修改的前面加上from
Swift 3到5.1新特性整理
Swift 3到5.1新特性整理

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
Swift iOS架构设计与MVVM模式实战
Swift iOS架构设计与MVVM模式实战

本专题聚焦 Swift 在 iOS 应用架构设计中的实践,系统讲解 MVVM 模式的核心思想、数据绑定机制、模块拆分策略以及组件化开发方法。内容涵盖网络层封装、状态管理、依赖注入与性能优化技巧。通过完整项目案例,帮助开发者构建结构清晰、可维护性强的 iOS 应用架构体系。

286

2026.03.03

python中print函数的用法
python中print函数的用法

python中print函数的语法是“print(value1, value2, ..., sep=' ', end=' ', file=sys.stdout, flush=False)”。本专题为大家提供print相关的文章、下载、课程内容,供大家免费下载体验。

192

2023.09.27

python print用法与作用
python print用法与作用

本专题整合了python print的用法、作用、函数功能相关内容,阅读专题下面的文章了解更多详细教程。

19

2026.02.03

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

1030

2023.08.02

java中boolean的用法
java中boolean的用法

在Java中,boolean是一种基本数据类型,它只有两个可能的值:true和false。boolean类型经常用于条件测试,比如进行比较或者检查某个条件是否满足。想了解更多java中boolean的相关内容,可以阅读本专题下面的文章。

367

2023.11.13

java boolean类型
java boolean类型

本专题整合了java中boolean类型相关教程,阅读专题下面的文章了解更多详细内容。

42

2025.11.30

if什么意思
if什么意思

if的意思是“如果”的条件。它是一个用于引导条件语句的关键词,用于根据特定条件的真假情况来执行不同的代码块。本专题提供if什么意思的相关文章,供大家免费阅读。

847

2023.08.22

switch语句用法
switch语句用法

switch语句用法:1、Switch语句只能用于整数类型,枚举类型和String类型,不能用于浮点数类型和布尔类型;2、每个case语句后面必须跟着一个break语句,以防止执行其他case的代码块,没有break语句,将会继续执行下一个case的代码块;3、可以在一个case语句中匹配多个值,使用逗号分隔;4、Switch语句中的default代码块是可选的等等。

569

2023.09.21

C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

76

2026.03.11

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
swift开发文档
swift开发文档

共33课时 | 26.1万人学习

玩儿转Swift视频教程
玩儿转Swift视频教程

共44课时 | 9万人学习

传智播客Swift基础视频教程
传智播客Swift基础视频教程

共40课时 | 8.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号