Starting: cclog

Hipo 2.0 has been rewritten from Swift 1 to Swift 2. The subsequent Hipo functions are stable and updates are much slower… Swift itself is in great progress. 5.0 has been released. This article summarizes the updates from Swift 3.0 to Swift 5.1.

Prepare a summary from new to old for easy reading.

All the things below are from HackingWithSwift.com.


Swift, 5.1

Swift 5.1 update is late, separate from Swift 5.1 changes.

Swift, 5.0

Swift 5.0 ABI Stability is the most important ABI Stability for Swift 5.0.

There are other updates as well.

Resulttype

Implementation of the SE-0235 proposal. Used for error handling in complex objects.

The Result type has two generic enumerators, Success and Failure, and the generics for Failure must follow Swift’s Error type.

Routine use

enum NetworkError: Error {
    case badURL
}

import Foundation

func 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)
    }
}
Copy the code

First, Result has a get() method that either returns a success value or throws an error. So you can use it this way.

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

Again, Result can accept a closure to initialize, and if the closure returns successfully, it is placed on the side of success, and if an error is thrown, it is placed on the side of failure.

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

Finally, you can use your own Error enumeration, but Swift official recommends that you use swift. Error as an Error parameter.

“It’s expected that most uses of Result will use Swift.Error as the Error type argument.”

Raw string

Se-0200 introduces Raw strings wrapped in #. Characters inside are not processed, especially escape characters.

The difference needs to do that

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

This is especially useful for regular

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

Custom string interpolation

The SE-0228 proposal improves Swift’s string interpolation to make it more efficient and free.

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,
Copy the code

// TODO: More use, more research

Dynamic callable type

Se-0216 added @dynamicCallable to support dynamic method calls, similar to @dynamicMemberLookup.

You can take

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

Into a

@dynamicCallable
struct 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(a)let result = random(numberOfZeroes: 0)
Copy the code
  • @dynamicCallableparameter
    • No parameter labelwithArgumentsYou can use any followExpressibleByArrayLiteralType, such as array, array slice, set, etc
    • With a parameter labelwithKeywordArguments, use any followExpressibleByDictionaryLiteralTypes, such as dictionaries, and key value pairs, and moreKeyValuePairsYou can see here,What is KeyValuePairs?
  • You can use it for structs, enums, classes, and protocols
  • If you usewithKeywordArgumentsRather thanwithArgumentsYou still use it as a no-argument label, except that key is an empty string.
  • ifwithKeywordArgumentsorwithArgumentsThe call type also throws an error.
  • Cannot be used in extensions@dynamicCallable
  • You can still add properties and methods.

Process future enumeration values

Implementation of SE_0192.

Sometimes enumerated switches use default to prevent errors, but it is not actually used, but if new cases are added in the future, those processing places will be missed. Now you can add @unknkow to trigger Xcode.

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

This will raise an alarm if PasswordError (switch block is no longer Exhaustive) is not cleared.

fromtry?Flush nesting is optional

struct User {
    var id: Int

    init? (id:Int) {
        if id < 1 {
            return nil
        }

        self.id = id
    }

    func getMessages(a) throws -> String {
        // complicated code here
        return "No messages"}}let user = User(id: 1)
let messages = try? user? .getMessages()Copy the code

In the above example, for Swift 4.2 and before, message would be String?? In Swift 5, you can return a flattened String, okay?

Check if the integers are even

Se-0225 added isMultiple(of:) to check if the integer is even, same as if rowNumber % 2 == 0.

let rowNumber = 4

if rowNumber.isMultiple(of: 2) {
    print("Even")}else {
    print("Odd")}Copy the code

The dictionarycompactMapValues()methods

Se-0218 added the compactMapValues() method to the dictionary, which is like combining the array compactMap() method (iterating over the members, determining optional values, and discarding nil members) with the dictionary’s mapValues() method (converting only the dictionary’s values).

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]
Copy the code

Recall function: conditional count

Se-0220 introduces the count(where:) function to count the number of members in a list that follows a Sequence.

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")}Copy the code

This feature was withdrawn due to performance issues.

Swift, 4.2

CaseIterableagreement

The proposed implementation of SE-0194, Swift4.2 adds the CaseIterable protocol, which automatically generates an array of all enumerations for the allCases attribute of an enumeration.

enum Pasta: CaseIterable {
    case cannelloni, fusilli, linguine, tagliatelle
}

