2016-07-15 2 views
2

다음 예제에서 관련 개체가 원본/호스트 개체 할당이 해제 될 때 자동으로 할당이 해제되지 않는 이유를 설명 할 수 있기를 바랍니다. 아래의 예제 코드는 다소 (사전 사과)이지만 내 문제점을 설명합니다.NSManagedObjectContext 할당 해제 문제 - (Swift | Associated Objects)

import UIKit 
import CoreData 

class ViewController: UIViewController { 

    @IBAction func createProduct(sender: AnyObject) { 

     let context = CoreDataHelpers.vendBackgroundWorkerContext() 
     let newProduct = CoreDataHelpers.newProduct(context: context) 

     newProduct.sku = "8-084220001" 

     do { 
      try newProduct.managedObjectContext?.save() 
      print("Product created [SKU: \(newProduct.sku ?? "NotDefined")]") 
     } catch { 
      print(error) 
     } 
    } 
} 


public class CoreDataHelpers { 

    public static let mainContext = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext 

    public class func vendBackgroundWorkerContext() -> NSManagedObjectContext { 
     let managedObjectContext = NSManagedObjectContext(concurrencyType: .PrivateQueueConcurrencyType) 
     managedObjectContext.parentContext = self.mainContext 

     return managedObjectContext 
    } 

    class func newProduct(context context: NSManagedObjectContext) -> Product { 
     let newProduct = NSEntityDescription.insertNewObjectForEntityForName("Product", inManagedObjectContext: context) as! Product 

     return newProduct 
    } 

} 

createProduct 기능이 실행되는 새로운 PrivateQueueConcurrencyType 관리 개체 컨텍스트 :


예는 문자열 속성 sku와 엑스 코드 템플릿에서 제공하는 기본 CoreData의 스택과 함께 CoreData 엔터티 Product 가정 (MOC)는 새로운 Product Managed Object (MO)에 의해 판매되고 사용됩니다. 위의 코드는 올바르게 작동합니다.

그러나! 나는 createProduct 함수의 처음 두 행을 결합하면 있도록 :

let newProduct = CoreDataHelpers.newProduct(context: CoreDataHelpers.vendBackgroundWorkerContext()) 

다음 응용 프로그램은 EXC_BAD_ACCESStry newProduct.managedObjectContext?.save()에서 충돌합니다.

언뜻보기에 이것은 약간 이상하게 보입니다. 우리가 한 것은 코드를 리팩토링 한 것입니다. documentation을 파기하면 managedObjectContext 속성은 unowned(unsafe)으로 선언됩니다. 이것은 아마도 생성 된 MOC가 할당 해제되었음을 의미하며 매달 포인터 (제 가정이 틀린 경우 제발 수정하십시오)을 의미합니다.

MOC가 할당 해제되지 않도록하기 위해 MO 자체와 연결해 보았습니다. newProduct :

class func newProduct(context context: NSManagedObjectContext) -> Product { 
    let newProduct = NSEntityDescription.insertNewObjectForEntityForName("Product", inManagedObjectContext: context) as! Product 

    var key: UInt8 = 0 
    objc_setAssociatedObject(newProduct, &key, context, .OBJC_ASSOCIATION_RETAIN) 

    return newProduct 
} 

이가 나타납니다 훌륭하게 작동 - 나는 악기에서 확인 될 때까지. (소스 객체가 해제 될 때 자동으로 할당 해제해서는 안?)을 Product MO가 해제 될 때, 지금 관련 MOC가 아닌 것으로 생각된다

내 질문은 : 누군가는 설명 할 경우 추가 참조 그것이 할당 해제되는 것을 막고있는 MOC입니까? MO와 MOC 사이에 보관주기를 만들었습니까?

enter image description here

답변

0

당신은 아마 순환 출자를 (사이클 유지) 만들 수 있습니다.

모든 관리 객체는 관리 컨텍스트 (컨텍스트가 객체를 소유 함)에서 소유하며 컨텍스트를 연관된 객체로 설정하면 객체가 컨텍스트를 소유하게됩니다.

따라서 할당 해제되지 않습니다.

진짜 해결 방법은 배경 컨텍스트를 mainContext과 같은 로컬 속성에 저장하는 것입니다.

+0

필요에 따라 작업자 컨텍스트를 삭제하거나 생성하면 안되는 이유는 무엇입니까? 예 : 아직 변경되지 않은 두 개의 MO가 있습니다. 같은 맥락에서 저장이 MO 둘 모두를 유지할 것입니다 - 당신은 단지 그것들 중 하나를 유지하려고했을 것입니다).여러 작업자 컨텍스트를 판매하는 주목할만한 CD 스택 (예 : https://www.bignerdranch.com/blog/introducing-the-big-nerd-ranch-core-data-stack/). –

+0

@SoOverIt 맞습니다. 나는 대답의 마지막 부분을 제거했습니다. 그러나 여전히 사용중인 관리 컨텍스트에 대한 강력한 참조가 있는지 확인해야합니다. – Sulthan

+0

'모든 관리 대상 개체는 관리 컨텍스트에 의해 소유됩니다.' 이것은 전적으로 사실이 아닙니다. 컨텍스트가 삭제 된 관리 대상 개체를 계속 가질 수 있습니다. NSManagedObject Class Reference의 managedObjectContext 문서를 참조하십시오. (https://developer.apple.com/library/mac/documentation/Cocoa/Reference/CoreDataFramework/Classes/NSManagedObject_Class/#//apple_ref/occ/instp/NSManagedObject/ managedObjectContext) - "수신자가 컨텍스트에서 삭제 된 경우 nil 일 수 있습니다." –