2014-11-26 2 views
1

온라인으로 여러 기사를 읽는 데 일주일 이상을 투자했습니다. & StackOverflow Q & 스위프트 배열을 메모리 관리로 UIViewController 번으로 내 앱에서 계속 충돌하고 있습니다. 네가 도울 수 있기를 바란다.스위프트 배열/컬렉션 메모리 관리

부모 클래스 컨트롤러를 상속 한 여러 하위 클래스 (예제를 사용하여 단순화 한)와 부모 클래스 컨트롤러가 있습니다.

class ParentViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { 
    lazy var results: [AnyObject] = [AnyObject]() //can contain various classes, such as Product, User, etc. 

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 
     return results.count 
    } 

     ...  
} 


class SubViewController: ParentViewController { 

    ... loads results Array via REST API, then then appends to array using 
    results.append(Product()) 

} 

무작위로, 나는이 같은 충돌을 얻을 것 :

EXC_BAD_ACCESS KERN_INVALID_ADDRESS at 0x0000000a1abb4b17 
Thread : Crashed: com.apple.main-thread 
0 libobjc.A.dylib    0x000000019478fe10 cache_getImp + 16 
1 libobjc.A.dylib    0x0000000194784a6c lookUpImpOrForward + 540 
2 libobjc.A.dylib    0x000000019478fdb8 _objc_msgSend_uncached_impcache + 56 
3 libswiftCore.dylib    0x00000001004d4e40 _ZN5swift12metadataimpl14ValueWitnessesINS0_17ObjCRetainableBoxEE18initializeWithCopyEPNS_11OpaqueValueES5_PKNS_8MetadataE + 24 
4 libswiftCore.dylib    0x000000010036e3cc _TFSa6appendU__fRGSaQ__FQ_T_ + 92 

내 이해를 바탕으로, 나는 resultsresults.append()가 호출 될 때까지는 더 이상 메모리에 있기 때문에이 없다 생각합니다.

특히 하위 클래스가있는 경우 UIViewController에서 배열/컬렉션을 인스턴스화하는 가장 좋은 방법은 무엇입니까? 다음은 내 생각입니다. 모든 의견을 환영합니다.

1. 부모 클래스로 lazy을 사용하십시오. 이것은 내가 deinit()를 사용하여 메모리 할당을 해제해야이 여전히 또한, 충돌이 발생, 기본 케이스이며, SubViewController에서

lazy var results: [AnyObject] = [AnyObject]() 

2.Init 충돌의 원인은? 부모 클래스에서

in ParentViewController 
var results: [AnyObject] 

in SubViewController 
    required init(coder aDecoder: NSCoder) { 
     super.init(coder: aDecoder) 
     self.results = [Product]() 
    } 

3.Make results 선택 사항이 선택적 항목을 확인하기 위해 부모 클래스의 모든 방법을 필요로한다. 배열을 init 또는 viewDidLoad()에 초기화해야합니까? 또한, deinit 결과가 있어야합니까? 부모 클래스에서 제외하려면?

in ParentViewController 
var results: [AnyObject]? 

deinit { 
    results = nil 
} 

in SubViewController 
    required init(coder aDecoder: NSCoder) { 
     super.init(coder: aDecoder) 
     self.results = [Product]() 
    } 

모든 의견을 환영합니다.

답변

1

뷰 컨트롤러의 수명과 관계가 무엇인지 알 수는 없지만이 작업을 안정적으로 수행하는 한 가지 방법은 AppDelegate에 "결과"배열을 배치하는 것입니다. 이것은 뷰 컨트롤러에 대해 작업 할 때 존재하고 뷰 컨트롤러에서 액세스 할 수 있음을 보장합니다.

let appDelegate = UIApplication.sharedApplication().delegate as AppDelegate 
appDelegate.results.append(...) 
+0

감사합니다. 불행하게도 라이프 사이클은 실제 컨트롤러의 수명주기 동안 애플리케이션 폭이 아닙니다. – Dean

1

나머지 스레드에서 가져온 결과를 기본 스레드에 추가 하시겠습니까? 시도하지 않는 경우 :

dispatch_async(dispatch_get_main_queue(), { 
    results.append(objectsFromApi) 
}) 
+0

'AFNetworking'을 사용 중이므로 별도의 스레드에서로드합니다. 주 스레드에서 추가해야합니까? – Dean

+0

죄송합니다, 나는'AFNetworking' 코드를 두 번 확인했습니다. 성공 완료 블록은'dispatch_get_main_queue'를 자동으로 호출하여 주 스레드에서 완료됩니다. 충돌 보고서를 두 번 확인하고'results.append()'가 주 스레드에서 수행되는지 확인합니다. – Dean

+0

확인. 완성 클로저에서 self 키워드를 사용하여 결과에 액세스합니까 :'self.results'? Xcode는 이것을 요구할 것입니다. 또한 배열이 포함 된'ViewController'가 아직 살아 있는지 확인 하시겠습니까? 당신은 도구 할당 도구를 사용하여 알아낼 수 있습니다. SubViewController 뷰를 수동으로 다른 ViewController 뷰에 삽입 했으므로 SubViewController 뷰를 수동으로 유지하는 참조가 없습니다. –