我正在尝试找出适合在Swift中使用的单例模型.到目前为止,我已经能够得到一个非线程安全模型:
class var sharedInstance: TPScopeManager {
get {
struct Static {
static var instance: TPScopeManager? = nil
}
if !Static.instance {
Static.instance = TPScopeManager()
}
return Static.instance!
}
}
Run Code Online (Sandbox Code Playgroud)
在Static结构中包装单例实例应允许单个实例在没有复杂命名方案的情况下不与单例实例发生冲突,并且它应该使事情变得相当私密.显然,这个模型不是线程安全的,所以我尝试将dispatch_once添加到整个事情中:
class var sharedInstance: TPScopeManager {
get {
struct Static {
static var instance: TPScopeManager? = nil
static var token: dispatch_once_t = 0
}
dispatch_once(Static.token) { Static.instance = TPScopeManager() }
return Static.instance!
}
}
Run Code Online (Sandbox Code Playgroud)
但我得到一个编译器错误dispatch_once:
无法将表达式的类型'Void'转换为'()'类型
我已经尝试了几种不同的语法变体,但它们似乎都有相同的结果:
dispatch_once(Static.token, { Static.instance = TPScopeManager() })
Run Code Online (Sandbox Code Playgroud)
dispatch_once使用Swift 的正确用法是什么?我最初认为问题出在块中,因为dispatch_once错误消息,但我看的越多,我认为可能是获得() …
我有快速的线程问题.我有一个包含一些对象的数组.在委托上,类每秒都会获得新对象.之后我必须检查对象是否已经在数组中,所以我必须更新对象,否则我必须删除/添加新对象.
如果我添加一个新对象,我必须首先通过网络获取一些数据.这是handelt经过一个街区.
现在我的问题是,如何同步这项任务?
我尝试了一个dispatch_semaphore,但是这个阻止了UI,直到块完成.
我还尝试了一个简单的bool变量,它检查块当前是否执行并同时跳过compare方法.
但这两种方法都不理想.
什么是管理阵列的最佳方式,我不想在阵列中有重复的数据.
我最近看了WWDC GCD的谈话,我认为有一个代码片段有问题.它是关于使用DispatchQueues使属性线程安全.
class MyObject {
private var internalState: Int
private let internalQueue: DispatchQueue // Serial or Concurrent?
var state: Int {
get {
return internalQueue.sync { internalState }
}
set (newState) {
internalQueue.sync { internalState = newState }
}
}
}
Run Code Online (Sandbox Code Playgroud)
他们使用DispatchQueue来锁定属性.但我认为这个片段无效,因为internalQueue可能是并发的.所以,如果我们所说的setter从两个不同的DispatchQueues /线程如果内部队列中不连续,这也可能导致右线程问题?因为在我的理解中,sync只保存调用线程,并在任务完成时继续.你觉得这个片段怎么样?我错了吗?
我经常碰到“线程安全”这两个关键术语,想知道这意味着什么。例如,在Firebase或Realm中,某些对象被视为“线程安全”。线程安全的东西到底意味着什么?
示例A: - 这会导致App Crash.
DispatchQueue.main.async {
let url = URL(string: imageUrl)
do {
let data = try Data(contentsOf: url!)
DispatchQueue.main.sync {
self.imageIcon.image = UIImage(data: data)
}
}
Run Code Online (Sandbox Code Playgroud)
例B: - 但事实并非如此
DispatchQueue.global().async {
let url = URL(string: imageUrl)
do {
let data = try Data(contentsOf: url!)
DispatchQueue.main.sync {
self.imageIcon.image = UIImage(data: data)
}
}
Run Code Online (Sandbox Code Playgroud)
据我所知,
Quest1: - 那么为什么我的应用程序在后台线程(即main.async)执行任务时崩溃,而不是调用主线程来更新UI.
Quest2: - main.async和global().async有什么区别.
下面的代码据说可以设置一个线程安全的单例:
class Singleton {
static var shared = Singleton()
private let internalQueue = DispatchQueue(label: "SingletionInternalQueue", qos: .default, attributes: .concurrent)
private var _foo: String = "aaa"
var foo: String {
get {
return internalQueue.sync { _foo }
}
set (newState) {
internalQueue.async(flags: .barrier) { self._foo = newState }
}
}
func setup(string: String) {
foo = string
}
}
Run Code Online (Sandbox Code Playgroud)
但我不明白这个目的.
例如,如果我希望get价值foo,我不应该只是阅读它吗?应始终在主线程上执行操作,那么添加另一个线程又有什么意义呢?
与此类似set:如果我担心同时设置值的多个源,我们不能简化该代码并消除.barrier参数吗?
internalQueue.async(flags: .barrier) { self._foo = newState}
Run Code Online (Sandbox Code Playgroud)
如果它在一个sync块中,是不是强制它进入主线程?如果是这样,那为什么代码不需要 …