여러 맵 로컬 검색을 동시에 수행

Stéphane de Luca

여러 검색을 동기식으로 수행하고 (다음 요청을 실행하기 전에 이전 요청이 완료 될 때까지 기다림) 계속 진행하기 전에 모든 작업이 완료 될 때까지 차단합니다.

그러나 로컬 검색의 완료 핸들은 세마포어가 포기하면 차단 된 것처럼 보이고 실행됩니다. 나는 성공하지 못한 채 많은 시도를했다.

내 코드와 로그는 다음과 같습니다 (플레이 그라운드에 복사 / 붙여 넣기 가능).

import CoreLocation
import MapKit


func search(_ query: String, in span: MKCoordinateSpan, centered center: CLLocationCoordinate2D, id: Int) {

    let semaphore = DispatchSemaphore(value: 0)
    //let group = DispatchGroup(); group.enter()

    // Run the request for this rect
    print("\(#function): local search on the \(id)th portion ")

    let request = MKLocalSearch.Request()
    request.naturalLanguageQuery = query
    request.region = MKCoordinateRegion(center: center, span: span)

    if #available(iOS 13, *) {
        request.resultTypes = .pointOfInterest
    }


    let search = MKLocalSearch(request: request)

    search.start { response, error in
        print("\(id) got \(response?.mapItems.count) items")
        semaphore.signal()
    }


    let s = semaphore
    //let s = group

    // Wait for the request ot complete
    print("\(#function): waiting for the \(id)th portion to complete")
    //guard _ = s.wait(wallTimeout: .distantFuture) else {
    guard s.wait(timeout: .now() + 5) == .success else {
        print("\(#function): ***Warning: \(id)th timeout, job incomplete")
        return
    }

    print("\(#function): \(id)th completed")
}



let rect = CGRect(
    x: 48.10,
    y: 3.43,
    width: 0.09,
    height: 0.09
)


let n = 4
let latDelta = rect.width / CGFloat(n)
var latOffs = rect.minX



let queue = OperationQueue()
//queue.maxConcurrentOperationCount = 1
var ops = [BlockOperation]()

// -- Run all asyn loca search requests synchronuously
for i in 0..<n {
    // Take the next cut of the original region
    let portion = CGRect(
        x: latOffs,
        y: rect.minY,
        width: latDelta,
        height: rect.height
    )

    latOffs += latDelta

    ops.append(BlockOperation { [portion, i] in
        let center = CLLocationCoordinate2D(latitude: CLLocationDegrees(portion.midX), longitude: CLLocationDegrees(portion.midY))
        let span = MKCoordinateSpan(latitudeDelta: CLLocationDegrees(portion.width), longitudeDelta: CLLocationDegrees(portion.height))

        search("coffee", in: span, centered: center, id: i)
    })
}

queue.addOperations(ops, waitUntilFinished: true)

print("All done")

현재 가짜 출력 :

search(_:in:centered:id:): local search on the 1th portion 
search(_:in:centered:id:): local search on the 2th portion 
search(_:in:centered:id:): local search on the 3th portion 
search(_:in:centered:id:): local search on the 0th portion 
search(_:in:centered:id:): waiting for the 1th portion to complete
search(_:in:centered:id:): waiting for the 3th portion to complete
search(_:in:centered:id:): waiting for the 2th portion to complete
search(_:in:centered:id:): waiting for the 0th portion to complete
search(_:in:centered:id:): ***Warning: 0th timeout, job incomplete
search(_:in:centered:id:): ***Warning: 2th timeout, job incomplete
search(_:in:centered:id:): ***Warning: 1th timeout, job incomplete
search(_:in:centered:id:): ***Warning: 3th timeout, job incomplete
All done
0 got Optional(10) items
2 got Optional(10) items
1 got Optional(10) items
3 got Optional(10) items

[최신 정보]

예상되는 출력은 다음과 같이 no ***WarningAll done마지막 줄로 표시되어야 합니다 (정확한 번호 매기기 순서는 네트워크 조건에 따라 다름).

search(_:in:centered:id:): local search on the 1th portion 
search(_:in:centered:id:): local search on the 2th portion 
search(_:in:centered:id:): local search on the 3th portion 
search(_:in:centered:id:): local search on the 0th portion 
search(_:in:centered:id:): waiting for the 1th portion to complete
search(_:in:centered:id:): waiting for the 3th portion to complete
search(_:in:centered:id:): waiting for the 2th portion to complete
search(_:in:centered:id:): waiting for the 0th portion to complete
0 got Optional(10) items
search(_:in:centered:id:): 0th completed
2 got Optional(10) items
search(_:in:centered:id:): 2th completed
1 got Optional(10) items
search(_:in:centered:id:): 1th completed
3 got Optional(10) items
search(_:in:centered:id:): 3th completed
All done