for shape in Pasta.allCases {
    print("I like eating \(shape).")}Copy the code

Of course, you can do it yourself

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)}Copy the code

Warnings and error instructions

Implementation of the SE-0196 proposal. Swift 4.2 provides these two prompts to make Xcode prompt at compile time

  • #warningWarning, mainly to indicate the need for future processing, Xcode can compile through
  • #errorUsed in the Library to force a message that it needs to be fixed or it will not compile.
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"}}Copy the code

It can also be used with #if.

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

Dynamic lookup member

Implementation of the SE-0195 proposal. Swift 4.2 provides @dynamicmemberlookup property, which is used together with subscript(dynamicMember:) to achieve dynamic attribute values.

@dynamicMemberLookup
struct Person5 {
    subscript(dynamicMember member: String) - >String {
        let properties = ["name": "Tylor Swift"."city" : "Nashville"]
        return properties[member, default: ""]}}let person5 = Person5(a)print("person5.name: \(person5.name)")
print("person5.city: \(person5.city)")
print("person5.favoriteIceCream: \(person5.favoriteIceCream)")
// person5.name: Tylor Swift
// person5.city: Nashville
// person5.favoriteIceCream: 
Copy the code

Of course, there are similar uses for polymorphism.

@dynamicMemberLookup
struct 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(a)print("person5.age: \(person5.age)")
let age: Int = person5.age
print("person5.age2: \(age)")
// person5.age: 
// person5.age2: 26
Copy the code

Note that you need to specify the explicitly specified type for Swift to work correctly.

And if you already have an existing attribute, the dynamic attribute will not take effect

struct Singer {
    public var name = "Justin Bieber"

    subscript(dynamicMember member: String) - >String {
        return "Taylor Swift"}}let singer = Singer(a)print(singer.name)
// Justin Bieber
Copy the code

DynamicMemberLookup can be used with protocols, structures, enumerations, classes, and even classes labeled @objc and their successors.

For example, with protocol, you can use it like this

@dynamicMemberLookup
protocol 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)
Copy the code

The example of Chris Lattner’s proposal makes sense,

@dynamicMemberLookup
enum 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}}Copy the code

Normal use

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

If I write it the way I wrote it

json[0]? .name?.first?.stringValueCopy the code

Conditional compliance with protocol enhancements

Swift 4.1 introduces conditional compliance protocols

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

In Swift 4.1, however, an error is reported if you want to determine whether an object is following a protocol. Swift 4.2 fixes this problem

let items: Any = [Book(), Book(), Book()]

if let books = items as? Purchaseable {
    books.buy()
}
Copy the code

Also, Swift’s built-in types, optional arrays, dictionaries, ranges, automatically follow Hashable if their members follow Hashable.

Random number generation andshuffling

Implementation of the SE-0202 proposal. Swift 4.2 provides a native random number method. This means you don’t need to use arc4random_Uniform () or GameplayKit to do it.

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()
Copy the code

Se-0202 also suggests shuffle() and Shuffled ()

var albums = ["Red"."1989"."Reputation"]

// shuffle in place
albums.shuffle()

// get a shuffled array back
let shuffled = albums.shuffled()
Copy the code

There is also the randomElement() method.

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

Simpler, secure hashes

The se-0206 implementation makes it easier to use the Hashable protocol for your own types.

Swift 4.1 can automatically generate hash values for types that follow the Hashable protocol. But you still have to write a lot of code if you have to implement it yourself.

Swift 4.2 introduces the Hasher structure, which provides random seeds, and generic hash functions to simplify the process

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()
Copy the code

Check whether the list meets the conditions

The implementation of SE-0207 provides the allSatisfy() method to check whether all elements in an array satisfy conditions.

let scores = [85.88.95.92]
let passed = scores.allSatisfy { $0> =85 }
Copy the code

Removes elements from the original dictionary

Se-0197 provides a new removeAll(where:) method to provide a more efficient filter-like method that manipulates raw data.

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

Boolean toggling

Se-0199 provides a toggle() method for Bool, similarly

extension Bool {
   mutating func toggle(a) {
      self=!self}}Copy the code

Swift 4.2 you can do this

var loggedIn = false
loggedIn.toggle()
Copy the code

Swift, 4.1

EquatableandHashableagreement

