问题标签 [ios-multithreading]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
1 回答
520 浏览

ios - 原子属性包装器仅在声明为类而不是结构时才有效

我在 Swift 中创建了一个“锁”,并为我的 Swift 类创建了一个使用该锁的 Atomic 属性包装器,因为 Swift 缺少 ObjC 的atomicproperty 属性。

当我在启用线程清理器的情况下运行测试时,它总是在使用我的 Atomic 属性包装器的属性上捕获数据竞争。

唯一有效的是将属性包装器的声明更改为类而不是结构,这里的主要问题是:为什么它有效!

print在属性包装器中添加了 s 和 lockinit来跟踪创建的对象的数量,它与 struct/class 相同,尝试在另一个项目中重现问题,也没有用。但我会添加与问题相似的文件,并让我知道它为什么起作用的任何猜测。

原子属性包装器

模型(数据竞争应该发生在publicVariable2此处的属性上)

更新 1: 完整的 Xcode 项目:https ://drive.google.com/file/d/1IfAsOdHKOqfuOp-pSlP75FLF32iVraru/view?usp=sharing

0 投票
1 回答
71 浏览

ios - ViewDidAppear 不从 Firebase 更新我的图片,但更新文本信息

我对 IOS 编程还是很陌生,在使用 Firebase 数据库和存储时遇到了问题。这是图像:

编辑文件之前

这是配置文件在编辑之前的样子。如果用户点击编辑按钮,我们将进入编辑模式。

编辑期间

在编辑过程中,我们更改了它的名称、描述、人物图标和横幅图片,当我们完成它时,它会回到这个配置文件并查看更新的文件。但是,编辑后,它返回的是这样的:

编辑后

名称和描述确实改变了,但头像没有改变。事实上,如果我再次编辑配置文件,它将更新到我更改的最后一张图片。如果我退出并返回个人资料页面,它将显示正确的图片,这是最后更新的图片。这是我在配置文件视图控制器中的代码:

并且函数ViewDidAppear是完全相同的代码(除了super.viewDidAppear(animated))。我觉得这与线程有关,因为我确实将下载线程与主线程异步以确保配置文件得到更新,但我对 IOS 中的线程仍然很陌生,无法判断这是否是这里的问题. 请帮忙,谢谢!

编辑用户信息的代码:

让我知道您是否还需要在DataManager. 它是一个包含 Firebase 数据库 API 调用的辅助类。

代码viewDidAppear()

更新:感谢@Pratik Prajapati,问题是我在图片更新之前过早地刷新了页面,所以我已经将我的代码重新写入其中,并且它有效!

但是,我确实认为这不是正确的方法。我实际上已经将 3 个完成块链接在一起,上传实际上需要一秒钟才能从编辑切换回配置文件。我肯定做错了什么。关于如何改进此代码的任何建议?如果我有 10 个信息而不是 3 个要更新怎么办?我不能将 10 个完成块链接在一起!

无论如何,感谢提供信息的家伙。我确实学到了很多东西!

0 投票
0 回答
39 浏览

ios - iOS NSInternalInconsistencyException 线程冲突崩溃

我有一个第三方 iOS 应用程序使用的 iOS SDK 项目,最近报告了围绕 SDK 中一个 API 的崩溃,原因是:

第三方应用程序调用的 API 是异步的,它在后台线程中异步执行一些操作,并在主线程上向调用者返回一个回调。

我知道在后台线程而不是主线程中执行 UI 操作时经常会引发此异常。

但是,我不明白为什么仍然会发生这种情况,因为在该 SDK API 中,在将回调返回给调用者之前,我有以下代码来确保调用者在主线程上获得回调:

堆栈跟踪:

调用者是否仍有可能在后台线程中获得回调?

0 投票
1 回答
144 浏览

ios - 如何将 newBackgroundContext() 与 URLSession.shared.dataTaskPublisher 一起使用?

在 Github 创建了一个简单的 Core Data 项目来演示我的问题:

Xcode 截图

我的测试应用程序下载一个 JSON 对象列表,将其存储在 Core Data 中,并通过@FetchRequest.

因为对象列表在我的真实应用程序中有 1000 多个元素,所以我想将实体保存到后台线程而不是主线程上的核心数据中。

最好我想使用URLSession.shared.dataTaskPublisher已经使用的相同的默认后台线程。

