Swift:扩展 [?] 来生成 [?] 可能吗?

2024-04-26

在 Swift 中,我有一个具有以下基本前提的自定义结构:

一个包装结构体,可以包含符合以下条件的任何类型BinaryInteger如Int、UInt8、Int16等

protocol SomeTypeProtocol {
    associatedtype NumberType

    var value: NumberType { get set }
}

struct SomeType<T: BinaryInteger>: SomeTypeProtocol {
    typealias NumberType = T

    var value: NumberType
}

还有 Collection 的扩展:

extension Collection where Element: SomeTypeProtocol {
    var values: [Element.NumberType] {
        return self.map { $0.value }
    }
}

例如,这很好用:

let arr = [SomeType(value: 123), SomeType(value: 456)]

// this produces [123, 456] of type [Int] since literals are Int by default
arr.values

我想做的是完全相同的事情,但是对于SomeType<T>?

let arr: [SomeType<Int>?] = [SomeType(value: 123), SomeType(value: 456)]

// this doesn't work, obviously
arr.values

// but what I want is this:
arr.values // to produce [Optional(123), Optional(456)]

我已经尝试了无数次尝试来解决这个问题,并进行了大量的研究,但我希望任何明智的 Swift 老手都能对此有所启发。

这就是我想象的样子,但这行不通:

extension Collection where Element == Optional<SomeType<T>> {
    var values: [T?] {
        return self.map { $0?.value }
    }
}

这是一种在不使用泛型的情况下实现目标的笨拙方法,但它有效:

extension Collection where Element == Optional<SomeType<Int>> {
    var values: [Int?] {
        return self.map { $0?.value }
    }
}

let arr: [SomeType<Int>?] = [SomeType(value: 123), SomeType(value: 456)]
arr.values // [Optional(123), Optional(456)]

但它需要为每个符合 BinaryInteger 的已知类型手动编写扩展,并且在不手动更新代码的情况下不会自动包含采用 BinaryInteger 的未来可能的类型。

// "..." would contain the var values code from above, copy-and-pasted
extension Collection where Element == Optional<SomeType<Int>> { ... }
extension Collection where Element == Optional<SomeType<Int8>> { ... }
extension Collection where Element == Optional<SomeType<UInt8>> { ... }
extension Collection where Element == Optional<SomeType<Int16>> { ... }
extension Collection where Element == Optional<SomeType<UInt16>> { ... }
extension Collection where Element == Optional<SomeType<Int32>> { ... }
extension Collection where Element == Optional<SomeType<UInt32>> { ... }
extension Collection where Element == Optional<SomeType<Int64>> { ... }
extension Collection where Element == Optional<SomeType<UInt64>> { ... }

2018 年 6 月 23 日编辑:

解决方案 #1 - 完全通用但必须是 Func,而不是计算属性

扩展于奥莱的回复 https://stackoverflow.com/a/51001112/2805570:

优点:如果values()成为一个func而不是计算属性,这是一个优雅的解决方案。

缺点:没有已知的方法可以将此方法实现为计算属性,并且 Swift 的快速帮助弹出窗口在检查时显示 [T] 和 [T?]values()在你的代码中。即:它只是说func values<T>() -> [T] where T : BinaryInteger这不是很有信息或 Swifty。然而,它当然仍然是强类型的。

extension Collection {
    func values<T>() -> [T] where Element == SomeType<T> {
        return map { $0.value }
    }

    func values<T>() -> [T?] where Element == SomeType<T>? {
        return map { $0?.value }
    }
}

解决方案 #2 - 可选协议解决方法

扩展于马丁的回复 https://stackoverflow.com/a/50999846/2805570:

优点:允许使用计算属性(最终用户访问起来更干净,因为它不需要 func 括号)并在 Xcode 的快速帮助弹出窗口中显示推断的类型。

缺点:从内部代码的角度来看并不那么优雅,因为它需要解决方法。但不一定是缺点。

// Define OptionalType

protocol OptionalType {
    associatedtype Wrapped
    var asOptional: Wrapped? { get }
}

extension Optional: OptionalType {
    var asOptional: Wrapped? {
        return self
    }
}

// Extend Collection

extension Collection where Element: SomeTypeProtocol {
    var values: [Element.NumberType] {
        return self.map { $0.value }
    }
}

extension Collection where Element: OptionalType, Element.Wrapped: SomeTypeProtocol {
    var values: [Element.Wrapped.NumberType?] {
        return self.map { $0.asOptional?.value }
    }
}

马丁·R的回答 https://stackoverflow.com/a/50999846是一个很好的解决方案。不需要额外标记协议的替代方案是:编写一个不受约束的扩展于Collection,并在该扩展中定义一个通用函数,即受约束的 to where Element == SomeType<T>?:

extension Collection {
    func values<T>() -> [T?] where Element == SomeType<T>? {
        return map( { $0?.value })
    }
}

这有效:

let arr: [SomeType<Int>?] = [SomeType(value: 123), SomeType(value: 456)]
arr.values() // [Optional(123), Optional(456)]

你会注意到我使用了func而不是计算属性。我无法正确理解通用语法。这不是应该起作用吗?

