iOS分享世界swift开发技巧iOS第三方资料收集

MG--Swift3.x进阶语法学习3

2017-03-24  本文已影响185人  Mg明明就是你

一、元祖(Tuples)


  • 2.Returning multiple values(返回多个值)

 - 举个栗子
func fetchWeather() -> (type: String, cloudCover: Int, high: Int, low: Int) {
         return ("Sunny", 50, 32, 26)
}
let weather = fetchWeather()
print(weather.type)
返回多个值


二、Generics(泛型)

  • 1.我们来看一个简单的例子 (type(of: value)打印的是类型,在Swift2.x语法对应的函数是(value.dynamicType),动态识别类型,这就是泛型的好处

func inspect<T>(value: T) {
    print("Received \(type(of: value)) with the value \(value)")
}
inspect(value: "明哥")
FF77A052-62A1-42A6-A098-C3F15052CA36.png
inspect(value: "123")
FE471D99-57C8-4714-AE3D-E078D27710BE.png
extension Float: Numeric {}
extension Double: Numeric {}
extension Int: Numeric {}
protocol Numeric {
    static func *(lhs: Self, rhs: Self) -> Self  // 平方
    static func +(lhs: Self, rhs: Self) -> Self // 相加
}
func squareSomething<T: Numeric>(value: T) -> T {
    return value * value
}
func addSomething<T: Numeric>(value: T) -> T {
    return value + value
}
squareSomething(value: 1.2)
addSomething(value: 1.2)

struct deque<T> {
    var array = [T]()
    mutating func pushBack(_ obj: T) {
        array.append(obj)
    }
    mutating func pushFront(_ obj: T) {
        array.insert(obj, at: 0)
    }
    mutating func popBack() -> T? {
        return array.popLast()
    }
    mutating func popFront() -> T? {
        if array.isEmpty {
            return nil
        } else {
            return array.removeFirst()
        }
    }
}
// 创建一个deque
var testDeque = deque<Int>(array: [2313,321,32,24])
testDeque.pushBack(5)
testDeque.pushFront(2)
testDeque.pushFront(1)
testDeque.pushFront(3)
testDeque.pushFront(4)
testDeque.popFront()
testDeque.popBack()
print(testDeque)
struct CountedSet<T: AnyObject> {
        var internalSet = NSCountedSet()
        func addObject(_ obj: T) {
            internalSet.add(obj)
        }
        func removeObject(_ obj: T) {
            internalSet.remove(obj)
        }
        func countForObject(_ obj: T) -> Int {
            return internalSet.count(for: obj)
        }
}
var countedSet = CountedSet<NSString>()
countedSet.addObject("明哥")
countedSet.addObject("明哥")
countedSet.addObject("Hello")
countedSet.countForObject("Hello")
countedSet.countForObject("明哥")
print(countedSet)
var countedSet2 = CountedSet<NSNumber>()
countedSet2.addObject(5)
print(countedSet2)



三、闭包

  • 通过学习我们自己知道,在Swift中,布尔值、数字、字符串、数组、字典、结构等等都是值类型。类是引用类型,但也闭包
  • 闭包是引用,我们从截图可以看到值是往上递增的



四、操作符

  • 最简单的操作符:"="
  • 但是我对操作符("=")进行重写之后,请看👇的代码


    对操作符("=")进行重写.png
  • 操作符("**")进行重写。求立方



    操作符重写
let test1 = (1...100).contains(42)
let test2 = 1...100 ~= 42
let dictString = "Danger, Will Robinson: mathematics failure!"
dictString ~= "计算机"
dictString.contains("计算机")
~=这个关系运算符实现的功能和包含函数一样


五、数组的高级用法

  • 1.filter()

let namees = ["Michael Paul", "Keybe brinte", "Michael Cofe",
              "ming ming", "Michael Jordan"]
let result = names.filter({ name in
      if name.hasPrefix("Michael") {
          return true
      } else {
        return false;
      }
})
print(result)   // 返回符合要求的结果,打印如图
let result = namees.filter({ name in
        return name.hasPrefix("Michael")
})
print(result)  // 返回符合要求的结果,打印如图
let result = namees.filter { return $0.hasPrefix("Michael") }
print(result)   // 返回符合要求的结果,打印如图
let words = ["Swift","iOS","cocoa","OSX","tvOS"]
let tweet = "This is an example tweet larking about Swift"
words.contains(where: tweet.contains) // Print(true)
// 或者这样写
tweet.characters.split(separator: " ").lazy.map(String.init).contains(where: Set(words).contains) // Print(true)
// 再或者这么写
words.filter({ tweet.contains($0)}) // 打印的是Swift

let mg_numbers = [1, 3, 5, 7, 9]
let number_result =  mg_numbers.reduce(0) { (int1, int2) -> Int in
       int1 + int2
} // 累加数组中的元素
print(number_result)
let number_result =  mg_numbers.reduce(0) {
       $0 + $1
} // 累加数组中的元素
let result = reduceNumbers.reduce(0, +)
let scores = [100, 90, 95]
let result = scores.reduce("明哥") { $0 + String($1) }
print(result);
打印结果.png
let scores = [100, 8, 6,"欢迎你的来电"] as [Any]
let result = scores.reduce("你好!") { $0 + String(describing: $1) }
print(result);
打印结果.png
let names = ["Taylor", "Paul", "Adele", "mingmming", "Swift","Michael Jordan"]
let longest = names.reduce("") { $1.characters.count  >  $0.characters.count ? $1 : $0 }
names.max { $1.characters.count > $0.characters.count } // 最长
names.min(by: {$1.characters.count > $0.characters.count}) // 最短
找出数组中字符最长的元素.png
let names = ["Taylor", "Paul", "Adele"]
let count = names.reduce(0) { $0 + $1.characters.count }
print(count)
打印结果.png
let numbers = [
                    [1, 1, 2],
                    [3, 5, 8],
                    [13, 21, 34] 
                  ]
let flattened: [Int] = numbers.reduce([]) { $0 + $1 }
print(flattened)
numbers.flatMap { $0 }
reduce的多个数组转一个数组.png
let names = ["Taylor", "Paul", "Adele"]
let longEnough = names.reduce(true) { $0 && $1.characters.count > 4 }
let longEnough1 = names.reduce(true) { $0 || $1.characters.count > 4 }
reduce的并或的关系.png

• false && false == false
• true && false == false
• false && true == false
• true && true == true

• false || false == false
• true || false == true
• false || true == true
• true || true == true


let π = Double(M_PI)
let max = 8.0 * π
let ds = stride(from:0.0, to:max, by:π / 6.0).map({1 - cos($0)})
Sina
let moneyArray = [213,432,54,123,321]
let stringsArray = moneyArray.map({"\($0)明明MG"})
print(stringsArray)
类型转换.png
let lipsum = "This is an example tweet larking about Swift."
let words1 = lipsum.characters.split{$0 == " "}.map(String.init)
print(words1)
let splitedArray = lipsum.components(separatedBy: " ")
print("拆分后的数组:\(splitedArray)")
拆分后的数组


六、Error(错误)

  • 我们来举个🌰 ,密码提示错误,抛出异常
enum PasswordError: Error {
        case Empty  // 密码为空
        case Short(minChars: Int)  // 密码不能少于
        case Obvious(message: String) // 明显的错误
}
func encryptString(str: String, withPassword password: String) throws
    -> String {
        if password.isEmpty {
           throw PasswordError.Empty
        }
        if password == "12345" {
            throw PasswordError.Obvious(message: "I have the same number on my luggage")
        }
        if password.characters.count < 4 {
            throw PasswordError.Short(minChars: 4)
        }
        let encrypted = password + str + password
        return String(encrypted.characters.reversed())
}
func testCatch() {
        do {
            let encrypted = try encryptString(str: "secret information!",
                                              withPassword: "1234567")
            print("You password is: \(encrypted)")
        } catch PasswordError.Empty {
            print("You must provide a password.")
        } catch PasswordError.Obvious(let message) {
            print("Your password is obvious: \(message)")
        } catch PasswordError.Short(let minChars) where minChars < 4 {
            print("We have a lax security policy: passwords must be at least \(minChars)")
        } catch PasswordError.Short(let minChars) where minChars < 8 {
            print("We have a moderate security policy: passwords must be at least \(minChars)")
        } catch PasswordError.Short(let minChars) {
            print("We have a serious security policy: passwords must be at least \(minChars)")
        }catch {
            print("Error")
        }
}
 let encrypted = try encryptString(str: "secret information!",
                                          withPassword: "")
密码是空.png
let encrypted = try encryptString(str: "secret information!",
                                          withPassword: "123")
密码长度不够.png
let encrypted = try encryptString(str: "secret information!",
                                          withPassword: "12345")
密码已经存在.png

"

let encrypted = try encryptString(str: "secret information!",
                                          withPassword: "1234567")
显示新创建的密码.png


七、Assertions(断言)

  • 断言允许您声明某些条件必须是真的。条件是给你的,可以是复杂的,但如果它为false的话您的程序将立即停止。

func *(lhs: [Int], rhs: [Int]) -> [Int] {
      precondition(lhs.count == rhs.count, "Arrays were not the same size")
        var result = [Int]()
        for (index, int) in lhs.enumerated() {
            result.append(int * rhs[index])
        }
        return result
}
[1, 2] * [4, 5, 2]
[12, 5] * [5, 6]
数组个数不对应,报错.png
数组个数对应,数组相乘结果.png


八、补充数组的那些高级用法示例

  • 我们通过一个例子学习👇的东西

// 统计一个数组中每一个字符个数的函数
func lengthOfStrings(strings: [String]) -> [Int] {
    var result = [Int]()
    for string in strings {
        result.append(string.characters.count)
    }
    return result
}
func lengthOfStrings(strings: [String]) -> [Int] {
      return strings.map { $0.characters.count }
}

let fruits = ["Apple", "Cherry", "Orange", "Pineapple"]
let upperFruits = fruits.map({ $0.uppercased() })
print(upperFruits)
转化成大写.png
let mg_scores = [100, 80 ,43, 48, 85, 70, 60, 55]
let formatted = mg_scores.map { "Your score was \($0)" }
- 数组的元素是否及格
let passOrFail = mg_scores.map { $0 > 60 ? "Pass" : "Fail" }
print(passOrFail)
- 数组的元素是否在某一个范围之内
let position = [50, 60, 40]
let averageResults = position.map { 45...55 ~= $0  ? "Within average" : "Outside average" }
print(averageResults)
  - 打印结果截图
数组的元素添加东西.png
数组的元素是否及格.png
数组的元素是否在某一个范围之内.png
开平方.png
  • Map?

func fetchUsername(id: Int) -> String? {
      if id == 1989 {
          return "明哥"
      } else{
          return nil
      }
}
let username = fetchUsername(1989)
let formattedUsername: String
if let username = username {
       formattedUsername = "Welcome, \(username)!"
} else {
       formattedUsername = "Unknown user"
}
let username = fetchUsername(1989)
let formattedUsername = username.map { "Welcome, \($0)!" } ?? "Unknown user"


let manyNumbers = [[1, 2], [3, 4], [5, 6]]
let flattened = Array(manyNumbers.joined()) // 2.x语法使用flatten() 函数
多个数组变成一个数组
  • flatMap()的功能更像是Map()和joined()的结合

let albums: [String?] = ["Fearless", nil, "Speak Now", nil, "Red"]
let albumsResult = albums.map { $0 }
print("map: \(albumsResult)")   //  打印的是可选类型
print("flatMap: \(albums.flatMap { $0 })")  // 会自动过滤空值,打印的是确定类型
👀👀结果.png

到了这里,如果你还不是很清楚flatmap()是否有用,那么继续👀下面
- 再看一个🌰

let flatMapscores = ["100", "90", "Fish", "85"]
let flatMapResult = flatMapscores.flatMap { Int($0) }
let mapResult = flatMapscores.map { Int($0) }
print("flatMapscores: \(flatMapscores)")
print("flatMapResult: \(flatMapResult)")  // flatMapResult: [100, 90, 85]
print("mapResult: \(mapResult)") // mapResult: [Optional(100), Optional(90), nil, Optional(85)]
打印结果.png

- 这个技术可以用于当你需要区分成功与失败之间的代码使用的可选性。任何有抛异常的函数都可用于try?去处理,它在函数转换为失败时返回nil。

- 测试代码以及结果.png

- 解释:这个测试的代码将加载到一个数组中的somefile-1.txt、somefile-2.txt、somefile-3.txt内容等等。不存在的任何文件都会抛出一个异常,try?会转换为nil和flatmap()将忽略,所有执行的操作只需要一行代码!

  • 结论:你可以看到,flatmap()汇集了flatten(),map(),和filter() 的功能,它会对可选值和空值做特殊的处理


filter()

  • 通过学习了上面这么多函数,我想你已经晕😲了,这需要一段时间去熟悉之后,才会理清思路。如果你足够清醒,那就继续往下看。
let fibonacciNumbers = [1, 2, 3, 5, 8, 13, 21]
let evenFibonacci = fibonacciNumbers.filter { $0 % 2 == 0 }
print("filter: \(evenFibonacci)")
print("map: \(fibonacciNumbers.map { $0 % 2 == 0 })")
print("flatMap: \(fibonacciNumbers.flatMap { $0 % 2 == 0 })")
三者之间的区别
再👀一个🌰.png
let words = ["ming", "Fearless", "Red"]
let input = "ming favorite Color is Red"
let result = words.filter { input.contains($0)}
不包含返回为空数组
返回包含的字符数组.png
let words: [String?] = ["1989", nil, "Fearless", nil, "Red"]
let input = "My favorite album is Fearless"
let result = words.filter { $0 != nil }
print(result)
let result1 = words.flatMap { $0 }
print(result1)
结果截图.png
let scores = ["Paul": 100, "Taylor": 95, "Adele": 90, "Michael": 85, "Justin": 60]
let goodScores = scores.filter { $1 > 85 }
goodScores
print(goodScores[0].1)
print(goodScores[1].1)
print(goodScores[2].1)
打印结果

补充:在Swift4中:字典:使用filter(),你返回来的结果是一个字典,不再是元祖。



  • 轻轻点击,关注我简书

轻轻点击,关注我简书

轻轻点击,关注我微博

浏览我的GitHub


  • 扫一扫,关注我

扫一扫,关注我.jpg
上一篇 下一篇

猜你喜欢

热点阅读