同时访问0x1c0a7f0f8,但修改需要对Xcode 9 beta 4进行互斥访问错误 [英] Simultaneous accesses to 0x1c0a7f0f8, but modification requires exclusive access error on Xcode 9 beta 4
问题描述
我的项目同时使用Objective-C和Swift代码.当用户登录时,它会调用一组用于用户首选项的api,我有一个DataCoordinator.swift类来计划API操作,并且我从UserDetailViewController.m类进行了此调用以加载用户首选项.在我使用Xcode 9 beta 4将代码迁移到Swift 4之前,这种方法可以正常工作.现在,当我登录时,通过在DataCoordinator类中给出此错误,它崩溃了.下面是我的DataCoordinator和Viewcontroller类的示例.
my project uses both Objective-C and Swift code. When a user logs in, it calls a set of apis for user preference, I have a DataCoordinator.swift class which schedules the API operation and I make this calls from UserDetailViewController.m class to load user preferences. This use to work fine before I migrated my code to Swift 4 using Xcode 9 beta 4. Now when I login it crashes by giving me this error in my DataCoordinator class. Below is a sample of my DataCoordinator and Viewcontroller class.
DataCoordinator.swift
import UIKit
@objcMembers
class DataCoordinator: NSObject {
//MARK:- Private
fileprivate var user = myDataStore.sharedInstance().user
fileprivate var preferenceFetchOperations = [FetchOperation]()
fileprivate func scheduleFetchOperation(_ operation:FetchOperation, inFetchOperations operations:inout [FetchOperation]) {
guard operations.index(of: operation) == nil else { return }
operations.append(operation)
}
fileprivate func completeFetchOperation(_ fetchOperation:FetchOperation, withError error:Error?, andCompletionHandler handler:@escaping FetchCompletionHandler) {
func removeOperation(_ operation:FetchOperation, fromOperations operations:inout [FetchOperation]) {
if operations.count > 0 {
operations.remove(at: operations.index(of: fetchOperation)!)
handler(error)
}
}
if preferenceFetchOperations.contains(fetchOperation) {
removeOperation(fetchOperation, fromOperations: &preferenceFetchOperations)
}
}
fileprivate func schedulePreferencesFetchOperation(_ serviceName:String, fetch:@escaping FetchOperationBlock){
let operation = FetchOperation(name: serviceName, fetch: fetch);
scheduleFetchOperation(operation, inFetchOperations: &preferenceFetchOperations)
}
fileprivate func runOperationsIn(_ fetchOperations:inout [FetchOperation]) {
for var operation in fetchOperations {
guard operation.isActivated == false else { continue }
operation.isActivated = true
operation.execute()
}
}
//MARK:- Non-Private
typealias FetchCompletionHandler = (_ error:Error?)->Void
var numberOfPreferencesFetchCalls:Int {
get { return preferenceFetchOperations.count }
}
// MARK: -
func fetchPreferences(_ completionHandler:@escaping FetchCompletionHandler) -> Void {
defer {
runOperationsIn(&preferenceFetchOperations)
}
schedulePreferencesFetchOperation("com.fetchPreferences.type1") {[unowned self] (operation:FetchOperation) in
WebServiceManager.getType1Detail(for: user) {[unowned self] (error) in
self.completeFetchOperation(operation, withError: error, andCompletionHandler: completionHandler)
}
}
schedulePreferencesFetchOperation("com.fetchPreferences.type2") {[unowned self] (operation:FetchOperation) in
WebServiceManager.getType2Detail(for: user) {[unowned self] (error) in
self.completeFetchOperation(operation, withError: error, andCompletionHandler: completionHandler)
}
}
schedulePreferencesFetchOperation("com.fetchPreferences.type3") {[unowned self] (operation:FetchOperation) in
WebServiceManager.getType3Detail(for: user) {[unowned self] (error) in
self.completeFetchOperation(operation, withError: error, andCompletionHandler: completionHandler)
}
}
schedulePreferencesFetchOperation("com.fetchPreferences.type4") {[unowned self] (operation:FetchOperation) in
WebServiceManager.getType4Detail(for: user) {[unowned self] (error) in
self.completeFetchOperation(operation, withError: error, andCompletionHandler: completionHandler)
}
}
}
}
// MARK:- Fetch Operation Struct
private typealias FetchOperationBlock = (_ operation:FetchOperation)->Void
private struct FetchOperation:Hashable {
fileprivate var runToken = 0
fileprivate let fetchBlock:FetchOperationBlock
let name:String!
var isActivated:Bool {
get {
return runToken == 0 ? false : true
}
mutating set {
if runToken == 0 && newValue == true {
runToken = 1
}
}
}
fileprivate var hashValue: Int {
get {
return name.hashValue
}
}
func execute() -> Void {
fetchBlock(self)
}
init (name:String, fetch:@escaping FetchOperationBlock) {
self.name = name
self.fetchBlock = fetch
}
}
private func ==(lhs: FetchOperation, rhs: FetchOperation) -> Bool {
return lhs.hashValue == rhs.hashValue
}
///这就是我在viewcontrollers viewDidLoad方法中调用它的方式
//This is how I call it in my viewcontrollers viewDidLoad method
__weak UserDetailViewController *weakSelf = self;
[self.dataCoordinator fetchPreferences:^(NSError * _Nullable error) {
if (error == nil) {
[weakSelf didFetchPrefrences];
}
else {
// handle error
}
}];
//completion response
- (void)didFetchPrefrences {
//when api calls complete load data
if (self.dataCoordinator.numberOfPreferencesFetchCalls == 0) {
//Load details
}
}
我不确定该如何进行,我在 https:/上看到了一个错误报告./bugs.swift.org/browse/SR-5119 ,但似乎已在Xcode 9 beta 3中修复.感谢任何帮助
I'm not sure how to proceed on this, I saw a bug report at https://bugs.swift.org/browse/SR-5119 but it seems to be fixed in Xcode 9 beta 3. Any help is appreciated
推荐答案
我认为此错误"可能是Swift 4的功能",特别是他们称之为对内存的专有访问"的内容.
I think this 'bug' may be a Swift 4 'feature', specifically something they call 'Exclusive access to Memory'.
观看此WWDC视频.在50分钟左右,长发的演讲者对此进行了解释.
Check out this WWDC video. Around the 50 minute mark, the long-haired speaker explains it.
https://developer.apple.com/videos/play/wwdc2017/402/?time = 233
如果您愿意忽略它,可以尝试在方案设置中关闭线程清理器.但是,调试器试图告诉您一个细微的线程问题,因此最好利用您的时间来弄清楚为什么在读取数组的同时向数组写入某些内容.
You could try turning the thread sanitizer off in your scheme settings if you're happy to ignore it. However, the debugger is trying to tell you about a subtle threading issue so it's probably a better use of your time to try to figure out why you've got something writing to your array at the same time it's being read from.
这篇关于同时访问0x1c0a7f0f8,但修改需要对Xcode 9 beta 4进行互斥访问错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!