所以在 Xcode 生成的标准Persistence.swift中,我只添加了 2 行:

在我的DownloadManager.swift单例中,我调用:

正如您在上面的屏幕截图中看到的那样,这失败了

线程 4:EXC_BAD_INSTRUCTION(代码=EXC_I386_INVOP,子代码=0x0)

因为我在 Xcode 中添加了以下“启动时传递的参数”:

-com.apple.CoreData.ConcurrencyDebug 1

谁能告诉我,如何newBackgroundContext()在正确的线程上调用?

更新:

我试图解决我的问题,如下面的代码,但错误是一样的:

更新 2:

我假设当newBackgroundContext()被调用时,它会占用当前线程,然后您可以从同一个线程使用该上下文......

情况似乎并非如此,我必须调用perform,performAndWait或(我已经在 GithubperformBackgroundTask上更新了我的代码来做到这一点)。

仍然我想知道,如果线程newBackgroundContext可以与URLSession.shared.dataTaskPublisher...

0 投票
0 回答
21 浏览

swift - iOS Swift DispatchQueue,在将新任务添加到队列之前等待当前任务结束

在将 DispatchQueue 用作 SerialQueue 时,如何在添加新任务之前等待队列上的当前活动进程/任务完成处理,以避免 DispatchQueue 被大量任务阻塞。

在 java 中,我们可以通过使用最大池大小为 1 的 ThreadPoolExecutor 来实现这一点,并在开始另一个任务之前检查内部队列是否为空。

iOS Swift 中是否有类似的东西来实现这一点?

0 投票
1 回答
62 浏览

ios - SwiftUI:将 MLKit 结果返回给 SwiftUI 视图不起作用

我有一个具有以下功能的 ScannerService 类:

我从 ScannerView 调用此函数:

}

现在,我返回的是一个空字符串,而不是来自 MLKit TextRecognizer 的结果。经过一些调试,我意识到这与函数在 textRecognizer.process(visionImage) 完成之前完成有关——因为如果我在该函数中放置一个打印语句,它会显示正确的结果。

我试图放置一个 DispatchQueue.main.async,但是,我仍然无法及时获得打印结果——但是,作为线程新手,我不确定在哪里使用它。

当我单击扫描按钮时,结果返回空,但是,当我再次单击扫描按钮时,我可以在控制台中看到之前检测到的文本。

想知道在这里让 detectText 函数完成以便可以在 UI 中使用结果的最佳方法是什么。

0 投票
0 回答
30 浏览

swift - 迅速。在其他线程中运行时在原始线程中执行代码

我有使用 SwiftUI 编码的 iOS 应用程序。部分代码来自 Kotlin multiplatform (kmm) 我需要对异步代码做一些工作,它必须在单独的线程中执行。但我也有回调要在线程执行期间运行并且回调失败,因为可变性限制(kotlin 防止对象从一个线程共享到另一个线程)任务是逐行通过 url 读取文件。并向回调对象发送线路问题是回调对象是在外部创建的。

代码与此类似

我启动新线程 Thread {},当我执行 self.callback.OnStart(totalLines: size) 时出现错误“未捕获的 Kotlin 异常:kotlin.native.IncorrectDereferenceException:非法尝试访问非共享”

我不能冻结那个对象,因为它里面有一些计数器,它必须是可变的。

所以,我的问题是:有没有办法在“外部线程”中执行我的回调调用?在我在函数中调用 Thread {} 之前处于活动状态的线程中。

注意,我在这里使用 Thread 只是因为 URLSession.shared.bytes 是异步的,并且需要在线程中运行。无论如何,我调用线程并等待信号量。

在调用 Thread {} 之前,可能类似于 let originalThread = Thread.current 。然后以某种方式使用该值访问前一个线程?

另外,我知道 DispatchQueue 。但我不知道我的函数是否是从主 swift 线程调用的,所以我不会尝试执行 DispatchQueue.main.async { } 因为原始线程可能不同。也许 DispatchQueue 可以用于我用 Thread.current 捕获的原始线程?

你对我有什么想法吗?

0 投票
1 回答
46 浏览

swift - 调度组崩溃

我创建了一种从 Firebase 获取用户消息的方法,但是当离开DispatchGroup应用程序崩溃时会导致此错误Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)

我不确定我做错了什么。请帮助和解释我。

代码: