Deprecated: imwpcache\f884414bce24ee67f\f73723ec7b1919fa5::__construct(): Implicitly marking parameter $YECBGYFECGEAFWHA as nullable is deprecated, the explicit nullable type must be used instead in /www/wwwroot/www.chuangxiangniao.com/wp-content/plugins/imwpcache-dist/build/f884414bce24ee67ff73723ec7b1919fa5.php on line 2

Deprecated: imwpcache\f884414bce24ee67f\f73723ec7b1919fa5::__construct(): Implicitly marking parameter $BBWFDDBHHYHDXXAB as nullable is deprecated, the explicit nullable type must be used instead in /www/wwwroot/www.chuangxiangniao.com/wp-content/plugins/imwpcache-dist/build/f884414bce24ee67ff73723ec7b1919fa5.php on line 2
Swift 3到5.1新特性整理_创想鸟

Swift 3到5.1新特性整理

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运行复制

enum NetworkError: Error {    case badURL}import Foundationfunc fetchUnreadCount1(from urlString: String, completionHandler: @escaping (Result) -> 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)    }}

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

代码语言:javascript代码运行次数:0运行复制

fetchUnreadCount1(from: "https://www.hackingwithswift.com") { result in    if let count = try? result.get() {        print("(count) unread messages.")    }}

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

代码语言:javascript代码运行次数:0运行复制

let result = Result { try String(contentsOfFile: someFile) }

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

Raw string

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

差值需要这样做

代码语言:javascript代码运行次数:0运行复制

let answer = 42let dontpanic = #"The answer to life, the universe, and everything is #(answer)."#

这个对于正则的特别好用

代码语言:javascript代码运行次数:0运行复制

let regex1 = "\[A-Z]+[A-Za-z]+.[a-z]+"let regex2 = #"[A-Z]+[A-Za-z]+.[a-z]+"#

自定义字符串插值

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

代码语言:javascript代码运行次数:0运行复制

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,

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

动态可调用类型

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

你可以将

代码语言:javascript代码运行次数:0运行复制

struct RandomNumberGenerator {    func generate(numberOfZeroes: Int) -> Double {        let maximum = pow(10, Double(numberOfZeroes))        return Double.random(in: 0...maximum)    }}

转变为

代码语言:javascript代码运行次数:0运行复制

@dynamicCallablestruct RandomNumberGenerator {    func dynamicallyCall(withKeywordArguments args: KeyValuePairs) -> 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)

@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运行复制

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

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

try?抹平嵌套可选代码语言:javascript代码运行次数:0运行复制