Classes and structs can be compared, which needs to be implemented manually.

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
Copy the code

Swift 4.1 provides the Equatable protocol, which automatically generates the == method.

Of course, you can still implement the == method yourself (for example, businesses have attributes like ID).

It’s also a hassle to implement an object hash, which you might need to implement manually:

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

Swift 4.1 provides the Hashable protocol for automatically generating hashValues, which you can still implement yourself.

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
Copy the code

CodableProtocol and Key value conversion policy

Swift 4 offers a handy Codable protocol, but it uses the underscore snake_case instead of the camel’s back to convert keys, which is less liberal.

Swift 4.1 provides keyDecodingStrategy for this situation, along with the keyEncodingStrategy attribute (default. UseDefaultKeys) to address these issues.

let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase

do {
    let macs = try decoder.decode([Mac].self, from: jsonData)
    print(macs)
} catch {
    print(error.localizedDescription)
}

let encoder = JSONEncoder()
encoder.keyEncodingStrategy = .convertToSnakeCase
let encoded = try encoder.encode(someObject)
Copy the code

Follow the agreement conditionally

Swift 4.1 implements the SE-0143 proposal, allowing you to follow a protocol only under certain circumstances.

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

This will make your code more secure. The following code is rejected for compilation in Swift because it does not comply with the Coodable protocol.

import Foundation

struct Person {
   var name = "Taylor"
}

var people = [Person()]
var encoder = JSONEncoder(a)try encoder.encode(people)
Copy the code

Recursive constraints in association types

Swift 4.1 implements the SE-0157 proposal, where an association type can be limited by the protocol that defines it in a recursive protocol.

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

// TODO: I am not sure about my feelings now, but I will add further information later.

canImportfunction

Implementation of the SE-0075 proposal. Swift 4.1 introduced the canImport function, which allows you to check whether a module can be imported.

#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
Copy the code

There’s been a similar approach before

#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
Copy the code

targetEnvironmentfunction

Implementation of the SE-0190 proposal, Swift 4.1 provides targetEnvironment functions to detect whether it is an emulator or real hardware.

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

FlatMap was renamed compactMap

A useful function of flatMap was the ability to filter elements in an array that were nil, which Swift 4.2 renamed to the more powerful compactMap with a clear meaning

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

Swift, 4.0

Coodableagreement

Swift 4 previously used NSCoding to do encoding and decoding, but it requires some template codes and is prone to error. The Coodable protocol in Swift 4 exists for this purpose.

It’s incredibly simple to use.

struct Language: Codable {
    var name: String
    var version: Int
}

let swift = Language(name: "Swift", version: 4)
Copy the code

Complete use

let encoder = JSONEncoder(a)if let encoded = try? encoder.encode(swift) {
    if let json = String(data: encoded, encoding: .utf8) {
        print("swift strng\(json)")}let decoder = JSONDecoder(a)if let decoded = try? decoder.decode(Language.self, from: encoded) {
        print("Swift name: \(decoded.name)")}}Copy the code

Multiline string literals

