带你初识Swift4.0,踏入Swift的大门

imango 2年前
   <p>背景</p>    <p>由于Swift4之前的版本也看过好几遍,不过好久没看有点忘记了,不过这次看也是非常得心应手。项目中也准备引入Swift,所以作者再次详细看了 <a href="/misc/goto?guid=4959756766429073452" rel="nofollow,noindex">The Swift Programming Language (Swift 4.0.3)</a> 英文官方文档一遍,并且详细列举了本人认为大家比较常用并且应该掌握的所有知识点。这里不做深入探究,如果哪里不懂的话,可以自行深入研究。</p>    <p>所有知识点</p>    <ul>     <li> <p>数组可以用“+”表示两个数组组合</p> </li>     <li> <p>字符串截取等操作很简洁</p> </li>    </ul>    <pre>  <code class="language-swift">let greeting = "Hello, world!" let index = greeting.index(of: ",") ?? greeting.endIndex let beginning = greeting[..</code></pre>    <ul>     <li> <p>Dictionary可以遍历,并且支持移除操作</p> </li>    </ul>    <pre>  <code class="language-swift">airports["APL"] = nil 或 removeValue(forKey:)</code></pre>    <p>遍历:</p>    <pre>  <code class="language-swift">for (airportCode, airportName) in airports {     print("(airportCode): (airportName)") }</code></pre>    <ul>     <li> <p>switch语法很强大,很灵活,支持任何类型,比如字符串、范围、管道等等。而且不用break语句</p> </li>    </ul>    <pre>  <code class="language-swift">case "a", "A": case 1..<5: case (-2...2, -2...2) case let (x, y) where x == y</code></pre>    <ul>     <li> <p>guard关键词使用使语句更简单明了</p> </li>     <li> <p>#available判断api版本更简洁</p> </li>    </ul>    <pre>  <code class="language-swift">if #available(iOS 10, macOS 10.12, *) {     // Use iOS 10 APIs on iOS, and use macOS 10.12 APIs on macOS } else {     // Fall back to earlier iOS and macOS APIs }</code></pre>    <ul>     <li> <p>函数可以返回多个值</p> </li>    </ul>    <pre>  <code class="language-swift">func minMax(array: [Int]) -> (min: Int, max: Int) {     var currentMin = array[0]     var currentMax = array[0]     for value in array[1.. currentMax {             currentMax = value         }     }     return (currentMin, currentMax) }</code></pre>    <ul>     <li> <p>函数参数可以设置默认值</p> </li>    </ul>    <pre>  <code class="language-swift">func someFunction(parameterWithoutDefault: Int, parameterWithDefault: Int = 12) {     // If you omit the second argument when calling this function, then     // the value of parameterWithDefault is 12 inside the function body. } someFunction(parameterWithoutDefault: 3, parameterWithDefault: 6) // parameterWithDefault is 6 someFunction(parameterWithoutDefault: 4) // parameterWithDefault is 12</code></pre>    <ul>     <li> <p>可变参数...</p> </li>    </ul>    <pre>  <code class="language-swift">func arithmeticMean(_ numbers: Double...) -> Double {     var total: Double = 0     for number in numbers {         total += number     }     return total / Double(numbers.count) } arithmeticMean(1, 2, 3, 4, 5)</code></pre>    <ul>     <li> <p>inout 可以修改外部变量。与c语言指针有点类似</p> </li>    </ul>    <pre>  <code class="language-swift">func swapTwoInts(_ a: inout Int, _ b: inout Int) {     let temporaryA = a     a = b     b = temporaryA</code></pre>    <ul>     <li> <p>函数可以与属性变量一样对待。可以传递、取值等</p> </li>     <li> <p>闭包(Closures)与Block类似</p> </li>    </ul>    <p>{ (parameters) -> return type in     statements }</p>    <p>*@escaping和@autoclosure修饰闭包 @escaping使闭包在函数执行结束之前不会被执行。</p>    <pre>  <code class="language-swift">var completionHandlers: [() -> Void] = [] func someFunctionWithEscapingClosure(completionHandler: @escaping () -> Void) {     completionHandlers.append(completionHandler)//闭包没有执行,而是加到数组中了 }</code></pre>    <p>@autoclosure简化了闭包的代用,不过代码会变的难懂,苹果建议尽量不使用</p>    <pre>  <code class="language-swift">// customersInLine is ["Alex", "Ewa", "Barry", "Daniella"] func serve(customer customerProvider: () -> String) {     print("Now serving (customerProvider())!") } serve(customer: { customersInLine.remove(at: 0) } ) // Prints "Now serving Alex!"</code></pre>    <p>使用之后:</p>    <pre>  <code class="language-swift">// customersInLine is ["Ewa", "Barry", "Daniella"] func serve(customer customerProvider: @autoclosure () -> String) {     print("Now serving (customerProvider())!") } serve(customer: customersInLine.remove(at: 0))//大括号没有啦 // Prints "Now serving Ewa!"</code></pre>    <ul>     <li> <p>枚举功能很强大,很灵活,可以枚举的类型非常多,比如string、character、integer。</p> </li>    </ul>    <pre>  <code class="language-swift">enum Barcode {     case upc(Int, Int, Int, Int)     case qrCode(String) } var productBarcode = Barcode.upc(8, 85909, 51226, 3) switch productBarcode { case .upc(let numberSystem, let manufacturer, let product, let check):     print("UPC: (numberSystem), (manufacturer), (product), (check).") case .qrCode(let productCode):     print("QR code: (productCode).") }</code></pre>    <pre>  <code class="language-swift">enum Planet: Int{} enum ASCIIControlCharacter: Character {} enum CompassPoint: String {}</code></pre>    <ul>     <li> <p>indirect表示枚举中使用了自己</p> </li>    </ul>    <pre>  <code class="language-swift">enum ArithmeticExpression {     case number(Int)     indirect case addition(ArithmeticExpression, ArithmeticExpression)     indirect case multiplication(ArithmeticExpression, ArithmeticExpression) }</code></pre>    <p>或</p>    <pre>  <code class="language-swift">indirect enum ArithmeticExpression {     case number(Int)     case addition(ArithmeticExpression, ArithmeticExpression)     case multiplication(ArithmeticExpression, ArithmeticExpression) }</code></pre>    <ul>     <li> <p>struct&&class struct传递是值传递;class是引用传递</p> </li>    </ul>    <pre>  <code class="language-swift">In Swift, many basic data types such as String, Array, and Dictionary are implemented as structures. This means that data such as strings, arrays, and dictionaries are copied when they are assigned to a new constant or variable, or when they are passed to a function or method.  </code></pre>    <ul>     <li> <p>===和!==用来比较对象</p> </li>     <li> <p>lazy懒加载,使用的时候再加载</p> </li>     <li> <p>仅读属性。将get、set移除,直接返回,可以用来实例单例</p> </li>    </ul>    <pre>  <code class="language-swift">struct Cuboid {     var width = 0.0, height = 0.0, depth = 0.0     var volume: Double {         return width * height * depth     } }</code></pre>    <ul>     <li> <p>mutating用来修改struct和enum。因为二者是不能不能被自己的实例对象修改属性变量</p> </li>    </ul>    <pre>  <code class="language-swift">struct Point {     var x = 0.0, y = 0.0     mutating func moveBy(x deltaX: Double, y deltaY: Double) {         x += deltaX         y += deltaY     } } var somePoint = Point(x: 1.0, y: 1.0) somePoint.moveBy(x: 2.0, y: 3.0) print("The point is now at ((somePoint.x), (somePoint.y))") // Prints "The point is now at (3.0, 4.0)" **注意let不能修改** let fixedPoint = Point(x: 3.0, y: 3.0) fixedPoint.moveBy(x: 2.0, y: 3.0) // this will report an error</code></pre>    <pre>  <code class="language-swift">enum TriStateSwitch {     case off, low, high     mutating func next() {         switch self {         case .off:             self = .low         case .low:             self = .high         case .high:             self = .off         }     } } var ovenLight = TriStateSwitch.low ovenLight.next() // ovenLight is now equal to .high ovenLight.next() // ovenLight is now equal to .off</code></pre>    <ul>     <li> <p>class和static都可修饰类方法,class修饰的可以被子类重写</p> </li>     <li> <p>脚标(Subscripts)。可以类、结构体、枚举定义脚标从而快速访问属性等。</p> </li>    </ul>    <pre>  <code class="language-swift">subscript(index: Int) -> Int {     get {         // return an appropriate subscript value here     }     set(newValue) {         // perform a suitable setting action here     } }</code></pre>    <ul>     <li> <p>final可以防止被子类继承。</p> </li>     <li> <p>deinit 只有类有,当类销毁时会被回调。</p> </li>     <li> <p>?是否为nil;??设置默认值</p> </li>     <li> <p>异常处理</p> </li>    </ul>    <pre>  <code class="language-swift">do {     try expression     statements } catch pattern 1 {     statements } catch pattern 2 where condition {     statements }</code></pre>    <p>try!明确知道不会抛出异常。</p>    <ul>     <li> <p>defer代码块执行后必须执行的代码</p> </li>    </ul>    <pre>  <code class="language-swift">func processFile(filename: String) throws {     if exists(filename) {         let file = open(filename)         defer {             close(file)         }         while let line = try file.readline() {             // Work with the file.         }         // close(file) is called here, at the end of the scope.     } }</code></pre>    <ul>     <li> <p>is判断是否某个类型;as? 或 as!转换至某个类型</p> </li>     <li> <p>Extensions与oc的category类似</p> </li>    </ul>    <pre>  <code class="language-swift">extension SomeType: SomeProtocol, AnotherProtocol {     // implementation of protocol requirements goes here }</code></pre>    <ul>     <li> <p>Protocols</p> </li>    </ul>    <p>protocol SomeProtocol {     // protocol definition goes here }</p>    <p>使用</p>    <pre>  <code class="language-swift">struct SomeStructure: FirstProtocol, AnotherProtocol {     // structure definition goes here }</code></pre>    <pre>  <code class="language-swift">protocol SomeProtocol {     var mustBeSettable: Int { get set }//有get和set方法     var doesNotNeedToBeSettable: Int { get }//只有get方法,不能单独设置,只能在初始化的时候设置。 }</code></pre>    <ul>     <li> <p>检查是否遵循了某个协议</p> </li>    </ul>    <ul>     <li> <p>is遵循了返回true,否则返回false</p> </li>     <li> <p>as?遵循了正常转换,否则为nil</p> </li>     <li> <p>as!遵循了正常转换,否则抛出错误</p> </li>    </ul>    <ul>     <li> <p>泛型(Generic);通常使用T、U、V等大写字母表示。</p> </li>    </ul>    <p>func someFunction(someT: T, someU: U) {     // function body goes here }</p>    <ul>     <li> <p>weak或unowned(与oc的unsafe_unretained类似)解决循环应用的问题</p> </li>    </ul>    <p>weak var tenant: Person?</p>    <ul>     <li> <p>访问控制权限(open > public > interal > fileprivate > private)</p> </li>    </ul>    <ul>     <li> <p>private</p> <p>private 访问级别所修饰的属性或者方法只能在当前类里访问。 (注意:Swift4 中,extension 里也可以访问 private 的属性。)</p> </li>     <li> <p>fileprivate</p> <p>fileprivate 访问级别所修饰的属性或者方法在当前的 Swift)</p> </li>     <li> <p>internal(默认访问级别,internal修饰符可写可不写)</p> <p>internal 访问级别所修饰的属性或方法在源代码所在的整个模块都可以访问。 如果是框架或者库代码,则在整个框架内部都可以访问,框架由外部代码所引用时,则不可以访问。 如果是 App 代码,也是在整个 App 代码,也是在整个 App 内部可以访问。</p> </li>     <li> <p>public</p> <p>可以被任何人访问。但其他 module 中不可以被 override 和继承,而在 module 内可以被 override 和继承。</p> </li>     <li> <p>open</p> <p>可以被任何人使用,包括 override 和继承。</p> </li>    </ul>    <p> </p>    <p> </p>    <p>来自:http://www.cocoachina.com/ios/20180129/21979.html</p>    <p> </p>