struct User {    var id: Int    init?(id: Int) {        if id  String {        // complicated code here        return "No messages"    }}let user = User(id: 1)let messages = try? user?.getMessages()

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

检查整数是否为偶数

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

代码语言:javascript代码运行次数:0运行复制

let rowNumber = 4if rowNumber.isMultiple(of: 2) {    print("Even")} else {    print("Odd")}

字典compactMapValues()方法

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

代码语言:javascript代码运行次数:0运行复制

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]

撤回的功能: 带条件的计数

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

代码语言:javascript代码运行次数:0运行复制

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

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

Swift 4.2CaseIterable协议

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

代码语言:javascript代码运行次数:0运行复制

enum Pasta: CaseIterable {    case cannelloni, fusilli, linguine, tagliatelle}for shape in Pasta.allCases {    print("I like eating (shape).")}

当然还可以自行实现

代码语言:javascript代码运行次数:0运行复制

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

警告和错误指令

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

#warning,警告,主要为了提示后续需要处理,Xcode可以编译通过#error, 常用在Library中,强制提示,需要修复,否则不会编译通过。代码语言:javascript代码运行次数:0运行复制

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

还可以和#if配合使用。

代码语言:javascript代码运行次数:0运行复制

#if os(macOS)#error("MyLibrary is not supported on macOS.")#endif

动态查找成员

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

代码语言:javascript代码运行次数:0运行复制

@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: 

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

代码语言:javascript代码运行次数:0运行复制

@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

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

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

代码语言:javascript代码运行次数:0运行复制

struct Singer {    public var name = "Justin Bieber"    subscript(dynamicMember member: String) -> String {        return "Taylor Swift"    }}let singer = Singer()print(singer.name)// Justin Bieber

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

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

代码语言:javascript代码运行次数:0运行复制

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

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

代码语言:javascript代码运行次数:0运行复制

@dynamicMemberLookupenum JSON {   case intValue(Int)   case stringValue(String)   case arrayValue(Array)   case dictionaryValue(Dictionary)   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  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   }}

正常使用

代码语言:javascript代码运行次数:0运行复制

let json = JSON.stringValue("Example")json[0]?["name"]?["first"]?.stringValue

如果用上述的写法

代码语言:javascript代码运行次数:0运行复制

json[0]?.name?.first?.stringValue

有条件地遵循协议的增强

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

代码语言:javascript代码运行次数:0运行复制

extension Array: Purchaseable where Element: Purchaseable {    func buy() {        for item in self {            item.buy()        }    }}

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

代码语言:javascript代码运行次数:0运行复制

let items: Any = [Book(), Book(), Book()]if let books = items as? Purchaseable {    books.buy()}

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

随机数产生和shuffling

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

代码语言:javascript代码运行次数:0运行复制

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

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

代码语言:javascript代码运行次数:0运行复制

var albums = ["Red", "1989", "Reputation"]// shuffle in placealbums.shuffle()// get a shuffled array backlet shuffled = albums.shuffled()

还有randomElement()方法。

代码语言:javascript代码运行次数:0运行复制

if let random = albums.randomElement() {    print("The random album is (random).")}

更简单,安全的Hash

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

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

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

代码语言:javascript代码运行次数:0运行复制

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

检查列表是否满足条件

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

代码语言:javascript代码运行次数:0运行复制

let scores = [85, 88, 95, 92]let passed = scores.allSatisfy { $0 >= 85 }

原地字典的元素移除

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

代码语言:javascript代码运行次数:0运行复制

var pythons = ["John", "Michael", "Graham", "Terry", "Eric", "Terry"]pythons.removeAll { $0.hasPrefix("Terry") }print(pythons)

Boolean toggling

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

代码语言:javascript代码运行次数:0运行复制

extension Bool {   mutating func toggle() {      self = !self   }}

Swift 4.2 你可以这样

代码语言:javascript代码运行次数:0运行复制

var loggedIn = falseloggedIn.toggle()

Swift 4.1EquatableHashable协议

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

代码语言:javascript代码运行次数:0运行复制

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

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

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

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

代码语言:javascript代码运行次数:0运行复制

var hashValue: Int {    return firstName.hashValue ^ lastName.hashValue &* 16777619}

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

代码语言:javascript代码运行次数:0运行复制

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

Codable协议,Key值转化策略

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

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

代码语言:javascript代码运行次数:0运行复制

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)

有条件地遵循协议

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

代码语言:javascript代码运行次数:0运行复制

extension Array: Purchaseable where Element: Purchaseable {   func buy() {      for item in self {         item.buy()      }   }}

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

代码语言:javascript代码运行次数:0运行复制

import Foundationstruct Person {   var name = "Taylor"}var people = [Person()]var encoder = JSONEncoder()try encoder.encode(people)

关联类型中的递归限制

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

代码语言:javascript代码运行次数:0运行复制

protocol Employee {   associatedtype Manager: Employee   var manager: Manager? { get set }}

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

canImport函数

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

代码语言:javascript代码运行次数:0运行复制

#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

之前还有类似的方法

代码语言:javascript代码运行次数:0运行复制

#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

targetEnvironment函数

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

代码语言:javascript代码运行次数:0运行复制

#if targetEnvironment(simulator)   // code for the simulator here#else   // code for real devices here#endif

flatMap改名为compactMap

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

代码语言:javascript代码运行次数:0运行复制

let array = ["1", "2", "Fish"]let numbers = array.compactMap { Int($0) }// [1, 2]

Swift 4.0Coodable协议

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

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

代码语言:javascript代码运行次数:0运行复制

struct Language: Codable {    var name: String    var version: Int}let swift = Language(name: "Swift", version: 4)

完整的使用

代码语言:javascript代码运行次数:0运行复制

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

多行字符串字面量

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

代码语言:javascript代码运行次数:0运行复制

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

改进Key-value编码中的keypaths

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

代码语言:javascript代码运行次数:0运行复制

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

改进字典函数

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

filter返回的是个字典map 返回的仍然是数组mapValues,返回的则是字典grouping初始化方法,可以将数组处理成字典default赋值和取值会比较方便。代码语言:javascript代码运行次数:0运行复制

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]

字符串又变成了Collection类型

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

代码语言:javascript代码运行次数:0运行复制

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

单侧区间

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

代码语言:javascript代码运行次数:0运行复制

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"]

Swift 3.1扩展限制的优化

Swift支持对扩展做限制。

代码语言:javascript代码运行次数:0运行复制

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)

代码语言:javascript代码运行次数:0运行复制

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)

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

