热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

同时访问0x1c0a7f0f8,但修改需要Xcode9beta4上的独占访问错误

如何解决《同时访问0x1c0a7f0f8,但修改需要Xcode9beta4上的独占访问错误》经验,为你挑选了4个好方法。

我的项目使用Objective-C和Swift代码.当用户登录时,它会为用户首选项调用一组apis,我有一个DataCoordinator.swift类来调度API操作,我从UserDetailViewController.m类调用此类来加载用户首选项.在使用Xcode 9 beta 4将我的代码迁移到Swift 4之前,这种用法正常工作.现在当我登录时,我在DataCoordinator类中给出了这个错误.下面是我的DataCoordinator和Viewcontroller类的示例.

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方法中调用它

__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中修复.任何帮助表示赞赏



1> Mark Bridges..:

我认为这个'bug'可能是一个Swift 4'功能',特别是他们称之为'独家访问内存'.

看看这个WWDC视频.大约50分钟后,这位长发演讲者解释道.

https://developer.apple.com/videos/play/wwdc2017/402/?time=233

如果您乐意忽略它,可以尝试在方案设置中关闭线程消毒剂.但是,调试器试图告诉你一个微妙的线程问题,所以它可能更好地利用你的时间来弄清楚为什么你在读取数据的同时写入了你的数组.


这有一些非凡的微妙之处.首先,如果你在一个struct的属性上有一个didSet观察者,*write access仍然被强制为active*.其次,如果这是在类的属性上,则由于某些引用该问题的引用语义而不强制执行*写访问*.最后,如果突变发生*通过*协议类型,它*取决于*协议类型是否为"类"绑定.如果没有,它就会以`struct`级别的限制行事,即使运行时类型毕竟是引用类型.我不希望ppl跟随w/o示例代码.

2> 小智..:

在目标的构建设置下.选择No EnforcementExclusive Access to MemorySwift Compiler - Code Generation


请注意,这不会自动修复实际的数据争用问题.但是,线程清理程序可能会发现误报 - 如果变异函数有自己的同步原语设置,通常就是这种情况.

3> Ralf Hundewa..:

仅适用于Swift 4以及使用.initialKVO设置选项时

如果在observeValue方法中检查上下文,只需将上下文变量设置为静态.这篇博文详细描述了这个bug.



4> J. Doe..:

Swift 5.0中,这是在发布模式下运行应用程序时的默认行为。在5.0之前(今天为Swift 4.2.1及更低版本),此行为仅在调试模式下运行。

如果您忽略此错误,则您的应用程序将在发布模式下失败。

考虑以下示例:

func modifyTwice(_ value: inout Int, by modifier: (inout Int) -> ()) {
  modifier(&value)
  modifier(&value)
}

func testCount() {
  var count = 1
  modifyTwice(&count) { $0 += count }
  print(count)
}

打印print(count)行时count的值是多少?好吧,我也不知道,当您运行此代码时,编译器会给出不可预测的结果。在Swift 4.0中,在调试模式下是不允许的,在Swift 5.0中,即使在运行时,它也会崩溃。

资料来源:https : //swift.org/blog/swift-5-exclusivity/


推荐阅读
author-avatar
无梗啦_671
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有