我想使用 Swift 检查对象是否已定义或存在。
像这样:
if (isset(Object)){
}
我在使用时遇到问题:
if let x = myObject.property {
//My code
} <- Here I got 'EXC_BAD_ACCESS'
通常代码可以工作,但有时会失败。当调试失败时 myObject 被定义并具有其他属性,但是当我尝试时:
调试器中的 myObject.property 显示:“无效表达式”
myObject.otherProperty <- 有效!
这不是我第一次收到该消息,上一次是关于 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........)
}
}
}
我的类(class):
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
}
最佳答案
此代码不安全,很可能是导致问题的原因:
if let canal = Canal.getCanal(getManagedContext()) {
if let imagenFondo: Imagen = canal.imagenFondo {
canal
是一个托管对象。它只能在与其上下文关联的队列上访问。托管对象不是线程安全的。我怀疑 getManagedContext()
会返回一个未绑定(bind)到主 (UI) 队列的上下文。在这种情况下,canal.imagenFondo
是非法的。
由于这是 UI 代码,正确的方法是创建一个绑定(bind)到主队列的托管对象上下文 (NSManagedObjectContext(concurrencyType: .MainQueueConcurrencyType)
) 并通过以下方式获取所有 UI 访问的对象那个上下文。
对于非 UI 代码,您通常需要将对托管对象的访问包装在 context.performBlock()
中,以确保所有访问都发生在正确的队列中。
参见 Core Data Concurrency更多指南。
关于ios - 如果对象无效,如何检查 Swift?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38127169/