代码语言:javascript代码运行次数:0运行复制

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)

嵌套类型支持泛型

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

代码语言:javascript代码运行次数:0运行复制

struct Message {    struct Attachment {        var contents: T    }    var title: T    var attachment: Attachment}

序列(Sequences)协议增加了prefix(while:), drop(while:)两个方法prefix(while:): 遍历所有元素,直到遇到不满足条件的元素 ,并且返回满足的元素drop(while:): 就是返回 prefix(while:)相反的就好。代码语言:javascript代码运行次数:0运行复制

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)

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

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

代码语言:javascript代码运行次数:0运行复制

func someFunction(argumentLabel parameterName: Int) {}// 使用必须带上参数标签someFunction(argumentLabel: 1)// 如果不指定,参数名称可以作为菜参数标签func someFunction(firstParameterName: Int, secondParameterName: Int) {}someFunction(firstParameterName: 1, secondParameterName: 2)

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

代码语言:javascript代码运行次数:0运行复制

func someFunction(_ firstParameterName: Int, secondParameterName: Int) {}someFunction(1, secondParameterName: 2)

移除多余代码

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

代码语言:javascript代码运行次数:0运行复制

// 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

以及

代码语言:javascript代码运行次数:0运行复制

// 第一行是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

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

代码语言:javascript代码运行次数:0运行复制

dismissViewControllerAnimated(true, completion: nil)dismiss(animated: true, completion: nil)dismiss(animated: true)prepareForSegue()override func prepare(for segue: UIStoryboardSegue, sender: AnyObject?)

枚举和属性从大驼峰替换为小驼峰

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

代码语言:javascript代码运行次数:0运行复制

UIInterfaceOrientationMask.Portrait // oldUIInterfaceOrientationMask.portrait // newNSTextAlignment.Left // oldNSTextAlignment.left // newSKBlendMode.Replace // oldSKBlendMode.replace // new

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

代码语言:javascript代码运行次数:0运行复制

enum Optional {    case None    case Some(Wrapped)}

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

代码语言:javascript代码运行次数:0运行复制

for case let .some(datum) in data {    print(datum)}for case let datum? in data {    print(datum)}

更swift地改进C函数

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

代码语言:javascript代码运行次数:0运行复制

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

以及

代码语言:javascript代码运行次数:0运行复制

// 第一行是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))

名次和动词

这部分属于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新特性整理

以上就是Swift 3到5.1新特性整理的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/25486.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2026年9月22日 12:58:26
Sublime运行Python3而不是Python2_修改构建系统中python命令
下一篇 2025年11月20日 11:57:51