[업데이트 2] 라인 주석 해제시 출력되는 내용 //queue.maxConcurrentOperationCount = 1

search ( : in : centered : id :) : 0 번째 부분에 대한 지역 검색 2020-03-28 23:49:41 +0000 search ( : in : centered : id :) : 0 번째 부분이 완료되기를 기다립니다 2020-03 -28 23:49:41 +0000 search ( : in : centered : id :) : *** 경고 : 0 번째 타임 아웃, 작업 미완료 2020-03-28 23:49:46 +0000 search ( : in : centered : id :) : 1 차 지역 검색 2020-03-28 23:49:46 +0000 search ( : in : centered : id :) : 1 차 부분 완료 대기 2020-03-28 23:49:46 + 0000 search ( : in : centered : id :) : *** 경고 : 1 차 타임 아웃, 작업 미완료 2020-03-28 23:49:51 +0000 search ( : in : centered : id :) : 2 일 로컬 검색 부분 2020-03-28 23:49:51 +0000 search ( : in : centered : id :) : 2 번째 부분 완료 대기 2020-03-28 23:49:51 +0000 search (: in : centered : id :) : *** 경고 : 2 차 타임 아웃, 작업 미완료 2020-03-28 23:49:56 +0000 search ( : in : centered : id :) : 3 차 부분 로컬 검색 2020- 03-28 23:49:56 +0000 search ( : in : centered : id :) : 3 번째 부분 완료 대기 2020-03-28 23:49:56 +0000 search ( : in : centered : id :) : *** 경고 : 3 번째 타임 아웃, 작업 미완료 2020-03-28 23:50:01 +0000 완료 됨 2020-03-28 23:50:01 +0000 0 개 선택 사항 (10) 항목 획득 2020-03-28 23 : 50 : 02 +0000 3 개 획득 옵션 (10) 개 2020-03-28 23:50:02 +0000 2 개 획득 옵션 (10) 개 2020-03-28 23:50:02 +0000 1 개 획득 옵션 (10) 항목 2020-03-28 23:50:02 +0000

참고 : Btw, \(Date())각 인쇄 끝에 추가 했습니다.

Rob

이러한 작업이 직렬 방식으로 작동하도록하려면 대기열이 한 번에 하나만 실행할 수 있도록 지정해야합니다.

queue.maxConcurrentOperationCount = 1

그리고 당신이 발견했듯이, 당신 은 작업이 완료 될 때까지 현재 스레드를 차단하는 waitUntilFinished옵션을 사용하지 않기를 원합니다 addOperations. 대신 완료 핸들러 패턴을 사용하십시오.


내가 사용한 코드는 다음과 같습니다.

func performMultipleSearches(completion: @escaping () -> Void) {
    let searches = ["restaurant", "coffee", "hospital", "natural history museum"]

    let queue = OperationQueue()
    queue.maxConcurrentOperationCount = 1

    for (i, searchText) in searches.enumerated() {
        queue.addOperation {
            self.search(searchText, in: self.mapView.region, id: i)
        }
    }

    queue.addOperation {
        completion()
    }
}

func search(_ query: String, in region: MKCoordinateRegion, id: Int) {
    let semaphore = DispatchSemaphore(value: 0)

    os_log("%d starting", id)

    let request = MKLocalSearch.Request()
    request.naturalLanguageQuery = query
    request.region = region

    if #available(iOS 13, *) {
        request.resultTypes = .pointOfInterest
    }

    let search = MKLocalSearch(request: request)

    search.start { response, error in
        defer { semaphore.signal() }

        guard let mapItems = response?.mapItems else {
            os_log("  %d failed", id)
            return
        }

        os_log("  %d succeeded, found %d:", id, mapItems.count)
    }

    os_log("  %d waiting", id)
    guard semaphore.wait(timeout: .now() + 5) == .success else {
        os_log("  %d timedout", id)
        return
    }

    os_log("  %d done", id)
}

그 결과 :

