如果一个对象无效,如何检查Swift?

时间:2016-06-30 15:11:52

标签: ios xcode swift properties defined

我想使用Swift检查对象是否已定义或存在。

这样的事情:

if (isset(Object)){

}

我使用时遇到了问题:

if let x = myObject.property {
    //My code
} <- Here I got 'EXC_BAD_ACCESS' 

通常代码有效,但有时会失败。如果在调试中失败,则定义myObject并具有其他属性,但是当我尝试:

时 调试器中的

myObject.property显示:“表达式无效”

myObject.otherProperty&lt; - Works!

这不是我第一次收到该消息,最后一个是UIViewController的对象和属性'view'。这一次发生在自定义类的对象上。

提前致谢!

我的代码:

class DetallesEntidadController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()

        if let canal = Canal.getCanal(getManagedContext()) {
            if let imagenFondo: Imagen = canal.imagenFondo {
                if let view = self.view {
                    let ivBackgroundImage = UIImageView(image: Utils.loadImageFromPath(imagenFondo.nombreFichero!))
                    ivBackgroundImage.frame = view.frame
                    var bottomView = CGFloat()
                    if let height = self.navigationController?.navigationBar.frame.height {
                        ivBackgroundImage.frame.origin.y = -height-Utils.getStatusBarHeight()
                        bottomView = view.frame.origin.y+view.frame.size.height-Utils.getStatusBarHeight()-height
                    } else {
                        bottomView = view.frame.origin.y+view.frame.size.height-Utils.getStatusBarHeight()
                    }
                    ivBackgroundImage.frame.origin.y = bottomView - ivBackgroundImage.frame.height

                    view.addSubview(ivBackgroundImage)
                    view.sendSubviewToBack(ivBackgroundImage)
                }
            } <- Thread 1: EXC_BAD_ACCESS (code=1, address=0x........)
        }
    }
}

我的课程:

import Foundation
import CoreData

class Canal: NSManagedObject {
    @NSManaged var titulo: String?
    @NSManaged var version: NSNumber?
    @NSManaged var imagenFondo: Imagen?
}

internal func persist(managedContext: NSManagedContext, xmlIndexerCanal: XMLIndexer){...}
internal static func getCanal(managedContext: NSManagedContext) -> Canal? {...}

import Foundation
import CoreData

class Imagen: NSManagedObject {

    @NSManaged var nombreFichero: String?
    @NSManaged var titulo: String?
    @NSManaged var url: String?

    internal func persist(managedContext: NSManagedObjectContext, strUrl: String){...}

}

失败的属性'canal.imagenFondo'但'canal.titulo'有效,错误有时会发生。

添加了:

func getManagedContext() -> NSManagedObjectContext {
    let delegado = UIApplication.sharedApplication().delegate as! AppDelegate
    return delegado.managedObjectContext
}

lazy var managedObjectContext: NSManagedObjectContext = {
    // Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.) This property is optional since there are legitimate error conditions that could cause the creation of the context to fail.
    let coordinator = self.persistentStoreCoordinator
    var managedObjectContext = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType)
    managedObjectContext.persistentStoreCoordinator = coordinator
    return managedObjectContext
}()

解决方案(感谢Rob Napier):

我的NSManagedObject需要在与创建它的上下文相同的线程中使用。 getManagedContext()方法替换为:

func getManagedContextMainQueue() -> NSManagedObjectContext {
    let delegado = UIApplication.sharedApplication().delegate as! AppDelegate

    let coordinator = delegado.persistentStoreCoordinator
    let managedObjectContext = NSManagedObjectContext(concurrencyType: .MainQueueConcurrencyType)
    managedObjectContext.persistentStoreCoordinator = coordinator
    return managedObjectContext
}

1 个答案:

答案 0 :(得分:2)

此代码不安全,可能是导致问题的原因:

    if let canal = Canal.getCanal(getManagedContext()) {
        if let imagenFondo: Imagen = canal.imagenFondo {

canal是一个托管对象。它只能在与其上下文关联的队列上访问。托管对象不是线程安全的。我怀疑getManagedContext()返回一个与主(UI)队列无关的上下文。在这种情况下,canal.imagenFondo是非法的。

由于这是UI代码,因此正确的方法是创建一个与主队列(NSManagedObjectContext(concurrencyType: .MainQueueConcurrencyType))绑定的托管对象上下文,并通过该上下文获取所有UI访问的对象。

对于非UI代码,您通常需要在context.performBlock()中包装对托管对象的访问权限,以确保所有访问都发生在正确的队列中。

有关详情,请参阅Core Data Concurrency指南。