2016-12-15 3 views
0

이 함수에서는 completionHandler를 사용하지만 여러 for 루프 (아래)에 중첩되어 있습니다. 문제는 핸들러가 루프가 실행될 때마다 호출되는 반면, 전체 함수가 처리를 완료하면 핸들러가 Set으로 전달 되기만하면됩니다. 루프 외부에 배치하면 너무 일찍 호출되어 비어 있습니다. 내가 여기서 뭘해야하지?루프 내부에서 completionHandler를 배치 할 위치는 어디입니까?

지금 나는 그것을 테스트하는 콘솔에 인쇄 할 때 인쇄 : 설정 항목 1 설정 항목 1, 2 설정 항목 1, 2, 3 등

struct RekoRequest { 




    public func getRekos(rekoType: rekoCategory, handler: @escaping (Set<String>) -> Void) { 

     var urls = [NSURL]() 
     var IDs = Set<String>() 


     TwitterRequest().fetchTweets(searchType: "things") { result in 


      guard let tweets = result as? [TWTRTweet] else {print("Error in getRekos receiving tweet results from TwitterRequest.fetchTweets"); return} 

      for tweet in tweets { 





       let types: NSTextCheckingResult.CheckingType = .link 
       let detector = try? NSDataDetector(types: types.rawValue) 
       guard let detect = detector else { print("NSDataDetector error"); return } 

       let matches = detect.matches(in: text, options: .reportCompletion, range: NSMakeRange(0, (text.characters.count))) 



       for match in matches { 


        if let url = match.url { 

         guard let unwrappedNSURL = NSURL(string: url.absoluteString) else {print("error converting url to NSURL");return} 

         //Show the original URL 
         unwrappedNSURL.resolveWithCompletionHandler { 

          guard let expandedURL = URL(string: "\($0)") else {print("couldn't covert to expandedURL"); return} 


          guard let urlDomain = expandedURL.host else { print("no host on expandedURL"); return } 

          switch urlDomain { 


          case "www.somesite.com": 

           let components = expandedURL.pathComponents 

           for component in components { 
            if component == "dp" { 
             guard let componentIndex = components.index(of: component) else {print("component index error"); return} 
             let IDIndex = componentIndex + 1 
             let ID = components[IDIndex] 

             //Filter out Dups and add to Set 
             IDs.insert(ID) 


             handler(IDs) 

             print(ID) //this prints multiple sets of IDs, I only want one when the function is finished completely 

            } 
           } 

           break; 

          default: 
           break; 
          } 
         } 


        } else { print("error with match.url") } 

       } //for match in matches loop 




      } //for tweet in tweets loop 


     } 
    } 







} 


// Create an extension to NSURL that will resolve a shortened URL 
extension NSURL 
{ 
    func resolveWithCompletionHandler(completion: @escaping (NSURL) -> Void) 
    { 
     let originalURL = self 
     let req = NSMutableURLRequest(url: originalURL as URL) 
     req.httpMethod = "HEAD" 

     URLSession.shared.dataTask(with: req as URLRequest) 
     { 
      body, response, error in completion(response?.url as NSURL? ?? originalURL) 
      } 
      .resume() 
    } 
} 
+1

왜 루프 후 완료 핸들러를 넣지 코드 호출? –

+0

루프 뒤에 넣으면 빈 세트가 생깁니다. – GarySabo

+0

@GarySabo 여기서'IDs' 세트를 삽입하고 있습니까? 'setOfIDs'는'IDs'라고 생각합니까? –

답변

0

애프터하여 완료 핸들러를 호출 for 루프. 중요

for component in components { 
    if component == "dp" { 
     ... 
    } 
} 
handler(IDs) 

:handlerTwitterRequest().fetchTweets() 후행 폐쇄 내 외부 루프의하지만 를 호출해야합니다. 귀하의 IDs 빈 설정으로 초기화되는 빈 집합

을 처리하는


접근. for 루프 내의 특정 조건을 충족 한 후에 만 ​​값이이 집합에 삽입됩니다. 이러한 조건이 충족되지 않으면 IDs 세트가 비어 있습니다.

바람직하지 않은 경우 완료 핸들러를 변경하거나 조건 논리를 변경하여 항상 비어 있지 않은 세트를 가져와야합니다.

콜백에 선택적 세트가있을 수 있습니다. 뭔가 같이 :

(Set<String>?) -> Void

IDs 경우가 비어, 다음 nil 세트의 가능성을 다루십시오 nil와 콜백 및 호출 코드가 있습니다.

또 다른 방법은 결과를 캡슐화하기 위해 열거 형을 생성하여 콜백에 사용하는 것입니다.뭔가 같은 :

열거

enum Result { 
    case success(Set<String>) 
    case failure 
} 

콜백

handler: (Result) -> Void

사용

handler(.success(IDs)) 

// or 

handler(.failure) 

getReckos(rekoType: .someType) { result in 
    switch result { 
    case .success(let IDs): 
     // Use IDs 
    case .failure: 
     // Handle no IDs 
    } 
} 
+0

에있는'IDs.insert (ID) '입니다. 고마워요. 올바르게 발음하지는 못했지만, 문제는 내가 보낼 completionHandler가 필요하다는 것입니다. 그것의 결과는 함수를 호출하여'RekoRequest(). getRekos (rekoType : sometype) {결과 in'가 루프를 반복 할 때 완료되어 1 세트 만 완료됩니다. 매번 루프, 즉 1, 1, 2, 1, 2, 3 등을 설정하십시오. – GarySabo

+0

@GarySabo 'handler'는 for 루프 외부에서 호출되어야합니다. 이렇게하면 루프가 끝나면'handler'가'ID'로 한번 호출됩니다. –

+0

@GarySabo 내 답변에 추가 점은 빈 집합에 대한 귀하의 의견을 해결하기 위해 노력하고 있습니다. 현재 코드를 작성한 방식으로 빈 세트가 가능합니다. 내 대답은 잠재적 인 빈 세트를 처리하는 방법에 대한 몇 가지 제안을 제공합니다. –