2020-03-28 16:16:25.219565-0700 MyApp[46601:2107182] 0 starting
2020-03-28 16:16:25.220018-0700 MyApp[46601:2107182]   0 waiting
2020-03-28 16:16:25.438121-0700 MyApp[46601:2107033]   0 succeeded, found 10:
2020-03-28 16:16:25.438269-0700 MyApp[46601:2107182]   0 done
2020-03-28 16:16:25.438436-0700 MyApp[46601:2107182] 1 starting
2020-03-28 16:16:25.438566-0700 MyApp[46601:2107182]   1 waiting
2020-03-28 16:16:25.639198-0700 MyApp[46601:2107033]   1 succeeded, found 10:
2020-03-28 16:16:25.639357-0700 MyApp[46601:2107182]   1 done
2020-03-28 16:16:25.639490-0700 MyApp[46601:2107182] 2 starting
2020-03-28 16:16:25.639598-0700 MyApp[46601:2107182]   2 waiting
2020-03-28 16:16:25.822085-0700 MyApp[46601:2107033]   2 succeeded, found 10:
2020-03-28 16:16:25.822274-0700 MyApp[46601:2107182]   2 done
2020-03-28 16:16:25.822422-0700 MyApp[46601:2107162] 3 starting
2020-03-28 16:16:25.822567-0700 MyApp[46601:2107162]   3 waiting
2020-03-28 16:16:26.015566-0700 MyApp[46601:2107033]   3 succeeded, found 1:
2020-03-28 16:16:26.015696-0700 MyApp[46601:2107162]   3 done
2020-03-28 16:16:26.015840-0700 MyApp[46601:2107162] all done

그만한 가치는 세마포어를 사용하지 않고 대신 비동기 Operation하위 클래스를 사용합니다 . 예를 들어 여기정의 된AsynchronousOperation 클래스를 사용한 다음 다음을 수행 할 수 있습니다.

class SearchOperation: AsynchronousOperation {
    let identifier: Int
    let searchText: String
    let region: MKCoordinateRegion

    init(identifier: Int, searchText: String, region: MKCoordinateRegion) {
        self.identifier = identifier
        self.searchText = searchText
        self.region = region

        super.init()
    }

    override func main() {
        os_log("%d started", identifier)

        let request = MKLocalSearch.Request()
        request.naturalLanguageQuery = searchText
        request.region = region

        if #available(iOS 13, *) {
            request.resultTypes = .pointOfInterest
        }

        let search = MKLocalSearch(request: request)

        search.start { response, error in
            defer { self.finish() }

            guard let mapItems = response?.mapItems else {
                os_log("  %d failed", self.identifier)
                return
            }

            os_log("  %d succeeded, found %d:", self.identifier, mapItems.count)
        }
    }
}

그리고

let searches = ["restaurant", "coffee", "hospital", "natural history museum"]

let queue = OperationQueue()
queue.maxConcurrentOperationCount = 1

for (i, searchText) in searches.enumerated() {
    queue.addOperation(SearchOperation(identifier: i, searchText: searchText, region: mapView.region))
}

queue.addOperation {
    completion()
}

이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.

침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제

에서 수정
0

몇 마디 만하겠습니다

0리뷰
로그인참여 후 검토

관련 기사

분류에서Dev

MongoDB에서 동시에 여러 컬렉션에 대한 전체 텍스트 검색을 수행하는 방법

분류에서Dev

HSV를 JET 컬러 맵에 수동으로 다시 매핑

분류에서Dev

matplotlib 컬러 맵에서 검색되는 색상을 제어 할 수 있습니까?

분류에서Dev

데이터베이스 행을 해시 맵으로 검색

분류에서Dev

SQL에서 피벗을 사용하여 동적으로 여러 행 검색

분류에서Dev

맵에서 여러 값 검색

분류에서Dev

표준 색상을 이전 컬러 맵에서 새 색상으로 변환

분류에서Dev

데이터 공급자 클래스 컬렉션으로 해시 맵을 복용하고 API 테스트에서 여러 매개 변수를 전달 작성

분류에서Dev

Gnuplot : 불연속 컬러 맵에 대한 값을 수동으로 할당하는 방법

분류에서Dev

MATLAB에서 여러 컬러 맵에 대한 컬러 바 표시

분류에서Dev

java-목록을 값으로 사용하여 맵에서 단어 검색

분류에서Dev

SQLITE에서 여러 단어로 부분 검색을 수행하는 방법은 무엇입니까?

분류에서Dev

Julia에서 배열을 플로팅 할 때 컬러 맵 적용

분류에서Dev

프로그래밍 방식으로 Bing 검색 엔진에 여러 문자를 삽입하고 각각에 대해 검색을 수행합니다.

분류에서Dev

동적 SQL을 사용하여 하나의 매개 변수에서 여러 열로 와일드 카드 검색 수행

