Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
swift组合声明语法_Swift_Variadic_Combine - Fatal编程技术网

swift组合声明语法

swift组合声明语法,swift,variadic,combine,Swift,Variadic,Combine,swiftcombine的声明性语法在我看来很奇怪,似乎有很多事情是不可见的 例如,以下代码示例在Xcode中生成和运行: [1, 2, 3] .publisher .map({ (val) in return val * 3 }) .sink(receiveCompletion: { completion in switch completion { case .failure(let error): print("Something went wr

swiftcombine的声明性语法在我看来很奇怪,似乎有很多事情是不可见的

例如,以下代码示例在Xcode中生成和运行:

[1, 2, 3]

.publisher
.map({ (val) in
        return val * 3
    })

.sink(receiveCompletion: { completion in
  switch completion {
  case .failure(let error):
    print("Something went wrong: \(error)")
  case .finished:
    print("Received Completion")
  }
}, receiveValue: { value in
  print("Received value \(value)")
})
我看到我假设的是一个使用[1,2,3]创建的数组文本实例。我猜它是一个数组文字,但我不习惯看到它“声明”,而不将它赋给变量名或常量或使用=

我有意在之后加入了一个新行。publisher。Xcode是否忽略了空格和换行符

由于这种风格,或者说我对这种风格的视觉分析比较新,我错误地认为“receiveValue:”是一个可变参数或一些新语法,但后来意识到它实际上是.sink(…)的一个参数。

Literals 首先,关于文字。可以在任何可以使用包含相同值的变量的地方使用文字。两者之间没有重要区别

let arr = [1,2,3]
let c = arr.count
let c = [1,2,3].count

空白 第二,关于空格。简单地说,斯威夫特不在乎你是否在一个点之前拆分一条语句。所以两者之间没有区别

let arr = [1,2,3]
let c = arr.count
let c = [1,2,3].count

锁链 当你一个接一个地链接很多函数时,拆分实际上是一种提高易读性的好方法。而不是

let c = [1,2,3].filter {$0>2}.count
写起来更好

let c = [1,2,3]
    .filter {$0>2}
    .count
或者为了更清楚

let c = [1,2,3]
    .filter {
        $0>2
    }
    .count
结论 这就是您展示的代码中所发生的一切:一个文本后跟一长串方法调用。为了便于阅读,它们被分割成不同的行,仅此而已

所以你在问题中提到的与联合收割机无关。这只是Swift语言的基本内容。您所谈论的一切都可能(而且确实)发生在根本不使用Combine的代码中

因此,从语法的角度来看,没有什么是“不可见的”,除了知道每个方法调用返回一个值,下一个方法调用可以应用到该值(就像我在上面的示例代码中,我对
.filter
的结果应用
.count
)。当然,因为您的示例是Combine,所以出现了一些“不可见的情况”,即这些值中的每一个都是发布者、运营商或订阅者(订阅者确实订阅了)。但这基本上只是知道什么是联合收割机的问题。因此:

  • [1,2,3]
    是一个数组,它是一个序列,因此它有一个
    publisher
    方法

  • 可应用于序列的
    publisher
    方法生成发布者

  • map
    方法(Combine的
    map
    ,而不是Array的
    map
    )可以应用于发布者,并生成另一个作为发布者的对象

  • sink
    方法可以应用于此,并生成一个订户,这就是链的末端

首先清理代码 格式化 首先,如果格式正确,阅读/理解此代码会容易得多。让我们从这个开始:

[1, 2, 3]
    .publisher
    .map({ (val) in
        return val * 3
    })
    .sink(
        receiveCompletion: { completion in
            switch completion {
            case .failure(let error):
                print("Something went wrong: \(error)")
            case .finished:
                print("Received Completion")
            }
        },
        receiveValue: { value in
            print("Received value \(value)")
        }
    )
清理
映射
表达式 我们可以通过以下方式进一步清理地图:

  • 使用隐式返回

    map({ (val) in
        return val * 3
    })
    
    map({ (val) in
        val * 3
    })
    
  • 使用隐式返回

    map({ (val) in
        return val * 3
    })
    
    map({ (val) in
        val * 3
    })
    
  • 删除参数声明周围不必要的括号

    map({ val in
        val * 3
    })
    
  • 删除不必要的新行。有时,它们在视觉上很有用,但这是一个足够简单的闭包,它只会添加无需的噪音

    map({ val in val * 3 })
    
  • 使用隐式参数,而不是非描述性的
    val

    map({ $0 * 3 })
    
  • 使用尾随闭包语法

    map { $0 * 3 }
    
  • 最终结果 有编号的行,所以我可以很容易地返回

    /*  1 */[1, 2, 3]
    /*  2 */    .publisher
    /*  3 */    .map { $0 * 3 }
    /*  4 */    .sink(
    /*  5 */        receiveCompletion: { completion in
    /*  6 */            switch completion {
    /*  7 */            case .failure(let error):
    /*  8 */                print("Something went wrong: \(error)")
    /*  9 */            case .finished:
    /* 10 */                print("Received Completion")
    /* 11 */            }
    /* 12 */        },
    /* 13 */        receiveValue: { value in
    /* 14 */            print("Received value \(value)")
    /* 15 */        }
    /* 16 */    )
    
    经历它。 第1行,
    [1,2,3]
    第1行是一个数组文本。它是一个表达式,就像
    1
    “hi”
    true
    someVariable
    1+1
    。这样的数组不需要分配给任何对象就可以使用

    有趣的是,这并不意味着它一定是一个数组。相反,Swift有
    ExpressibleByArrayLiteralProtocol
    。任何一致性类型都可以从数组文本初始化。例如,
    Set
    符合,因此您可以编写:
    let s:Set=[1,2,3]
    ,您将得到一个
    Set
    包含
    1
    2
    3
    。在缺少其他类型信息(例如上面的
    Set
    type注释)的情况下,Swift使用
    Array
    作为首选数组文字类型

    第2行,
    .publisher
    第2行调用数组文本的
    publisher
    属性。这将返回一个
    序列,这是一个非通用协议,但它位于
    组合
    模块的
    发布者
    命名空间(无大小写的枚举)中。因此,它的完全限定类型是

    它是一个
    发布者
    ,其
    输出
    Int
    ,其
    失败
    类型为
    从不
    (即,由于无法创建
    从不
    类型的实例,因此不可能发生错误)

    第3行,
    map
    第3行正在调用
    Combine.publisher.Sequence的
    map
    实例函数(也称为方法)。有两个闭包参数

  • {completion in…}
    闭包作为标记为
    receiveCompletion:
  • {value in…}
    闭包作为标记为
    receiveValue:
  • Sink正在为
    订阅创建一个新订阅服务器,该订阅服务器是一个带有
    .failure(failure)
    案例或
    .finished
    案例的枚举。由于
    Failure
    类型为
    Never
    ,因此实际上不可能在此处创建
    .Failure(Never)
    的值。因此,完成将始终是
    .finished
    ,这将导致
    打印(“接收到的Com”)