美文网首页Swift编程
iOS 10: Swift - 2.Founctions方法

iOS 10: Swift - 2.Founctions方法

作者: 廖马儿 | 来源:发表于2018-01-05 12:23 被阅读5次

    1.Function Parameters and Return Value,方法参数和返回类型

    @discardableResult

    如过没有使用到方法的返回值,可以在方法的前面加@discardableResult

        cul(2, 3)
        //print(sum)
        
    }
    
    @discardableResult
    func cul(_ a:Int, _ b:Int) -> Int {
    
        return a + b
    }
    

    返回为空的方法,下面三个是一样的,没有区别:

    func say1(_ s:String) -> Void { print(s) } 
    func say2(_ s:String) -> () { print(s) } 
    func say3(_ s:String) { print(s) }
    

    Function Signature:方法署名,方法标志
    忽略掉方法的声明和方法体,留下参数和返回类型,就是方法的署名或者标志( signature

    (Int, Int) -> Int
    

    A function’s signature is, in effect, its type — the type ofthe function.
    方法的署名实际上就是方法的类型。

    External Parameter Names

    作用有:

    • It clarifies the purpose of each argument; each argument label can give a clue asto how that argument contributes to the behavior of the function.

    • It distinguishes one function from another; two functions with the same name(before the parentheses) and the same signature but different externalizedparameter names are two distinct functions. // 可以区分方法,如果方法有相同的名字的话

    • It helps Swift to interface with Objective-C and Cocoa, where method parametersnearly always have externalized names.

      func echoString(_ s:String, times:Int) -> String { 
        var result = ""
         for _ in 1...times { 
         result += s
         }
         return result 
       }
      
        let s = echoString("hi", times:3)
      

      func echo(string s:String, times n:Int) -> String {
      var result = ""
      for _ in 1...n { result += s}
      return result
      }
      // 使用
      let s = echo(string:"hi", times:3)
      In the body of that function, there is now no times variable available; times is purelyan external name, for use in the call. The internal name is n

    Overloading:重载

    The legality of overloading in Swift is particularly striking if you’re coming from Objective-C, where overloading is not legal.

    Default Parameter Values:默认的参数值

    class Dog { 
        func say(_ s:String, times:Int = 1) {
           for _ in 1...times { print(s)
            }
        }
    }
    
    let d = Dog() d.say("woof") // same as saying   可以不传有默认值得参数 
    d.say("woof", times:1)
    

    Variadic Parameters:可变参数类型

    func sayStrings(_ arrayOfStrings:String ...) { 
        for s in arrayOfStrings { 
            print(s) 
        }
    }
    // 使用
    sayStrings("hey", "ho", "nonny nonny no")
    

    The global print function takes a variadic first parameter, so you can output multiple
    values with a single command:

    print("Manny", 3, true) // Manny 3 true
    

    可修改的变量

    iOS 10 Programming Fundamentals with Swift

    In the body of a function, a parameter is essentially a local variable. By default, it’s avariable implicitly declared with let. You can’t assign to it:

     func say(_ s:String, times:Int, loudly:Bool) { 
        loudly = true // compile error
    }
    
    func say(_ s:String, times:Int, loudly:Bool) { 
        var loudly = loudly 
        loudly = true // no problem
    }
    

    inout关键字:

    func removeCharacter(_ c:Character, from s: inout String) -> Int {
         var howMany = 0
         while let ix = s.characters.index(of:c) { 
            s.remove(at:ix)
            howMany += 1
         }
        return howMany 
    }
    // 使用:
    var s = "hello"
    let result = removeCharacter("l", from:&s)  // 结果的话,s = "heo"
    

    注意:The Cocoa APIs are written in C and Objective-C

    注意:

    Technically, we say that classes are reference types, whereas the other object type flavors are value types. When you pass an instance of a struct as an argument to afunction, you effectively wind up with a separate copy of the struct instance. But when you pass an instance of a class as an argument to a function, you pass areference to the class instance itself.
    引用类型和值类型的区别在方法中,这个特别重要。

    Function In Function:内部方法

    func checkPair(_ p1:Piece, and p2:Piece) -> Path? { 
        // ...
    
        func addPathIfValid(_ midpt1:Point, _ midpt2:Point) { 
        // ...
    
         } 
        
        for y in -1..._yct {
             addPathIfValid((pt1.x,y),(pt2.x,y)) 
        }
        for x in -1..._xct { 
            addPathIfValid((x,pt1.y),(x,pt2.y))
        }
        // ...
    }
    

    Recursion:递归

    func countDownFrom(_ ix:Int) {
         print(ix)
        if ix > 0 { // stopper 
            countDownFrom(ix-1) // recurse!
        }
    }
    

    Function As Value

    函数可以作为值来使用:

    func doThis(_ f:()->()) { 
        f()
    }
    

    在之前讲过,()->(),这样的除去函数名,方法体,只留下参数和返回值,称为函数署名,函数标志。(可以说是一种函数的类型)

     func doThis(_ f:()->()) { 
        f()
     } 
     func whatToDo() {
         print("I did it") 
     }
     doThis(whatToDo) // i did it 会被打印
    

    Type Aliases Can Clarify Function Types:类型别名

    typealias VoidVoidFunction = () -> () 
    func dothis(_ f:VoidVoidFunction) {
        f()
    }
    

    Anonymous Functions:匿名函数

    let arr = [2, 4, 6, 8] 
    func doubleMe(i:Int) -> Int {
        return i*2
    }
    let arr2 = arr.map(doubleMe) // [4, 8, 12, 16]
    

    等价于:

    let arr = [2, 4, 6, 8] 
    let arr2 = arr.map ({ 
        (i:Int) -> Int in
    return i*2
    })
    

    因为在其他的地方不需要用到doubleMe这个函数,所以可以直接用匿名函数
    也等价于:

    let arr = [2, 4, 6, 8] 
    let arr2 = arr.map {$0*2}
    

    Its parameter type isknown in advance, so we don’t need to specify that. Its return type is known byinspection of the function body, so we don’t need to specify that. There’s just oneparameter and we are going to use it, so we don’t need the in line as long we refer tothe parameter as $0. Our function body consists of just one statement, and it is areturn statement, so we can omit return. And map(_:) doesn’t take any otherparameters, so we can omit the parentheses and follow the name directly with a trail‐ing function.

    Swift 自动为内联函数提供了参数名称缩写功能,您可以直接通过$0,$1,$2来顺序调用闭包的参数。

    如果您在闭包表达式中使用参数名称缩写,您可以在闭包参数列表中省略对其的定义,并且对应参数名称缩写的类型会通过函数类型进行推断in关键字也同样可以被省略,因为此时闭包表达式完全由闭包函数体构成:

    reversed = sorted(names, { $0 > $1 } )
    

    在这个例子中,$0$1表示闭包中第一个和第二个String类型的参数。

    Define-and-Call

    { 
         // ... code goes here
    }()
    

    i.e.

    let para = NSMutableParagraphStyle()    
    para.headIndent = 10 
    para.firstLineHeadIndent = 10 // ... more configuration of para ... 
    content.addAttribute( // content is an   
        NSMutableAttributedString
        NSParagraphStyleAttributeName, 
        value:para,    
        range:NSRange(location:0, length:1))
    

    我们可以替换为:

     content.addAttribute(     
        NSParagraphStyleAttributeName, value: {
         let para = NSMutableParagraphStyle()    
        para.headIndent = 10 
        para.firstLineHeadIndent = 10
        // ... more configuration of para ...
        return para }(),
        range:NSRange(location:0, length:1))
    

    Closure:闭包

    Swift functions are closures.

    This means they can capture references to external vari‐ables in scope within the body of the function.

    我们可以吧函数名作为变量使用。

    class Dog { 
        var whatThisDogSays = "woof" 
        func bark() {
             print(self.whatThisDogSays) 
        }
    }
    

    使用:

    func doThis(_ f : (Void) -> Void) { 
        f()
     } 
    let d = Dog() 
    d.whatThisDogSays = "arf" 
    let barkFunction = d.bark   // 这里我们可以直接把函数名作为变量使用
    doThis(barkFunction) // arf
    

    How Closures Improve Code:

    func imageOfSize(_ size:CGSize, _ whatToDraw:() -> ()) -> UIImage {
        UIGraphicsBeginImageContextWithOptions(size, false, 0)
        whatToDraw()
        let result = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()
        return result
    }
    

    我们可以吧闭包写在最后当个尾巴那样写:

    let sz = CGSize(width:45, height:20) 
    let image = imageOfSize(sz) {
        let p = UIBezierPath( roundedRect: CGRect(origin:CGPoint.zero, size:sz), cornerRadius: 8)
        p.stroke()
    }
    

    Function Returning Function:函数返回函数

    这个比较深入

    func makeRoundedRectangleMaker(_ sz:CGSize) -> () -> UIImage { 
        return {
            imageOfSize(sz) { 
            let p = UIBezierPath(
            roundedRect: CGRect(origin:CGPoint.zero, size:sz),
           cornerRadius: 8) 
           p.stroke()
           }
        }
    }
    

    Closure Setting a Captured Variable:闭包设置一个变量

    相关文章

      网友评论

        本文标题:iOS 10: Swift - 2.Founctions方法

        本文链接:https://www.haomeiwen.com/subject/hcilvttx.html