Strings that span multiple lines can be wrapped with “””.

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 on
till you come to the end; then stop."
"""
Copy the code

Improve key-value encodingkeypaths

Keypaths are references to properties without actually reading the value of the property.

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.name
let maxWarpKeyPath = \Starship.maxWarp
let captainName = \Starship.captain.name

let starshipName = voyager[keyPath: nameKeyPath]
let starshipMaxWarp = voyager[keyPath: maxWarpKeyPath]
let starshipCaptain = voyager[keyPath: captainName]

print("starshipName \(starshipName).\(starshipCaptain)")
// starshipName Voyager, Kathryn Janeway
Copy the code

Improving dictionary functions

Swift 4 improves many of the dictionary’s functions.

  • filterIt returns a dictionary
  • mapIt still returns an array
  • mapValues, returns a dictionary
  • groupingInitialization method that handles an array as a dictionary
  • defaultIt’s easier to assign and evaluate.
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),\n\(populations),\n\(roundedCities),\n\(groupedCities),\n\(groupedCities2),\n\(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]
Copy the code

The string becomes a Collection type again

Strings are of Collection type, so there are a number of handy methods.

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)
}
Copy the code

Unilateral interval

Swift 4 supports single-sided ranges, with the missing side being 0 or the end of the set

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"]
Copy the code

Swift, 3.1

Optimization of extension limits

Swift supports restrictions on extensions.

extension Collection where Iterator.Element: Comparable {
    func lessThanFirst(a)- > [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)
Copy the code
extension Array where Element: Comparable {
    func lessThanFirst(a)- > [Element] {
        guard let first = self.first else { return[]}return self.filter{$0 < first }
    }
}

let items = [5.6.10.4.110.3].lessThanFirst()
print(items)
Copy the code

The above 3.0 extension restrictions are implemented by protocol. Swift 3.1 supports restrictions using types.

extension Array where Element= =Int {
    func lessThanFirst(a)- > [Int] {
        guard let first = self.first else { return[]}return self.filter{$0 < first }
    }
}

let items = [5.6.10.4.110.3].lessThanFirst()
print(items)
Copy the code

Nested types support generics

Swift 3.1 supports the use of generics in nested types.

struct Message<T> {
    struct Attachment {
        var contents: T
    }

    var title: T
    var attachment: Attachment
}
Copy the code

The Sequences protocol has been increasedprefix(while:).drop(while:)Two methods

  • prefix(while:): Iterates through all elements until an element that does not meet the criteria is encountered, and the element that does is returned
  • drop(while:): returnprefix(while:)The opposite is fine.
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)
Copy the code

Swift, 3.0

Function calls must use parameter labels

Swift features that the function can specify the argument label and parameter name respectively.

func someFunction(argumentLabel parameterName: Int){}// Use with a parameter label
someFunction(argumentLabel: 1)

// If not specified, the parameter name can be used as the parameter label of the dish
func someFunction(firstParameterName: Int, secondParameterName: Int) {
}
someFunction(firstParameterName: 1, secondParameterName: 2)
Copy the code

If you don’t want to use parameter tags, use _ instead

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

Remove unnecessary code

Mainly built-in objects and platform-specific streamlining to make code more readable.

/ / Swift, 2.2
let blue = UIColor.blueColor()
let min = numbers.minElement()
attributedString.appendAttributedString(anotherString)
names.insert("Jane", atIndex: 0)
UIDevice.currentDevice()
// Swift 3
let blue = UIColor.blue
let min = numbers.min()
attributedString.append(anotherString)
names.insert("Jane", at: 0)
UIDevice.current
Copy the code

As well as

// The first line is Swift 2.2
// Dilhan is 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
Copy the code

And lowercaseString -> lowercased(), uppercaseString ->uppercased()

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

Enumerations and properties are replaced from large humps with small humps

As the title suggests, on the one hand this is the Swift recommended usage, and on the other is the change in built-in objects

UIInterfaceOrientationMask.Portrait // old
UIInterfaceOrientationMask.portrait // new

NSTextAlignment.Left // old
NSTextAlignment.left // new

SKBlendMode.Replace // old
SKBlendMode.replace // new
Copy the code

Also, Swift optional types are implemented through enumeration

enum Optional {
    case None
    case Some(Wrapped)}Copy the code

If.some is used to handle the optional, this also needs to be changed

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

for case let datum? in data {
    print(datum)
}
Copy the code

Improve C functions more quickly

Basically, let the C function use more Swift

/ / Swift, 2.2
let ctx = UIGraphicsGetCurrentContext(a)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(a)// Swift 3
if 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()}Copy the code

As well as

// The first line is Swift 2.2
// The second line is Swift 3
CGAffineTransformIdentity
CGAffineTransform.identity

CGAffineTransformMakeScale(2.2)
CGAffineTransform(scaleX: 2, y: 2)

CGAffineTransformMakeTranslation(128.128)
CGAffineTransform(translationX: 128, y: 128)

CGAffineTransformMakeRotation(CGFloat(M_PI))
CGAffineTransform(rotationAngle: CGFloat(M_PI))
Copy the code

Placings and verbs

This is part of Swift’s more semantic improvements, which have been working on since 5.1, currently [swift.org-API Design Guidelines] (swift.org/documentati…) The method part is:

  • Name functions and methods according to their side effects
    • Those without side effects are named according to the rank.x.distance(to: y).i.successor()
    • Those with side effects are named after the verb.print(x).x.sort().x.append(y)
    • Name with and without modification
      • In the verb method, the past tense is used without modificationed(usually, the original data is not modified, but the new one is returned), and the modified one is used in the present tenseing.
      • In the noun method, use the noun without modification and add the modification before itfrom.