extension Collection {
    // error: consecutive declarations on a line must be separated by ';'
    var values<T>: [T?] where Element == SomeType<T>? {
        return self.map( { $0?.value })
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Swift:扩展 [?] 来生成 [?] 可能吗? 的相关文章

  • 在Java中将浮点数组写入文件

    我正在读取 NetCDF 文件 我想将每个数组作为浮点数组读取 然后将浮点数组写入新文件 如果我读取浮点数组 然后迭代数组中的每个元素 使用 DataOutputStream 我可以使其工作 但这非常非常慢 我的 NetCDF 文件超过 1
  • 操作按钮未出现在通知 iOS 10 中

    我在我的应用程序中使用本地推送通知 在 iOS 10 中为通知添加操作按钮时 它不会出现在通知下方 通知正在显示 但通知底部缺少操作按钮 下面给出了 appdelegate 代码 import UIKit import CoreData i
  • 图表无法在 Xcode 14 上编译

    我在图书馆中面临以下错误 Type 图表数据集 不符合协议 范围可替换集合 实例方法不可用 替换Subrange with 用于满足协议的要求 范围可替换集合 将其附加到扩展 ChartDataSet RangeReplaceableCol
  • 声纳违规:安全性 - 使用 byte[] 时直接存储数组

    我确实遇到过以下两篇关于类似问题的帖子声纳违规 https stackoverflow com questions 11580948 sonar violation security array is stored directly and
  • 按下后退按钮时 SwiftUI 工具栏项目被剪裁

    我在 SwiftUI 中遇到了一种奇怪的行为 我似乎无法解决它 鉴于以下简单的示例应用程序 我遇到了这种行为 工具栏项目在初始运行时正确呈现 但导航离开并返回它会被剪切 重新创建此示例代码 内容视图 swift import SwiftUI
  • 在 C# 中通过 C DLL 使用数组和指针

    我对 C 非常陌生 上周才开始学习 我有一个用 C 编写的自定义 DLL 具有以下函数 DLLIMPORT void test function double test 我想要做的是从 C 获取数组 test 的指针 因此 如果在 DLL
  • 指向字节数组的指针

    由于 Misra C 的要求 我的一位同事想要使用指针声明 但我遇到了一些问题 Misra 安全关键指南 不会让我们纯粹的程序员使用指针 但会让我们对数组字节进行操作 他打算获取一个指向字节数组的指针 因此我们不会在堆栈上传递实际的数组 T
  • 使用 Core Data Swift 对 TableView 和行进行分区

    我在 sqlite 中有两个表 代码由 XCode Generation 生成 class Event NSManagedObject NSManaged var startDate NSDate NSManaged var details
  • 如何在 PHP 中对数组和数据进行排序?

    这个问题旨在作为有关 PHP 中数组排序问题的参考 人们很容易认为您的特定案例是独特的并且值得提出新问题 但大多数实际上只是此页面上的解决方案之一的微小变化 如果您的问题因与此问题重复而被关闭 请仅在您能解释为什么它与以下所有问题显着不同的
  • SwiftUI TabbedView 仅显示第一个选项卡的内容

    我正在尝试建立一个TabbedView使用以下简单代码 TabbedView Text Hello world tabItemLabel Text Hello Text Foo bar tabItemLabel Text Foo 运行时 两
  • Java:带有 unicode 字符的 String.toCharArray()

    我知道 char 不能包含 Unicode 字符 例如 char c u1023 那么我该怎么做 String s ABCDEFG u1023 char c s toCharArray 出于性能原因 我想将 s 转换为 CharArray
  • Swift 生成器上的链式表达式错误

    迅速回复 zip 1 2 3 7 8 9 generate next repl swift 1 22 error value of type Zip2Generator
  • Java:如何实现3和?

    我正在研究 3 Sum 来自己实现它 并遇到了以下规则的实现 给定一个由 n 个整数组成的数组 S S 中是否存在满足 a b c 0 的元素 a b c 查找数组中所有总和为零的唯一三元组 注意 三元组 a b c 中的元素必须按非降序排
  • iOS 8 UITableView 分隔符插入 0 不起作用

    我有一个应用程序 其中UITableView的分隔符插入设置为自定义值 右0 Left 0 这完美地适用于iOS 7 x 但是在iOS 8 0我看到分隔符插入设置为默认值15在右侧 即使在 xib 文件中它设置为0 它仍然显示不正确 我该如
  • 为什么我的matchedGeometryEffect根据右下点移动?

    我只是尝试使用matchedGeometryEffect 制作一些动画 但是 存在一个错误 即该对象是根据右下点而不是中心进行动画处理的 我使用的代码在这里 import SwiftUI struct Test View Namespace
  • 将深层链接传递到 iOS 模拟器?

    我想找到一种更简单的方法来在 iOS 模拟器中调用深层链接 在 Android 上 您可以使用 ADB 通过控制台将链接传输到模拟器中 是否有类似的方法或解决方法来打开最新 iOS 模拟器的深层链接 您可以在终端中输入以下内容 xcrun
  • 如何将计算值转换为文字以进行枚举初始化

    我遇到了枚举的问题 因为我想将 case 初始化为双精度值PI 180 有没有办法通过常量或一些时髦的魔法获取这个计算值并将其转换为文字 以便我可以初始化枚举 我宁愿不必做3 14 我宁愿使用该值的实际编译器和硬件计算表示 所以我的第一次尝
  • 删除接口中的冗余类型

    我有以下接口 public interface IRevision
  • 编辑模板身份验证 Firebase

    您好 我使用 Firebase 启动了一个新应用程序 然后执行身份验证方法 但我需要编辑电子邮件地址验证和更改电子邮件地址的模板 这两个选项无法编辑 但重置密码后可以编辑模板 字段 消息 该消息仅在选项 电子邮件地址验证和更改电子邮件地址
  • PowerShell 与 MongoDB C# 驱动程序方法不兼容?

    由 C 泛型引起的最新 MongoDB 驱动程序的问题 Cannot find an overload for GetCollection and the argument count 1 我可能可以使用其他没有泛型的 GetCollect

随机推荐