小编dea*_*.dg的帖子

在 Swift 5.5 中如何等待来自同步函数的异步函数?

当遵守协议或重写超类方法时,您可能无法将方法更改为async,但您可能仍然想调用一些async代码。例如,当我正在重写一个根据 Swift 新的结构化并发编写的程序时,我想async通过class func setUp()覆盖XCTestCase. 我希望我的设置代码在任何测试运行之前完成,因此使用Task.detachedorasync { ... }是不合适的。

最初,我写了一个这样的解决方案:

final class MyTests: XCTestCase {
    override class func setUp() {
        super.setUp()
        unsafeWaitFor {
            try! await doSomeSetup()
        }
    }
}

func unsafeWaitFor(_ f: @escaping () async -> ()) {
    let sema = DispatchSemaphore(value: 0)
    async {
        await f()
        sema.signal()
    }
    sema.wait()
}
Run Code Online (Sandbox Code Playgroud)

这似乎运作良好。然而,在《Swift 并发:幕后花絮》中,运行时工程师 Rokhini Prabhu 指出:

信号量和条件变量等基元与 Swift 并发一起使用是不安全的。这是因为它们隐藏了 Swift 运行时的依赖信息,但在代码的执行中引入了依赖关系……这违反了线程前进的运行时契约。

她还包含了这种不安全代码模式的代码片段

func updateDatabase(_ …
Run Code Online (Sandbox Code Playgroud)

grand-central-dispatch async-await swift swift5

33
推荐指数
1
解决办法
1万
查看次数

Swift:类型别名和在协议中带有值的关联类型有什么区别?

在 Swift 中,以下代码编译没有问题。

protocol P1 {
    associatedtype T = Int
}

protocol P2 {
    typealias T = Int
}
Run Code Online (Sandbox Code Playgroud)

对我来说,这些似乎表现得几乎相同。我注意到的唯一区别是对何时可以使用有额外的限制,P1因为它具有关联类型。特别是,let x: P1是一个错误而let x: P2很好。

这两种协议之间的实际区别是什么?它们在编译代码中的处理方式不同吗?最后,使用P1而不是有优势P2吗?

为清楚起见编辑:

我知道关联类型和类型别名之间的工作差异,所以我很惊讶你甚至可以给关联类型一个固定值。这似乎违背了关联类型的全部目的。我想知道是否有任何实用程序可以为关联类型提供固定值,并且我想知道这两个协议在编译后是否不同。

type-alias associated-types swift swift-protocols

8
推荐指数
1
解决办法
2355
查看次数

Swift 中是否可以要求关联类型符合关联类型的关联协议?

我正在尝试(基本上没有任何理由)制定一个协议来描述类别理论中的类别。我试图想出这样的东西。

protocol Category {
    associatedtype Object: Protocol
}
protocol Hom {
    associatedtype C: Category
    associatedtype Source: C.Object
    associatedtype Target: C.Object
}
Run Code Online (Sandbox Code Playgroud)

特别是,我希望每个 Hom 类型都有一个关联的类别 C 以及关联的源和目标类型,它们都是该类别中的对象。因此,我将一个对象协议与每个类别相关联,并尝试使 Hom 的源和目标符合相应类别的对象协议。上面的代码无法编译

Type 'Self.Source' constrained to non-protocol, non-class type 'Self.C.Object'
Run Code Online (Sandbox Code Playgroud)

这个错误至少不清楚,因为 C.Object 被声明为协议。有什么办法可以解决这个问题吗?

编辑:

正如 Rob 所指出的,代码本身没有多大意义。Protocol 是 ObjC 中的一个特定类,而不是描述协议的类型。此外,不存在描述所有协议的类型,因为协议本身不能符合协议,因为它们只是对其他类型的要求。我正在寻找的是一个元类型,其中 Any.Protocol、Sequence.Protocol 等都是其实例。

我将更详细地说明我试图描述哪种结构。

类别是一个对象类型以及每对对象实例之间的同态类型。对于 Object 的两个实例 A 和 B,同态类型通常写为 Hom(A,B),但我会写Hom<A,B>为 Swiftier。然后类别配备有带有签名的组合<A: Object, B: Object, C: Object>(_ f: Hom<A,B>, _ g: Hom<B,C>) -> Hom<A,C>

如果 f 是 的实例Hom<A,B>,则 A …

associated-types swift swift-protocols

5
推荐指数
1
解决办法
1971
查看次数

仅当从 Xcode 运行时,Swift 包调用 /usr/bin/swift 时出现“无法打开 macho 文件...符号链接级别过多”错误

我正在 Swift 中开发一个命令行应用程序,它将调用来swift初始化包、编译东西、测试东西等。我正在使用 swift 包管理器和 Xcode。在我的工具中,我swiftProcess. 如果我从命令行运行我的工具,那么效果很好。但是,如果我从 Xcode 运行我的工具,一些奇怪的事情会打印到标准错误中。特别是,我得到

Failed to open macho file at /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift for reading: Too many levels of symbolic links
Run Code Online (Sandbox Code Playgroud)

是什么原因造成的?有什么方法可以避免它,或者我可以不从 Xcode 运行/测试这个实用程序吗?

以下是重现步骤:

mkdir XcodeRedirectionTest
cd XcodeRedirectionTest
swift package init
open Package.swift
Run Code Online (Sandbox Code Playgroud)

然后在 中Tests/XcodeRedirectionTestTests/XcodeRedirectionTestTests.swift,粘贴

Failed to open macho file at /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift for reading: Too many levels of symbolic links
Run Code Online (Sandbox Code Playgroud)

在 Xcode 中测试失败并显示

file://.../XcodeRedirectionTest/Tests/XcodeRedirectionTestTests/XcodeRedirectionTestTests.swift: test failure: XcodeRedirectionTestTests.testExample() failed: XCTAssertEqual failed: ("2021-05-18 19:43:18.084463-0400 swift[2836:4100702] Failed to open macho file …
Run Code Online (Sandbox Code Playgroud)

xcode swift swiftpm

2
推荐指数
1
解决办法
766
查看次数

在便利初始值设定项中使用 `self =` 委托给 JSONDecoder 或 Swift 中的工厂方法,以避免 `Cannotassign to value: 'self' is immutable`

有时在 Swift 中,为委托JSONDecoder或工厂方法的类编写初始化程序可能会很方便。例如,一个人可能想写

final class Test: Codable {
    let foo: Int
    
    init(foo: Int) {
        self.foo = foo
    }
    
    func jsonData() throws -> Data {
        try JSONEncoder().encode(self)
    }
    
    convenience init(fromJSON data: Data) throws {
        self = try JSONDecoder().decode(Self.self, from: data)
    }
}

let test = Test(foo: 42)
let data = try test.jsonData()
let decodedTest = try Test(fromJSON: data)
print(decodedTest.foo)
Run Code Online (Sandbox Code Playgroud)

但这无法编译

Cannot assign to value: 'self' is immutable.
Run Code Online (Sandbox Code Playgroud)

解决此问题的解决方案是什么?

initializer swift

2
推荐指数
1
解决办法
48
查看次数