非常不寻常的Xcode编译行为

时间:2014-10-23 19:50:43

标签: xcode dictionary swift

自Xcode 6.1和iOS 8.1发布以来,我的一个应用程序停止运行。 只有当我做了#34; RUN"我才能重现这个问题。在我的设备上使用" Release"而不是"调试"。

现在出现问题。这在调试模式下工作正常:

import Foundation

class CategoryParser {


    var categoriesSettingsDictionary : [String: AnyObject]?


    init() {
        let categoriesURL = NSBundle.mainBundle().URLForResource("CategoriesSettings", withExtension: "plist")
        categoriesSettingsDictionary = NSDictionary(contentsOfURL: categoriesURL!) as? Dictionary<String, AnyObject>
    }
}

但它在&#34;发布&#34;中崩溃了我实例化CategoryParser类型的Object时的模式。经过多次试验和错误后,我认为要阻止它解决问题,我可以将字典初始化放在两个println()语句之间。为什么那些会有所不同?

import Foundation

class CategoryParser {


    var categoriesSettingsDictionary : [String: AnyObject]?


    init() {
        let categoriesURL = NSBundle.mainBundle().URLForResource("CategoriesSettings", withExtension: "plist")
        println("_")
        categoriesSettingsDictionary = NSDictionary(contentsOfURL: categoriesURL!) as? Dictionary<String, AnyObject>
        println("_")
    }
}

1 个答案:

答案 0 :(得分:1)

它必须是Swift编译器中的优化问题。我认为,它将NSDictionaryDictionary<String,AnyObject>联系起来。

我通过以下设置重现了这个问题。


环境:Xcode 6.1(6A1052d)/ iPhone 6 / iOS 8.1

模板:单一视图应用程序

CategoriesSettings.plist:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>ct1</key>
    <string>test</string>
</dict>
</plist>

AppDelegate.swift

import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
        let result = loadPlist()
        println("result: \(result)")
        return true
    }

    func loadPlist() -> [String: AnyObject]? {
        let categoriesURL = NSBundle.mainBundle().URLForResource("CategoriesSettings", withExtension: "plist")
        let dict = NSDictionary(contentsOfURL: categoriesURL!)
        println(dict)
        let result = dict as? [String:AnyObject]
        return result
    }
}

// EOF

输出(带-O):

Optional({
    ct1 = test;
})
result: nil

输出(带-Onone):

Optional({
    ct1 = test;
})
result: Optional(["ct1": test])

但是,我不知道最好的解决方法。

也许这有效:

class CategoryParser {
    var categoriesSettingsDictionary : [String: AnyObject]?
    init() {
        let categoriesURL = NSBundle.mainBundle().URLForResource("CategoriesSettings", withExtension: "plist")
        categoriesSettingsDictionary = NSDictionary(contentsOfURL: categoriesURL!) as? Dictionary<String, AnyObject>
        if categoriesSettingsDictionary == nil {
            // NOTICE: to other developers about this workaround
            println("_")
            println("_")
        }
    }
}

将它们封装在autoreleasepool中也有效:

class CategoryParser {
    var categoriesSettingsDictionary : [String: AnyObject]?

    init() {
        autoreleasepool {
            let categoriesURL = NSBundle.mainBundle().URLForResource("CategoriesSettings", withExtension: "plist")
            self.categoriesSettingsDictionary = NSDictionary(contentsOfURL: categoriesURL!) as? Dictionary<String, AnyObject>
        }
    }
}

但是,截至目前,我认为您应该按原样使用NSDictionary,因为只要您只阅读它,NSDictionary和{{1}之间几乎没有实际区别在大多数情况下。

Dictionary<String,AnyObject>

或者,这可能过于激进,但您可以实施自己的class CategoryParser { var categoriesSettingsDictionary : NSDictionary? init() { let categoriesURL = NSBundle.mainBundle().URLForResource("CategoriesSettings", withExtension: "plist") categoriesSettingsDictionary = NSDictionary(contentsOfURL: categoriesURL!) } } NSDictionary转换器。

Dictionary