2017-04-22 3 views
0
class func loadData(
    onCompletition: @escaping ([LocationInfo])->Void){ 
    let workingQueue = DispatchQueue.global(qos:.utility) 
    let completitionQueue = DispatchQueue.main 
    workingQueue.sync { 
     print("\n Data fetch started \n") 
     let root = FIRDatabase.database().reference() 
     let locationSummary = root.child("LocSummary") 

     locationSummary.observeSingleEvent(of: .value,with: { (snapshot) in 
      for item in snapshot.children{ 
       let locationInfo = LocationInfo(snapshot: item as! FIRDataSnapshot) 
       FirebaseDataController.resultsArray.append(locationInfo) 
      } 
      completitionQueue.async { 
       print("\n data fetch completed \n ") 

       onCompletition(FirebaseDataController.resultsArray) 
       print("After on completion method") 
      } 
     }) 
    } 
} 

문제점은 결과 배열의 데이터에 액세스 할 때마다이 함수 완료 핸들러를 거쳐야한다는 것입니다. 테이블 뷰 등으로 작업하고 싶을 때 항상 할 수있는 일이 아닙니다. (모든 DB 상호 작용과 테이블 뷰 상호 작용을 처리하는 다른 많은 클래스를 처리하는 별도의 클래스가 있습니다.)메인 스레드의 커스텀 메소드 실행하기

내 코드는 AppDelegate를 통해 응용 프로그램의 시작 부분에이 코드를 실행하고 데이터에 액세스 할 때마다 호출 할 수있는 채워진 배열을 가질 수 있습니다.

이렇게하려면이 코드를 주 스레드에서 실행해야한다고 생각합니다. 나는 workingQueue를 주 스레드로 대체하여 시도했지만 응용 프로그램은 계속 충돌했다.

내가 할 수있는 일이 있습니까?

답변

0

귀하의 응용 프로그램을 사용하여 loadData를 호출합니다. 당신은 AppDelegate에의 application:didFinishLaunching: 방법으로이 기능을 실행하면 안전하게이 구현을 사용할 수 있어야합니다 :

class func loadData(onCompletition: @escaping ([LocationInfo])->Void){ 
    let completitionQueue = DispatchQueue.main 

    print("\n Data fetch started \n") 
    let root = FIRDatabase.database().reference() 
    let locationSummary = root.child("LocSummary") 

    locationSummary.observeSingleEvent(of: .value,with: { (snapshot) in 
     for item in snapshot.children{ 
      let locationInfo = LocationInfo(snapshot: item as! FIRDataSnapshot) 
      FirebaseDataController.resultsArray.append(locationInfo) 
     } 
     completitionQueue.async { 
      print("\n data fetch completed \n ") 

      onCompletition(FirebaseDataController.resultsArray) 
      print("After on completion method") 
     } 
    }) 
} 

메인 스레드에서이 작업을 수행 할 필요가 귀하의 추측은 잘못 - 그렇게 할 이유가 없다 실제로, 당신은 실속 한 사용자 인터페이스로 끝날 것입니다. 데이터를 가져 와서 주 스레드에서 비동기 적으로 사용자 인터페이스를 업데이트하십시오.

+0

답변 해 주셔서 감사합니다. 네가 한 말대로 했어. 나는 또 다른 방법을 창조했다. 결과 배열을 가져 오려면 다음과 같이하십시오. 클래스 func fetchData() { loadData {(data) in self.resultsArray = (data as NSArray)! [위치 정보] 인쇄 ("/ n 테이블보기 \ (resultsArray.count)/n") } } 그리고 난이 메서드는 응용 프로그램 deligate에서 호출합니다. 그러나 지금은 테이블 배열 컨트롤러를 참조하고 결과 배열에 데이터를로드 한 후 데이터를 다시로드하는 방법이 필요합니다. loadData 함수 또는 가져 오기 함수에서 테이블 뷰를 참조하려면 어떻게해야합니까? –

+0

테이블 뷰를 다시로드하는 것과 관련하여 이것은 물론 가능하지만 다른 질문이기도합니다. 다른 게시물을 게시하고 댓글에 나를 언급 할 수 있습니까? 그리고 주요 문제를 해결 한 경우이 것을 수락하십시오. 이것은 StackOverflow가 질문 및 답변 플랫폼이기 때문에 많은 질문을 피하려고합니다. 예를 들어 NSNotification을 보내고 관련 뷰 컨트롤러를 옵저버로 설정할 수 있습니다. –

+0

@MinonWeerasinghe 그리고 같은 클래스에서 실행되는 클로저에 'self'를 넘겨서는 안됩니다. 왜냐하면이 클래스가주기 유지를 사용하기 때문에 캡처 목록을 사용하면 다른 질문에서 도움이 될 것입니다. 대부분의 사람들이 배울 수 있도록 코드를 게시하십시오. 너의 경우:) –

0

메인 스레드에서 메소드를 호출하고자하므로.

  • 우선 DispatchQueue과 관련된 모든 코드를 삭제하십시오. 당신이 교착 상태가 발생할 때문에 응용 프로그램을 시작할 때 당신은 주 스레드에서 동 기적으로 호출하는 경우
  • 는 만 충돌합니다 - (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait;
관련 문제