相关推荐

  • AffinityDesigner如何导出AI生成的矢量图片?保存图像的步骤

    答案是选择合适的矢量格式并调整导出设置。在Affinity Designer中导出AI生成的矢量图时,应根据用途选择SVG(适用于Web)、PDF(适用于打印和跨平台分享)或EPS(适用于老旧系统);导出前需检查文本是否转曲、颜色模式是否正确,并优化路径与位图设置以平衡质量与文件大小;从其他AI工具…

    2026年9月22日
    000
  • php-gd怎么制作缩略图_php-gd生成高质量缩略图

    使用PHP-GD生成高质量缩略图需保持宽高比、选用imagecopyresampled进行重采样,并合理设置JPEG质量(80-95),同时处理PNG透明通道,避免图像失真或背景变黑。 使用 PHP-GD 制作高质量缩略图,核心在于正确处理图像缩放、保持宽高比、避免失真,并选择合适的图像质量参数。下…

    2026年9月22日
    000
  • MySQL安装后初始密码在哪里查看?

    MySQL安装后初始密码在哪里查看?MySQL安装后初始密码在哪里查看?MySQL安装后初始密码在哪里查看?MySQL安装后初始密码在哪里查看?

    mysql安装后的初始密码取决于安装方式和操作系统,通常可在错误日志中找到。1. 查看mysql错误日志:linux系统使用grep命令查找/var/log/mysqld.log或类似路径;windows系统在data目录下的hostname.err中搜索“temporary password”。2…

    2026年9月22日 用户投稿
    100
  • PHP日志记录怎么做_PHP中Monolog库实现灵活强大的日志系统

    Monolog是PHP中基于PSR-3标准的主流日志库,通过Composer安装后可轻松实现日志记录。使用Logger类创建实例并添加Handler(如StreamHandler写入文件、NativeMailerHandler邮件报警)来管理不同级别(debug、info、error等)日志输出,支…

    2026年9月22日
    200
  • 如何在RunwayML导出AI生成的4K图片?保存高清图像的教程

    要从RunwayML获得4K图像,需结合高分辨率生成设置与AI放大工具。首先在RunwayML中选择最高可用分辨率(如1024×1024或更高),并通过精细提示词和负面提示词优化生成质量;随后利用内置增强功能或外部AI放大工具(如Topaz Gigapixel AI、Upscayl)将图像…

    2026年9月22日
    100
  • mysql如何添加主键索引 mysql创建主键索引的步骤详解

    mysql如何添加主键索引 mysql创建主键索引的步骤详解mysql如何添加主键索引 mysql创建主键索引的步骤详解mysql如何添加主键索引 mysql创建主键索引的步骤详解mysql如何添加主键索引 mysql创建主键索引的步骤详解

    mysql中添加主键索引主要有三种方式:1. 创建新表时直接添加主键,可在列定义后使用primary key或在所有列定义后单独声明;2. 在已有表上通过alter table添加主键,需确保目标列非空且唯一,必要时先清洗数据;3. 添加复合主键,适用于多列组合才能唯一标识记录的情况。主键索引在in…

    2026年9月22日 用户投稿
    000
  • Winscp连接本地linux(centos7)

    要在本地linux系统(例如centos7)中查找ip地址,可以使用以下命令: ip addr show 或者更简洁的: ip a 这两个命令都会显示系统中所有网络接口的详细信息,包括IP地址。 如果你只想查看IPv4地址,可以使用以下命令: ip -4 addr show 或者使用ifconfig…

    2026年9月22日
    000
  • PHP数组如何定义和使用_PHP数组定义与使用详细教程

    PHP数组是存储和管理多个值的核心工具,支持索引、关联、混合及多维结构;通过方括号定义,可灵活访问、修改、添加或删除元素,并利用foreach高效遍历。 PHP数组是存储一系列值的强大工具,无论这些值是简单的数据项,还是更复杂的结构。它的核心思想就是把一堆相关的数据“打包”在一起,通过一个统一的名字…

    2026年9月22日
    000
  • VSCode 如何配置 Python 虚拟环境 VSCode 配置 Python 虚拟环境的步骤​

    VSCode 如何配置 Python 虚拟环境 VSCode 配置 Python 虚拟环境的步骤​VSCode 如何配置 Python 虚拟环境 VSCode 配置 Python 虚拟环境的步骤​VSCode 如何配置 Python 虚拟环境 VSCode 配置 Python 虚拟环境的步骤​VSCode 如何配置 Python 虚拟环境 VSCode 配置 Python 虚拟环境的步骤​

    在vscode中配置python虚拟环境的核心是选择正确的解释器,确保项目依赖隔离;2. 首先在项目根目录使用python -m venv .venv创建虚拟环境,或使用conda、pipenv等工具;3. 在vscode中打开项目文件夹,通过ctrl+shift+p输入“python: selec…

    2026年9月22日 用户投稿
    100
  • 逛京东先人一步下单E人E本EBOOK X14 Air笔记本 补贴立省10%

    逛京东先人一步下单E人E本EBOOK X14 Air笔记本 补贴立省10%逛京东先人一步下单E人E本EBOOK X14 Air笔记本 补贴立省10%逛京东先人一步下单E人E本EBOOK X14 Air笔记本 补贴立省10%逛京东先人一步下单E人E本EBOOK X14 Air笔记本 补贴立省10%

    10月13日10:00,京东抢先首发e人e本全新力作——ebook x14 air ai轻薄笔记本电脑,以仅898克的极致轻盈机身和卓越的本地ai算力,重新定义高效移动办公新标准。新品官方定价7999元,京东首发期间可享国家补贴直降10%,实付仅需7199元,晒单再赠50元京东e卡,下单即送高品质内…

    2026年9月22日 用户投稿
    000
  • Pictory如何快速生成AI视频?从文本到AI视频的完整教程

    Pictory通过智能算法将文字脚本转化为专业AI视频,核心在于自动分析文本、匹配视觉素材、生成语音并初步剪辑。用户登录后选择“Script to Video”,粘贴结构清晰的脚本,AI会自动分割场景并推荐素材,支持手动调整场景划分、替换素材、上传自定义图片视频以增强品牌一致性。平台提供多语言AI语…

    2026年9月22日
    000
  • MySQL最新版本如何下载?官方下载指南

    MySQL最新版本如何下载?官方下载指南MySQL最新版本如何下载?官方下载指南MySQL最新版本如何下载?官方下载指南MySQL最新版本如何下载?官方下载指南

    要下载mysql,推荐从官网直接下载;选择社区版或商业版取决于用途;下载时需选对操作系统和版本;安装遇到问题可查错误提示并搜索解决方案;验证安装成功可用命令行登录。下载步骤包括访问官网、选择版本与操作系统、使用installer、注册账号、开始下载安装。安装后配置root密码、字符集等。验证方式为命…

    2026年9月22日 用户投稿
    100
  • Flyway多数据库与CI/CD测试集成策略

    本文深入探讨了在CI/CD流程中,如何高效地配置Flyway以管理多数据库环境下的迁移,尤其关注集成测试场景。我们将比较使用真实数据库服务、Testcontainers以及Flyway自身多数据库配置的优劣,并提供关于分离生产与测试环境迁移脚本的实用策略,旨在确保开发、测试与生产环境的数据一致性与流…

    2026年9月22日
    100
  • 华为:Pura 80 Ultra、Watch GT 6 Pro入选2025年度最佳发明

    10月25日消息,华为终端官微今日发布喜讯:pura 80 ultra与watch gt 6 pro成功入选《时代周刊》2025年度最佳发明榜单。 华为方面指出,Pura 80 Ultra凭借其在影像设计与技术创新方面的突破性表现,赢得权威认可。 WATCH GT 6 Pro则因出色的运动监测功能、…

    2026年9月22日
    000
  • Spring Boot自定义Kafka配置与动态Bean注册最佳实践

    本文探讨了在Spring Boot应用中通过自定义注解简化Kafka配置的挑战与解决方案。重点介绍了如何利用META-INF/spring.factories实现早期自动配置,并详细阐述了使用ImportBeanDefinitionRegistrar在应用上下文初始化早期动态注册Kafka生产者工厂…

    2026年9月22日
    100
  • mysql安装后怎么维护 mysql日常维护操作大全

    mysql安装后怎么维护 mysql日常维护操作大全mysql安装后怎么维护 mysql日常维护操作大全mysql安装后怎么维护 mysql日常维护操作大全mysql安装后怎么维护 mysql日常维护操作大全

    开启并分析慢查询日志以优化 sql 性能;2. 定期使用逻辑或物理方式备份数据并异地存储;3. 监控连接数和服务器资源,防止资源耗尽;4. 定期执行 analyze、optimize 和 check 表操作以维护表健康;5. 合理管理日志配置与清理策略。mysql 安装后的日常维护主要包括慢查询监控…

    2026年9月22日 用户投稿
    100
  • 深度解析蝴蝶号如何实现AI实景24小时无人直播

    深度解析蝴蝶号如何实现AI实景24小时无人直播深度解析蝴蝶号如何实现AI实景24小时无人直播深度解析蝴蝶号如何实现AI实景24小时无人直播深度解析蝴蝶号如何实现AI实景24小时无人直播

    蝴蝶号能实现ai实景24小时无人直播,主要靠智能中控系统+实景画面采集+自动化互动机制。一、ai中控系统作为“大脑”,自动控制画面切换、语音播报、商品推荐和评论区互动,具备一定判断能力,确保稳定性与持续性。二、实景画面采集作为“眼睛”,通过高清摄像头和云台控制,在门店、仓库等场景采集实时画面,保障真…

    2026年9月22日 用户投稿
    200
  • VSCode配合Vivado进行FPGA图像处理(算法加速与优化)

    答案:VSCode与Vivado结合可提升FPGA图像处理开发效率,前者用于代码编辑、版本控制和远程开发,后者负责综合、实现与调试,二者协同实现高效算法优化。 将VSCode与Vivado结合用于FPGA图像处理,本质上是利用VSCode作为高效的代码编辑、版本控制和辅助开发环境,来弥补Vivado…

    2026年9月22日
    200
  • 构建VSCode多媒体编程界面与实时音视频处理

    答案:VSCode通过配置Node.js、Python扩展及FFmpeg等工具,结合OpenCV、PyAudio等框架,可构建高效音视频处理环境。1. 安装Python和Node.js支持,启用Pylance、Jupyter插件提升数据处理体验;2. 配置终端与Code Runner实现脚本一键执行…

    2026年9月22日
    100
  • 在Java中如何开发简易问答社区

    答案是Java结合Spring Boot可快速构建问答社区,通过设计questions、answers、users三张表实现数据存储,使用JPA进行持久化,前端用HTML+JS调用后端API完成用户提问、回答、查看与互动功能。 开发一个简易问答社区,核心是实现用户提问、回答、查看问题和互动功能。Ja…

    2026年9月22日
    100

发表回复

登录后才能评论
关注微信