스위프트 팀

13492 단어 iosasyncgcdswift

소개하다.


iOS 개발의 비동기적인 작업에 대해 이야기할 때, 우리는 단독 라인에서 실행될 코드에 대해 이야기한다.
우리는 왜 이렇게 해야 합니까?먼저 UI 관련 코드를 실행할 수 있는 유일한 스레드는 주 스레드Grand Central Dispatch의 홈 열에 의해 표시됨)입니다.예를 들어 백엔드 라인에서 업데이트할 수 없음UITableView.그래서 만약에 우리가 주 라인에서 네트워크 호출이 완료되기를 기다린다면 무슨 일이 일어날지 상상해 보세요.만약 이것이 메인 라인에서 실행되는 유일한 코드라면, 프로그램은 동결되어 나쁜 사용자 체험을 초래할 것이다.
이것이 바로 우리가 시간을 소모하는 작업(예를 들어 http 호출이 완료되기를 기다리는 것)이나 계산량이 많은 작업(예를 들어 응용CoreImage 필터)을 백엔드 라인에 의뢰하는 이유입니다.이렇게 하면 이 작업을 수행할 때 메인 라인이 막히지 않기 때문에 사용자는 백엔드에서 복잡한 작업을 완성할 때 응용 프로그램과 계속 상호작용할 수 있다.
비동기식 작업이 완료되면 UI를 업데이트하거나 원하는 작업을 수행할 수 있습니다.

동기식 및 비동기식


비동기적인 상하문에서 인코딩은 단순히 동기화 작업을 처리하는 것보다 더욱 도전적이다.
콘솔에서 인쇄할 수 있는 (무의미한) 기능이 있다고 상상해 보세요.
func say(_ text: String) {
    print(text)
}
상상해 봐요. 우리가 말하고 싶은 말"Hi", 그 다음에 몇 개의 짧은 말, 마지막"Goodbye"이에요.동기화 코드에서 이러한 작업을 쉽게 수행할 수 있습니다.
say("Hi")
say("I love cookies")
say("My dog is called Emma")
say("I develop iOS apps")
say("Goodbye")
간단해.줄마다 줄줄이 쓰여져 있는데, 그것들은 우리가 그것들을 쓰는 순서에 따른다.
이제 다음과 같은 비동기식 버전을 작성해 보겠습니다.
func say(_ text: String, completion: @escaping () -> Void) {
    let delay = Double.random(in: 1...2)
    DispatchQueue.main.asyncAfter(deadline: .now() + delay) {
        print(text)
        completion()
    }
}
이 코드의 역할은 완전히 같지만 그 외에 두 가지 일을 했다.
  • 지연 후 텍스트를 인쇄합니다.우리는 DispatchQueue.main.asyncAfter(...) 를 사용하여 지연을 도입했다.이렇게 함수는 현재 비동기적이다.지연도 무작위로 발생한다는 것은 얼마나 오래 실행될지 모른다는 것을 의미합니다.
  • 함수가 완성될 때 실행될 패키지를 전달했습니다.
  • 우선, 왜 이런 코드는 매우 어렵습니까?비동기 코드를 사용할 때, 우리는 많은 도전에 직면하게 될 것이다.우리는 앞으로의 글에서 라인 안전에 대해 토론하고, 비동기 코드에 존재할 수 있는 두 가지 문제를 설명할 것이다.

    연속 작업 실행


    첫 번째 문제는 비동기 함수를 어떻게 사용하여 동기화 행위를 시뮬레이션하는가이다.동기화 행위에 대해 나는 비동기 임무를 실행하고 완성을 기다린 다음에 첫 번째 임무의 결과를 사용하여 다른 비동기 임무를 실행하는 것을 가리킨다.
    http 요청을 처리할 때, 이것은 매우 흔히 볼 수 있는 상황이다.아마도 우리는 먼저 한 요청을 실행해서 한 사용자에게 로그인한 다음에 다른 요청을 실행해서 프로필에 대한 상세한 정보를 얻은 다음에 다른 요청을 실행해서 그들에 대한 다른 정보를 불러와야 할 것이다. 알겠습니다.로그인을 실행하지 않으면 나머지 http 호출을 실행할 수 없습니다.

    현재 코드는 이 문제를 해결할 수 있지만 첫 번째 함수의 완성 부분 중 두 번째 함수를 호출하는 것은 어떤 면에서도 가장 좋은 것이 아니다.그래서 우리의 예에서 이것은 다음과 같다.
    say("Hi") {
        say("I love cookies") {
            say("My dog is called Emma") {
                say("I develop iOS apps") {
                    say("Goodbye") {}
                }
            }
        }
    }
    
    너 문제 생겼어, 그렇지?이런 코드는 통상적으로 말일 피라미드it doesn't only happen in async code라고 불리기 때문에 조심해야 한다.
    이 문제를 해결하는 가장 일반적인 방법은 연합 수확기 Future 또는 PromiseKit'sPromise 또는 RxSwift flatMap 를 사용하는 것이다.만약 당신이 이런 상황에서의 업무 방식에 관심이 있다면, 나는 이런 상황을 위해 다른 글을 쓸 계획이지만, 지금은 this gistthis quite old but incredibly mind blowing talk from Javi Soto에서 나의 코드를 검사할 수 있다.

    동시 실행 작업


    비동기 코드를 사용할 때 두 번째로 자주 발생하는 문제는 병렬 실행 작업입니다.만약 우리가 비동기 코드의 실행 순서를 걱정하지 않는다면, 우리는 모든 비동기 작업을 병행하여 실행할 수 있고, 최종적으로 어떤 것들을 실행하여 완성할 수 있다.

    HTTP 호출도 이런 상황이 발생할 수 있는 흔한 곳이다.사용자의 프로필 화면에 접근하고 있다고 가정하십시오.이런 상황에서 우리는 그들의 사진, 게시물, 개인 정보 등을 위해 단말기에 전화를 걸어야 할 수도 있다.개인 정보를 불러오기 전에 그림이 불러오기를 기다리는 것이 의미가 있습니까?아니지.이런 상황에서 의미 있는 것은 모든 임무를 병행하여 시작하는 것이다.그 후에 우리는 적재 지시기나 어떤 것도 제거할 수 있다.
    우리의 예에서 우리는 동시적으로 Promise말한 다음에 모든 다른 단어"Hi","I love cookies""My dog is called Emma"를 병행적으로 말할 수 있다.그 후에 우리는'안녕히 계세요'라고 말할 수 있다.
    만약 비동기 프로그래밍 라이브러리를 사용한다면, 이것도 흔히 볼 수 있는 장면입니다. 그 중에서 틀림없이 당신과 관련이 있을 것입니다.연합 수확기 중에는 "I develop iOS apps" 가 있다.RxSwift에도 비슷한 함수 zip 가 있다.PromiseKit에서 사용할 수 있습니다 zip .
    이러한 구현에는 많은 고급 Swift가 포함됩니다.본고에서 우리는 더욱 간단한 병렬 비동기 코드를 처리하는 또 다른 방법을 모색할 것이다.

    언제 시작 해요?


    이것은 우리의 간단한 해결 방안이다.DispatchGroup는 매우 유용하고 사용하기 쉬운 종류이다.비동기식 작업 세트를 나타내며 다음과 같은 몇 가지 중요한 방법이 있습니다.
  • DispatchGroup: 호출enter()을 통해 우리는 enter 비동기 임무가 이미 시작되었다고 밝혔다.
  • DispatchGroup: leave() 비동기 작업이 종료되었음을 나타냅니다.
  • leave: 우리는 notify(queue:)를 사용하여 클립을 설정할 수 있다. notify에 들어간 모든 임무가 떠나면 이 클립을 실행할 수 있다.DispatchGroup 라는 동기화 버전 notify 이 하나 더 있는데, 이 버전은 wait(timeout:) 에 들어갈 때까지 현재 라인을 막습니다.
  • 이론은 충분하다. 이것이 실천에서 얼마나 간단한지 보자.
    우선 초기화가 필요합니다DispatchGroup:
    let group = DispatchGroup()
    
    간단해.이어서 우리는 임무가 시작될 때 팀에 들어가고 임무가 끝날 때 팀을 떠나야 한다.예를 들어 DispatchGroup라고 말하면 나는 이렇게 할 것이다.
    group.enter()
    say("I love cookies") {
        group.leave()
    }
    
    마지막으로, 대기열 구성"I love cookies"notify:
    group.notify(queue: .main) {
        print("Goodbye")
    }
    
    다른 작업이 모두 그룹을 떠날 때만 이 코드를 실행할 수 있습니다.
    그래서 전체 코드는:
    let group = DispatchGroup()
    
    print("Hi")
    
    group.enter()
    say("I love cookies") {
        group.leave()
    }
    
    group.enter()
    say("My dog is called Emma") {
        group.leave()
    }
    
    group.enter()
    say("I develop iOS apps") {
        group.leave()
    }
    
    group.notify(queue: .main) {
        print("Goodbye")
    }
    
    이것은 우리가 .main를 말한 다음에 다른 세 개의 짧은 말은 이후의 어느 때든지 출력될 것이다. 왜냐하면 그들은 병행적으로 실행되기 때문이다. 마지막에 우리는 "Hi"라고 말할 것이다.
    물론 이것은 단지 하나의 예일 뿐이다."Goodbye" 방법은 네트워크 호출, 데이터베이스 조작 또는 기타 실제 비동기 작업도 할 수 있다.

    요컨대


    우리는 비동기 코드가 무엇인지, 그리고 그것을 사용할 때 발생할 수 있는 두 가지 기본적인 문제를 정의했다. 그것이 바로 직렬과 병렬 실행 작업이다.병행 운행 임무에 대해 우리는 say가 간단한 해결 방안이라는 것을 발견했다.
    하지만, 나는 네가 도서관을 사용하는 것을 건의한다.내가 여기서 너희들에게 가르쳐 준 것은 기본적인 비동기 지식이지만 현실 세계에서 이것은 이렇게 간단하지 않기 때문에 생산 환경에서 전투 테스트를 거친 라이브러리를 사용하는 것이 항상 장점이다.저는 개인적으로 (iOS 13 이상 버전 지원) 애플Combine 또는 다른 방식으로 사용할 수 있다면RxSwift
    마지막으로, 본문을 끝내기 전에, 나는 반드시 async Wait를 언급해야 한다.ASync Wait이 있으면 모든 논의는 과거가 될 수 있습니다.그것은 동기화 코드를 작성하는 것처럼 비동기화 코드를 작성할 수 있도록 허용한다.이 제안 (이미 실현되어 다음 버전의 swift에서 발표될 것) here 을 볼 수 있고, 코드에서 시도해 볼 수도 있다. 예를 들어 this one.

    좋은 웹페이지 즐겨찾기