मैं यह जांचना चाहता हूं कि स्विफ्ट का उपयोग करके कोई ऑब्जेक्ट परिभाषित किया गया है या मौजूद है या नहीं।

कुछ इस तरह:

if (isset(Object)){

}

मुझे इसका उपयोग करने में समस्या है:

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

आमतौर पर कोड काम करता है, लेकिन कभी-कभी विफल हो जाता है। डिबगिंग में विफल होने पर myObject परिभाषित किया गया है और अन्य गुण हैं, लेकिन जब मैं कोशिश करता हूं:

MyObject.property डीबगर में दिखाता है: "अमान्य अभिव्यक्ति"

MyObject.otherProperty <- काम करता है!

यह पहली बार नहीं है कि मुझे वह संदेश मिला है, आखिरी वाला एक UIViewController और संपत्ति 'व्यू' के ऑब्जेक्ट के साथ था। इस बार एक कस्टम क्लास के ऑब्जेक्ट के साथ हो रहा है।

अग्रिम में धन्यवाद!

मेरा कोड:

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
}()

समाधान (धन्यवाद रॉब नेपियर):

मेरे 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
}
0
Gonzalo1987 30 जून 2016, 18:11
2
कृपया अपना वास्तविक कोड और संपत्ति परिभाषाएं पोस्ट करें। यह देखना असंभव है कि उसके बिना क्या हो रहा है।
 – 
Aaron Wojnowski
30 जून 2016, 18:15
1
हो सकता है कि आपकी समस्या यह?
 – 
Leonardo
30 जून 2016, 18:59
नहीं, क्षमा करें, वस्तु मौजूद है, मैंने 'canal.titulo' का उपयोग करने की कोशिश की है और यह काम करता है, और canal.imagenFondo' विफल हो जाता है... :( एक 'मजबूत संपत्ति' krakendev.io/blog/weak-and-un स्वामित्व -संदर्भ-इन-स्विफ्ट
 – 
Gonzalo1987
30 जून 2016, 19:06

1 उत्तर

सबसे बढ़िया उत्तर

यह कोड असुरक्षित है, और संभवतः आपकी समस्या का कारण है:

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

canal एक प्रबंधित वस्तु है। इसे केवल इसके संदर्भ से जुड़ी कतार पर ही पहुँचा जा सकता है। प्रबंधित ऑब्जेक्ट थ्रेड सुरक्षित नहीं हैं। मुझे संदेह है कि getManagedContext() एक संदर्भ देता है जो मुख्य (यूआई) कतार से बंधा नहीं है। उस स्थिति में canal.imagenFondo अवैध है।

चूंकि यह यूआई कोड है, इसलिए सही तरीका एक प्रबंधित ऑब्जेक्ट संदर्भ बनाना है जो मुख्य कतार (NSManagedObjectContext(concurrencyType: .MainQueueConcurrencyType)) से जुड़ा हुआ है और उस संदर्भ के माध्यम से सभी यूआई-पहुंच वाली वस्तुओं को प्राप्त करता है।

गैर-यूआई कोड के लिए, आपको अक्सर यह सुनिश्चित करने के लिए context.performBlock() में प्रबंधित वस्तुओं तक पहुंच लपेटनी होगी कि सभी पहुंच सही कतार में हो।

अधिक के लिए कोर डेटा कंसुरेंसी गाइड देखें।

2
Rob Napier 30 जून 2016, 19:26
Func getManagedContext() -> NSManagedObjectContext { delegado = UIApplication.sharedApplication() के रूप में डेलिगेट करें! AppDelegate वापसी delegado.managedObjectContext}। यह बुरा है? आमतौर पर काम करता है
 – 
Gonzalo1987
30 जून 2016, 19:26
मैं धागे में NSManagedObject का उपयोग कर सकता हूं (संपत्ति canal.titulo ठीक काम करता है)
 – 
Gonzalo1987
30 जून 2016, 19:31
सिर्फ इसलिए कि यह अवैध है इसका मतलब यह नहीं है कि यह हर बार विफल हो जाएगा। एक दौड़ की स्थिति है। यदि दौड़ विफल हो जाती है, तो आप दुर्घटनाग्रस्त हो जाते हैं। अगर यह सफल होता है, तो ऐसा लगता है कि यह काम करता है। मैं आपके विकास एक्सकोड योजना में आपकी तर्क सूची में "-com.apple.CoreData.ConcurrencyDebug 1" जोड़ने की अत्यधिक अनुशंसा करता हूं। जब आप प्रबंधित ऑब्जेक्ट का उपयोग केवल कभी-कभी क्रैश होने के बजाय गलत थ्रेड पर करते हैं, तो इससे कोर डेटा विश्वसनीय रूप से क्रैश हो जाएगा। oleb.net/blog/2014/06/core-data-concurrency -डिबगिंग
 – 
Rob Napier
30 जून 2016, 19:44
1
यह भी ध्यान दें कि titulo तक पहुंचना imagenFondo तक पहुंचने से बिल्कुल अलग है। एक साधारण गुण है। दूसरा एक ऐसा संबंध है जिसके लिए वर्तमान संदर्भ में किसी वस्तु को दोष देने की आवश्यकता होगी (एक बहुत अधिक जटिल और थ्रेड-असुरक्षित संचालन)।
 – 
Rob Napier
30 जून 2016, 19:46
MainQueueConcurrencyType का उपयोग करके विधि विफल नहीं हो रही है, मुझे इसके बारे में अधिक जानकारी चाहिए, लेकिन आपकी प्रतिक्रिया पूरे धागे को बंद कर देती है। आप अपनी प्रतिक्रिया के साथ बिल्कुल सही हैं, मुझे संगामिति के बारे में थोड़ा और अध्ययन करना होगा। स्पष्टीकरण के लिए Tyvm !!
 – 
Gonzalo1987
30 जून 2016, 19:49