2014-09-09 1 views
10

나는 계속 노력했지만 계속 얻지 못했습니다. 나는 프로그래밍에 익숙하지 않으므로 거의 모든 새로운 단계가 실험입니다. 인수/반환없이 일반 클로저를 디스패치하는 데 문제가 없지만 (여러 개의 인수를 취하고 결국 반환하는 함수를 처리하는 방법을 이해하지 못했습니다.Swift에서 함수를 올바르게 전달하는 방법은 무엇입니까?

적절한 "해결 방법"의 논리를 얻으려면 누군가가 실용적인 예제를 게시 할 수 있으면 좋을 것이므로 모든 것이 옳은지 확인할 수 있습니다. 저는 어떤 종류의 도움에 대해서도 매우 감사 할 것입니다 ... 다른 실용적인 예가 더 좋은 방법으로 주제를 설명한다면, 당신 자신의 것을 계속 따라 가십시오!

우선 순위가 낮은 백그라운드 대기열에 다음 함수를 비동기 적으로 전달하려는 경우 (또는 실수로 다른 곳에서 호출 될 때까지 기다리지 않고 함수를 정의 할 때 디스패치를 ​​구현하려고합니다. ?!) :

func mutateInt(someInt: Int) -> Int { 
    "someHeavyCalculations" 
    return result 
} 

또는 추가 배경 대기열에 (모든) 어떤 점에서 첫 번째 함수를 호출하는 여러 인수 기능 :

func someBadExample(someString: String, anotherInt: Int) -> Int { 
    "someHeavyStuff" 
    println(testString) 
    mutateInt(testInt) 
    return result 
} 

또는 보장되어야 UI 기능 메인 큐 (j UST 가상의 예) :이 같은 뭔가를 포장 수, 당신은 비동기 적으로 그렇게하고 싶었다면

func calculate(foo: String, bar: Int) -> Int { 
    // slow calculations performed here 

    return result 
} 

:

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {   
    let sectionInfo = self.fetchedResultsController.sections?[section] as NSFetchedResultsSectionInfo  
    return sectionInfo.numberOfObjects 
} 
+0

스위프트, 블록 지원이없는 C 함수에만 존재합니다. –

+0

오우, 오케이, 완전히 틀렸어! 그럼 ** 매개 변수 (들) 및 반환 (들)을 사용하여 ** 이러한 함수를 파싱하는 방법을 이해하지 못했습니다. 즉,이 예제에서 함수가 아니라 블록을 실제로 마주 칠 수있는 논리적 인 방법 (해결 방법)입니다. 너무 - 당신은 그 (약간 편집 한) 버전을 실천에 넣고 설명 할 수 있습니까? –

+0

어쨌든 귀하의 의견을 존중하여 이제 제 질문을 완전히 수정했습니다. 감사합니다! –

답변

20

의 당신이 어떤 기능과 같이 가지고 있다고 가정 해 봅시다

func calculate(foo: String, bar: Int, completionHandler: @escaping (Int) -> Void) { 
    DispatchQueue.global().async { 
     // slow calculations performed here 

     completionHandler(result) 
    } 
} 

또는 완료 대기열에서 항상 완료 핸들러가 항상 호출되도록하려면이 작업을 수행 할 수도 있습니다.

func calculate(foo: String, bar: Int, completionHandler: @escaping (Int) -> Void) { 
    DispatchQueue.global().async { 
     // slow calculations performed here 

     DispatchQueue.main.async {   
      completionHandler(result) 
     } 
    } 
} 

백그라운드에서 수행중인 작업에 대해 다른 우선 순위 백그라운드 대기열을 사용하거나 사용자 정의 대기열 또는 자체 작업 대기열을 사용할 수 있습니다. 그러나 그 세부 사항은 실제로 당면한 질문에 중요하지 않습니다.

이 함수는 기본 동기 함수가 수행하더라도 값을 반환하지 않습니다. 대신이 비동기 변환은 completionHandler 클로저를 통해 값을 다시 전달합니다. 따라서, 당신과 같이 사용합니다 :

calculate(foo: "life", bar: 42) { result in 
    // we can use the `result` here (e.g. update model or UI accordingly) 

    print("the result is = \(result)") 
} 

// but don't try to use `result` here, because we get here immediately, before 
// the above slow, asynchronous process is done 

(참고로, 위의 예 모두 스위프트 2.3 연주를 들어, previous version of this answer를 참조 3. 스위프트 있습니다.)에서`dispatch_async_f`를 사용하는 이유가되지 않습니다

+1

나는 며칠 전 당신의 대답 덕분에 "completionHandler"라는 기본 개념을 마침내 이해했지만,이 상황을 위해 랩핑 된 함수와 결합하여 완벽하게 사용할 수 있다는 것을 아직 깨닫지 못했습니다! –