분류에서Dev

각 색상을 수동으로 정의하지 않고 큰 matplotlib 컬러 맵을 갖는 방법은 무엇입니까?

분류에서Dev

컬러 맵을 라인별로 플롯

분류에서Dev

seaborn을 사용하여 히트 맵을 그릴 때 여러 행을 하나의 레이블로 표시 할 수 있습니까?

분류에서Dev

Folium 맵에서 컬러 맵의 배경색을 추가하는 방법

분류에서Dev

OpenCV 및 C ++로 동시에 여러 색상 검색

분류에서Dev

AND 및 OR을 사용하여 쿼리로 여러 행 검색

분류에서Dev

여러 맵 작업을 병렬로 실행

분류에서Dev

Matplotlib 컬러 맵이 임계 값 미만으로 검은 색으로 설정 됨

분류에서Dev

MySQL에서 전체 텍스트 검색 : 하나의 DB 테이블에서 여러 단어로 검색 수행

분류에서Dev

매개 변수의 확률 분포를 기반으로하는 컬러 맵을 사용하여 플롯에 색상을 지정하는 방법은 무엇입니까?

분류에서Dev

컬러 맵을 사용하여 선 색상 변경

분류에서Dev

객체를 키로 사용하여 해시 맵 검색

분류에서Dev

Hibernate의 맵으로 DB에서 행 검색

분류에서Dev

여러 SQLAlchemy 모델에서 일반 "검색 창"검색을 수행하는 방법

Related 관련 기사

  1. 1

    MongoDB에서 동시에 여러 컬렉션에 대한 전체 텍스트 검색을 수행하는 방법

  2. 2

    HSV를 JET 컬러 맵에 수동으로 다시 매핑

  3. 3

    matplotlib 컬러 맵에서 검색되는 색상을 제어 할 수 있습니까?

  4. 4

    데이터베이스 행을 해시 맵으로 검색

  5. 5

    SQL에서 피벗을 사용하여 동적으로 여러 행 검색

  6. 6

    맵에서 여러 값 검색

  7. 7

    표준 색상을 이전 컬러 맵에서 새 색상으로 변환

  8. 8

    데이터 공급자 클래스 컬렉션으로 해시 맵을 복용하고 API 테스트에서 여러 매개 변수를 전달 작성

  9. 9

    Gnuplot : 불연속 컬러 맵에 대한 값을 수동으로 할당하는 방법

  10. 10

    MATLAB에서 여러 컬러 맵에 대한 컬러 바 표시

  11. 11

    java-목록을 값으로 사용하여 맵에서 단어 검색

  12. 12

    SQLITE에서 여러 단어로 부분 검색을 수행하는 방법은 무엇입니까?

  13. 13

    Julia에서 배열을 플로팅 할 때 컬러 맵 적용

  14. 14

    프로그래밍 방식으로 Bing 검색 엔진에 여러 문자를 삽입하고 각각에 대해 검색을 수행합니다.

  15. 15

    동적 SQL을 사용하여 하나의 매개 변수에서 여러 열로 와일드 카드 검색 수행

  16. 16

    각 색상을 수동으로 정의하지 않고 큰 matplotlib 컬러 맵을 갖는 방법은 무엇입니까?

  17. 17

    컬러 맵을 라인별로 플롯

  18. 18

    seaborn을 사용하여 히트 맵을 그릴 때 여러 행을 하나의 레이블로 표시 할 수 있습니까?

  19. 19

    Folium 맵에서 컬러 맵의 배경색을 추가하는 방법

  20. 20

    OpenCV 및 C ++로 동시에 여러 색상 검색

  21. 21

    AND 및 OR을 사용하여 쿼리로 여러 행 검색

  22. 22

    여러 맵 작업을 병렬로 실행

  23. 23

    Matplotlib 컬러 맵이 임계 값 미만으로 검은 색으로 설정 됨

  24. 24

    MySQL에서 전체 텍스트 검색 : 하나의 DB 테이블에서 여러 단어로 검색 수행

  25. 25

    매개 변수의 확률 분포를 기반으로하는 컬러 맵을 사용하여 플롯에 색상을 지정하는 방법은 무엇입니까?

  26. 26

    컬러 맵을 사용하여 선 색상 변경

  27. 27

    객체를 키로 사용하여 해시 맵 검색

  28. 28

    Hibernate의 맵으로 DB에서 행 검색

  29. 29

    여러 SQLAlchemy 모델에서 일반 "검색 창"검색을 수행하는 방법

뜨겁다태그

보관