存档访问崩溃只在归档的可可应用程序(EXC_BAD_ACCESS / EXC_I386_GPFLT) [英] Memory Access Crash ONLY in Archived Cocoa Application (EXC_BAD_ACCESS/EXC_I386_GPFLT)

查看:612
本文介绍了存档访问崩溃只在归档的可可应用程序(EXC_BAD_ACCESS / EXC_I386_GPFLT)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了我的第一个Cocoa应用程序的OS X,并很高兴终于提交到iTunes连接。只是得到未批准,因为应用程序崩溃。我很难知道所有的东西,直到这里,现在我终于卡住了,不知道如何解决以下问题:



首先,该应用程序工作完全正常时,只是构建和运行。神秘的崩溃只会发生在应用程序存档。这就是为什么我没有注意到现金,并提交了不工作的应用程序到iTunes Connect。



我symolicated崩溃日志和应用程序崩溃,没有任何意义(对我来说)。这里是相关的(剥离)代码。



我有一个类 Countries 来自Core Data(SQLite)的一组项目:

  // 
// Countries.swift
//

import Cocoa

let appCountries = Countries()
class Countries {

lazy var items:[Country] = {
if let list = self.load(){
return list
}
else {
return []
}
}

func load() - > [国家]? {

如果let countryList = coreDataHelper.fetchEntitiesForClass(Country)as? [Country] {
return countryList
}
else {
return nil
}

}

}

国家是我的数据模型的实体。 coreDataHelper 类简单地包含用于创建数据存储,管理对象上下文和获取实体的所有相关方法。代码不相关,在同一个应用程序中的十几个其他用例中肯定有效。假设 coreDataHelper.fetchEntitiesForClass()返回实体的所有项目。



现在我有一个模态窗口code> beginSheet ,这是通过


I created my first Cocoa App for OS X and was happy to finally submit it to iTunes connect. Just to get not approved because the application is crashing. I had a hard time to figure out all things until here and now I'm finally stuck and don't know how to solve the following issue:

First of all, the application works perfectly fine when simply built and run. The mysterious crash will only happen when the app is archived. That's why I did not notice the cash before and submitted the not working app to iTunes Connect.

I symolicated the crash log and the app crashes at a point where it just doesn't make any sense (for me). Here is the relevant (stripped) code.

I have a class Countries which does not do much more than loading a set of items from Core Data (SQLite):

//
//  Countries.swift
//

import Cocoa

let appCountries = Countries()
class Countries {

    lazy var items: [Country] = {
        if let list = self.load() {
            return list
        }
        else {
            return []
        }
    }()

    func load() -> [Country]? {

        if let countryList = coreDataHelper.fetchEntitiesForClass("Country") as? [Country] {
            return countryList
        }
        else {
            return nil
        }

    }

}

Country is an entity of my data model. The coreDataHelper class simply holds all relevant methods for creating the data store, managed object context and fetching entities. The code is not relevant, works for sure in a dozen of other use cases in the same app. Just assume coreDataHelper.fetchEntitiesForClass() returns all items of an entity.

Now I have a modal window (beginSheet, which I implemented by following this tutorial) which holds a NSPopUpButton and I am populating all the Country elements to this PopUp:

//
//  ModalWindow.swift
//

import Cocoa

class ModalWindow: NSWindowController {

    var mainW: NSWindow = NSWindow()

    let locale = NSLocale.currentLocale()

    @IBOutlet weak var countries: NSPopUpButton!

    override init() {
        super.init()
    }

    override init(window: NSWindow!) {
        super.init(window: window)
        //Initialization code here.
    }

    required init?(coder: (NSCoder!)){
        super.init(coder: coder);
    }

    override func windowDidLoad() {
        super.windowDidLoad()
        // Implement this method to handle any initialization after your window controller's window has been loaded from its nib file.        
    }

    //method called to display the modal window
    func beginSheet(mainWindow: NSWindow){
        self.mainW = mainWindow
        NSApp.beginSheet(self.window!, modalForWindow: mainWindow, modalDelegate: self, didEndSelector:nil, contextInfo: nil)

        if let countryList = appCountries.items as NSArray? {

            for country in countryList as [Country] {
                if let localized = self.locale.displayNameForKey(NSLocaleCountryCode, value: country.name) {
                    self.countries!.addItemWithTitle(localized)
                }
            }
        }
    }

    //method called to slide out the modal window
    func endSheet(){
        NSApp.endSheet(self.window!)
        self.window!.orderOut(mainW)
    }

}

The symbolicated crash log tells me, the crash did happen in the line where I loop over the countryList:

for country in countryList as [Country] {

Crash-log excerpt:

Crashed Thread:        0  Dispatch queue: com.apple.main-thread

Exception Type:        EXC_BAD_ACCESS (SIGSEGV)
Exception Codes:       EXC_I386_GPFLT

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   libobjc.A.dylib               0x00007fff8b863064 objc_retain + 20
__TFC8MyApp18Modalwindow13windowDidLoadfS0_FT_T_ ModalWindow.swift:35
2   com.apple.AppKit                0x00007fff95dcee07 -[NSWindowController _windowDidLoad] + 586

From what I understand, this is a memory access issue. But I don't understand why. The thing is, when I NSLog the countryList it starts working:

if let countryList = appCountries.items as NSArray? {
  NSLog("[TEST] %@", countryList)
  for country in countryList as [Country] {
    //...
  }
}

I tried to interact in other ways with countryList but everything else will cause a crash when archived, unless I NSLog it first exactly like above. Even this would crash: NSLog("[TEST] %@", "\(countryList)"), even though it should be the exact same from my understanding. And again, this only happens when the application is archived in preparation for sending it to iTunes connect. Zero issues when simply built and run.

I am tempted to simply leave the NSLog in there and ship it that way, but I would like to understand what is going on an how to solve it appropriate.

Edit: Just installed the update Xcode 6.2 and have the same problem as with 6.1.1.

解决方案

I experimented with all the Build Settings which differed between Debug and Release. It looks like this is a Swift compiler issue. The problem disappears when I change the Optimization Level from Fastest to None. Both Fastest and Fastest, Unchecked produce above error. None works.

Now that I have identified the problem, I was able to search and find a better workaround. The problem is somehow related to Arrays in general and I found several mentions of it online. A simple workaround is to cast the array elements to AnyObject, like so:

for country in countryList as [AnyObject] as [Country] {
   //...
}

instead of

for country in countryList as [Country] {
   //...
}

Found this in another SO question: Swift optimization level breaks converting NSArray to Array

这篇关于存档访问崩溃只在归档的可可应用程序(EXC_BAD_ACCESS / EXC_I386_GPFLT)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