55,000원
다른 수강생들이 자주 물어보는 질문이 궁금하신가요?
- 미해결iOS Concurrency(동시성) 프로그래밍, 동기 비동기 처리 그리고 GCD/Operation - 디스패치큐와 오퍼레이션큐의 이해
AsyncOperation을 async await Task로 대체 가능한 지에 대한 질문
비동기 함수를 오퍼레이션으로 감싸는 경우에 대해 보다가 궁금한 게 있습니다. Async, await, asyne let, Task를 이용해서 비동기함수를 오퍼레이션으로 감싸는 처리를 대체하는 코드나 클래스를 만들 수 있을것 같은데 어떻게 생각하시는지 궁금합니다. 일단 GCD + DispatchGroup + completionHandler Closure 기반의 코드는 async await 등으로 꽤 많이 대체할 수 있지 않을까 생각이 들어서요
- 해결됨iOS Concurrency(동시성) 프로그래밍, 동기 비동기 처리 그리고 GCD/Operation - 디스패치큐와 오퍼레이션큐의 이해
교착상태 발생 가능성
안녕하세요! 강의 수강 중 질문 있어 글을 남깁니다.'교착상태의 다양한 발생 가능성' 부분을 보고 있습니다.그 중 첫 번째가 '동기 작업이 현재의 쓰레드를 필요로 하는 경우'입니다. 이 부분은 3-2 강의를 참고해서 이해를 했는데요. 아래처럼 비동기로 작업을 보냈는데, 자신을 block시킨 global queue에 할당되어 교착된 상태입니다.DispatchQueue.global().async { DispatchQueue.global().sync { ... } }두 번째가 '앞선 작업이 현재 쓰레드를 필요로 하는 경우'인데요, 생각해보니 위의 케이스를 제외하고는 마땅한 경우가 떠오르지 않아서요! 혹시 첫 번째 상황과 같은 것을 의미하는지, 제가 설명한 부분이 맞는 말인지 궁금합니다. 감사합니다! :)
- 미해결iOS Concurrency(동시성) 프로그래밍, 동기 비동기 처리 그리고 GCD/Operation - 디스패치큐와 오퍼레이션큐의 이해
GCD 프로젝트 iOS 16 실행 오류 문제
안녕하세요, 앨런 님. GCD 프로젝트의 iOS16 실행과 관련해 질문이 있어 글을 남겨봅니다.이번 Xcode 업데이트 이후, iOS16으로 설정된 iPhone 14, iPhone SE 3rd gen 등의 시뮬레이터는 물론, iOS16으로 업데이트 된 기기를 직접 연결해서 돌려보면 Collection View의 이미지가 정상적으로 로딩되지 않는 것 같습니다.아래에 1) 정상으로 작동하지 않는 iPhone 14Pro (16.0) 이미지와 2) 정상으로 작동하는 iPhone 12 (14.4) 이미지를 첨부하였습니다.혹시 이번 Xcode14와 iOS16으로 업데이트 되면서 Collection View 또는 Image View와 관련해서 변경된 사항이 있을까요?감사합니다. 덕분에 강의 잘 수강하고 있습니다 :)
- 해결됨iOS Concurrency(동시성) 프로그래밍, 동기 비동기 처리 그리고 GCD/Operation - 디스패치큐와 오퍼레이션큐의 이해
GCD 사용 중 질문 드립니다!
안녕하세요, GCD 강의 챕터 수강 중에 질문 있어 글 작성드립니다.예제의 asyncTiltShift함수에서 runQueue와 completionQueue를 구별하는 이유가 있을까요? completionQueue에서는 단순히 completionHandler 처리만 하기 때문에 따로 Queue에 task를 할당하는 이유가 있는지, 아래 코드처럼 바꿔줘도 상관없는지 궁금합니다!func asyncTiltShift2(_ inputImage: UIImage?, runQueue: DispatchQueue, completion: @escaping (UIImage?, Error?) -> ()) { runQueue.async { var error: Error? error = .none let outputImage = tiltShift(image: inputImage) completion(outputImage, error) } }설명 친절하고 상세하게 해주셔서 늘 감사드립니다 :)
- 미해결iOS Concurrency(동시성) 프로그래밍, 동기 비동기 처리 그리고 GCD/Operation - 디스패치큐와 오퍼레이션큐의 이해
DispatchQueue main 동작 방식
안녕하세요. 강의를 보다가 병렬큐에서의 동작 방식은 이해를 했지만 메인큐 즉 serial큐에서의 동작 원리가 정확하게 이해가 되지 않아서 질문을 남깁니다. 1. 메인스레드에서 main.async를 사용하게되면 현재 메인스레드에서 작업중인 태스크를 메인큐로 보냈다가 이걸 다시 메인스레드로 비동기로 할당한다는건데 동작 방식이 결국 후순위로 미룬다는 의미인거 같아서 조금 헷갈리네요.. 메인스레드에서 main.async를 사용한다는 것은 오래 걸리는 작업은 나중에 해~ 이런 의미로 사용하는걸까요? 이러한 동작방식은 defer를 사용하는 것과 유사해보입니다! 2. DispatchQueue.main.async { for i in 0..<20 { print(i) } } //2번 작업 for i in 60..<80 { print(i) } //3번 작업 DispatchQueue.main.async { for i in 20..<40 { print(i) } } //4번 작업 for i in 40..<60 { print(i) } 이러한 코드를 테스트 했을 때 동작 순서가 2 -> 1 -> 4 -> 3으로 예상을 했습니다. 그 이유는 1번 작업이 메인 큐로 갔을 때 다음 스레드가 진행되고 메인스레드에 2번 작업이 1번작업 뒤에 바로 할당된다고 생각을 했습니다. 하지만 동작 방식은 2 -> 4 -> 1- > 3으로 하는 것을 확인했습니다. 메인 스레드에서 비동기로 호출 했을 때 기존에 메인스레드에 있는 작업들의 동작 속도가 너무 빨라서 메인큐에서 메인스레드로 할당하기 전에 작업이 끝나서 그런건가라고 생각을 하고 sleep을 줘도 순서는 동일했습니다. 다음과 같이 main스레드에서 비동기를 처리하게 되면 파일에 선언된 코드들이 다 순차적으로 실행되고 나중에 비동기로 넘긴 태스크들이 메인스레드에 할당되는 것인지도 궁금합니다. 3. URLSession은 비동기적으로 작동하는 것으로 알고있는데 이것 또한 메인스레드에서 동작하고 있는 것이 맞나요? 혹시 제가 이해한 개념 중 오개념이 있다면 말씀해주시면 감사하겠습니다!
- 미해결iOS Concurrency(동시성) 프로그래밍, 동기 비동기 처리 그리고 GCD/Operation - 디스패치큐와 오퍼레이션큐의 이해
안녕하세요 질문드립니다.
안녕하세요. 강의 항상 감사합니다 :) 클로저 관련 공부하다가 하나의 함수 내에서 weak var weak_self = self 위처럼 변수를 선언한 후 클로저 내에서 캡쳐리스트를 사용 하지 않고 위에 선언한 weak_self?.xxx 이런식으로 접근해서 사용하는 코드가 있는데 위의 방식도 클로저 내에서 캡쳐리스트를 하여 [weak self] self?.xxx 접근할 때와 차이가 없는건가요? 스택오버플로우에서 비슷한 질문이 있어서 전달드립니다. https://stackoverflow.com/questions/41676764/difference-between-weak-self-and-weak-var-weakself-self
- 미해결iOS Concurrency(동시성) 프로그래밍, 동기 비동기 처리 그리고 GCD/Operation - 디스패치큐와 오퍼레이션큐의 이해
자료 다운로드가 안됨
자료 다운로드가 안되는데 버그인가요?
- 미해결iOS Concurrency(동시성) 프로그래밍, 동기 비동기 처리 그리고 GCD/Operation - 디스패치큐와 오퍼레이션큐의 이해
질문드립니다.
안녕하세요. 동기함수를 비동기 함수처럼 사용하는 법에서 동기함수(tiltShift)를 내부 내용을 그냥 비동기로 한번 감싸고 escaping 컴플리션 함수로 만들면 되지 않나요? DispatchQueue.global.async { guard let ~~ return image.applyBlur(radius:6, maskImage: mask) } 따로 작업을 마치고나서의 큐를 이용하는 이유가 궁금합니다!
- 미해결iOS Concurrency(동시성) 프로그래밍, 동기 비동기 처리 그리고 GCD/Operation - 디스패치큐와 오퍼레이션큐의 이해
8.LazyVar 코드에서 궁금한 점이 있습니다.
안녕하세요! 0.GCD - 8.LazyVar 코드 중 2) 시리얼큐+Sync로 해결(Thread-safe처리) 부분을 테스트 하다 궁금한 점이 생겨 글 남깁니다. 코드를 실행하면 다음과 같은 결과가 나옵니다. 이때, id 2가 1보다 먼저 나오는 경우가 있습니다. 대부분은 제대로 나오나 가끔 이런 식으로 순서가 바뀌어 나옵니다. 궁금한 점은 for문을 통해 돌렸기 때문에 id 2를 다루는 작업이 id 1을 다루는 작업보다 스레드에 더 늦게 배치될 것이라 예상이 되는데 시리얼 큐를 사용하는데 어떻게 먼저 나올 수 있는 건가요? 감사합니다.
- 미해결iOS Concurrency(동시성) 프로그래밍, 동기 비동기 처리 그리고 GCD/Operation - 디스패치큐와 오퍼레이션큐의 이해
Main.async 질문
안녕하세요 앨런! 강의를 듣던중 main.async에 대해 이해가 잘 가지 않아 질문드립니다. Dispathqueue.main.async는 task를 main 큐(main쓰레드)에 보내서 비동기적으로 처리하겠다는 말인데, 아시다시피 main 큐는 직렬 큐이기 때문에 비동기적으로 처리하려고해도 물리적으로 1개의 쓰레드밖에 없기 때문에 순서대로 task를 처리하게 됩니다. 결국엔 동기적으로 처리하게 되는거나 마찬가지인데, 왜 굳이 메인쓰레드를 비동기적으로 처리하는지 궁금합니다.
- 미해결iOS Concurrency(동시성) 프로그래밍, 동기 비동기 처리 그리고 GCD/Operation - 디스패치큐와 오퍼레이션큐의 이해
BlockOperation을 Serial OperationQueue에 넣었을 때 Serial하게 실행되지 않는 것 같습니다.
안녕하세요, 강의 잘 보고 있습니다. BlockOperation 자체는 Operation에 등록된 block들이 concurrent하게 실행된다고 나와 있고, 이걸 serial하게 실행하고 싶으면 이 BlockOperation을 maxConcurrentOperationCount를 1로 설정한 OperationQueue에 넣으면 된다고 하신 걸로 이해했습니다. 그래서 다음과 같이 코드를 작성하고 돌려봤는데, 등록한 block의 순서대로 print되지 않는 걸 봐서는 serial하게 실행되지 않는 것 같습니다. let operation = BlockOperation() for i in 0 ..< 1000 { operation.addExecutionBlock { print(i, Thread.current) } } let queue = OperationQueue() queue.maxConcurrentOperationCount = 1 queue.addOperation(operation) 이 코드를 실행하면 i가 0부터 999까지 순서대로 프린트되지 않고 랜덤하게 프린트됩니다. let queue = OperationQueue() queue.maxConcurrentOperationCount = 1 for i in 0 ..< 1000 { queue.addOperation { print(i, Thread.current) } } 반면에 위처럼 BlockOperation을 사용하지 않고 maxConcurrentOpreationCount가 1인 OperationQueue에 block을 순서대로 추가하면, 이전에 설명해주신 대로 serial하게 실행되어 0부터 999까지 차례대로 프린트됩니다. Thread.current의 프린트 결과를 봐도 두 번째 코드보다 첫 번째 코드에서 더 많은 쓰레드를 사용하는 것으로 보입니다. (질문과는 관계 없긴 한데, 이 과정에서 OperationQueue가 항상 동일한 쓰레드를 사용해서 Operation을 실행하지는 않는다는 것을 확인했습니다. 반면 serial하게 동작하는 커스텀 DispatchQueue는 항상 동일한 쓰레드를 사용하는 것으로 확인했습니다. maxConcurrentOperationCount가 1인 OperationQueue는 항상 동일한 쓰레드를 사용하지는 않더라구요. 사실 maxConcurrentOperationCount가 말 그대로 concurrent하게 실행될 수 있는 Operation의 개수를 말하는 것이지, 실행될 수 있는 쓰레드의 개수를 말하는 건 아니니까 이건 이것 나름대로 이해한 것 같습니다.) executionBlocks를 얻어서 좀 더 봐보려고 했는데 잘 안되더라구요. 혹시 이 부분 관련해서 제가 잘못 이해한 부분이 있는지, 아니면 추가 설명을 부탁드릴 수 있을까요? 감사합니다.
- 미해결iOS Concurrency(동시성) 프로그래밍, 동기 비동기 처리 그리고 GCD/Operation - 디스패치큐와 오퍼레이션큐의 이해
GCD final 프로젝트의 IndexPath로 매개변수 넘겨주는 부분에 대해 질문 드립니다.
안녕하세요, 앨런 님. 강의를 듣던 중 궁금한 점이 생겨 질문 드립니다. GCD final 프로젝트에서 PhotoCell 자체가 아닌 IndexPath를 매개변수로 넘겨줘야 한다고 말씀해주셨습니다. 이때, cell을 전달하면 안 되는 이유 중 하나로 이미 지나간 영역을 뽑아낼 수 있다고 말씀해주셨는데, IndexPath 같은 경우도 (section, row) 값을 사용하여 이미 지나간 영역의 이미지를 다운로드 하는 게 아닌가 싶은 궁금증이 생겨 질문을 드리게 되었습니다. 본 코드에서는 if let cell = self.collectionView.cellForItem(at: indexPath) as? PhotoCell 이 부분에서 지나간 IndexPath일 경우를 필터링한다고 생각하면 되는 걸까요? 그렇다면 만약 필터링을 해준다면 cell을 매개변수로 넘기는 경우도 사용 가능한지 궁금합니다. 필터링을 하더라도, cell은 재사용되기 때문에 cell을 그대로 사용하는 것은 안 좋지 않을까 추측하는데 확실치 않아서 질문 드립니다. 또한, indexPath가 아닌 클로저를 매개변수로 넘길 때도 문제점이 발생할까요? 예를 들어 { (image: UIImage) in cell.display(image: image) } 다음과 같은 클로저를 매개변수로 넘기는 것은 괜찮은 판단인지 궁금하여 질문 드립니다. 매개변수로 cell 자체 말고 IndexPath를 넘기는 일은 평소에 당연하게 생각했던 일이지만 확실한 이유를 잘 모르겠어서 이렇게 질문 드리게 되었습니다. 본 강의를 들으면서 많은 것을 배워갑니다. 감사합니다.
- 미해결iOS Concurrency(동시성) 프로그래밍, 동기 비동기 처리 그리고 GCD/Operation - 디스패치큐와 오퍼레이션큐의 이해
Operation의 순서기능 중 질문드립니다!
강의 한 편 한 편 볼때마다 지식이 업그레이드 되는 기분입니다. 좋은 강의 항상 감사드립니다~! 다름이 아니라 Operation의 순서기능 중 Operation에서 이전 작업의 결과물을 받기 위해선 프로토콜을 채택 혹은 작업물을 넘기는 Operation을 만들어야 한다고 말씀해주셨는데 그냥 outputImage를 직접 가져오는 것으로 해도되지 않을까요? 아래의 방법입니다! class TiltShiftOperation: Operation { var inputImage: UIImage? var outputImage: UIImage? override func main() { if inputImage == .none, // 인풋이미지가 없으면, let dependencyImageProvider = dependencies .filter({ $0 is ImageLoadOperation}) .first as? ImageLoadOperation { // 프로토콜이 아닌 직접적으로 Operation꺼내기 inputImage = dependencyImageProvider.outputImage } // 실제 작업 outputImage = tiltShift(image: inputImage) } } 이 방법의 문제는 뭐가 있을까요? 재사용성의 의미에서는 확실히 Protocol을 이용한 타입 캐스팅이 좋지만 그것 말고 프로토콜 채택으로 가져가는 또다른 장점이 있을까요?
- 미해결iOS Concurrency(동시성) 프로그래밍, 동기 비동기 처리 그리고 GCD/Operation - 디스패치큐와 오퍼레이션큐의 이해
큐로 sync하게 호출하는 이유가 궁금합니다
안녕하세요! 좋은 강의 정말 잘 듣고 있습니다ㅎㅎ 다름이 아니라 Dispatch Barrier강의를 듣던 중 궁금한 점이 생겼습니다. get, set 각각 다른큐로 sync, async하게 넘기는 예시를 보았습니다. 여기서 궁금한 점이 생겼는데 get을 하는데 굳이 큐로 sync하게 넘기는 이유가 있을까요? 현재 쓰레드에서 그대로 get을 하면 다른 쓰레드로 넘어가는 낭비를 하지않고 그대로 받아 올 수 있지 않나요? 여기서 조금 더 나아가서 현 쓰레드에서 큐(다른 쓰레드)로 굳이 sync하게 넘어가야할 이유를 모르겠습니다. 어차피 현 쓰레드가 동작하지 못하고 기다릴 바에야 현 쓰레드에서 모든 걸 처리하면 되지 않나요?
- 미해결iOS Concurrency(동시성) 프로그래밍, 동기 비동기 처리 그리고 GCD/Operation - 디스패치큐와 오퍼레이션큐의 이해
비동기 함수 만드는 법에 대해서 질문드립니다!
안녕하세요. 강의 잘 듣고 있습니다. 질문이 하나 있어서요! func asyncTiltShift(_ inputImage: UIImage?, runQueue: DispatchQueue, completionQueue: DispatchQueue, completion: @escaping (UIImage?, Error?) -> ()) runQueue와 completionQueue의 type이 DispathQueue로만 되어있던데, .체이닝으로 보니 main과 global은 안나오더라구요. 이 부분을 이해하려면, asyncTiltShift 메서드에 인자 DispatchQueue만 있다는 것은 DispatchQueue가 main과 global을 사용할 수 있어서 라고 이해하면 될까요? 수업에 나와있지않은 부분이라 실례를 무릎쓰고 여쭤봅니다^^;;
- 미해결iOS Concurrency(동시성) 프로그래밍, 동기 비동기 처리 그리고 GCD/Operation - 디스패치큐와 오퍼레이션큐의 이해
concurrent질문입니다.
아래처럼 concurrent임에도 클로저내에 있는 task들은 하나로 취급되어 print(slowadd(1,5))하나하나는 모두 동일한 스레드에서 처리되는건가요?
- 미해결iOS Concurrency(동시성) 프로그래밍, 동기 비동기 처리 그리고 GCD/Operation - 디스패치큐와 오퍼레이션큐의 이해
retain cycle 질문입니다.
강의 중 코드 입니다. 아래에서 weak self 하지 않을 경우 강한 참조 사이클은 일어나지 않는다고 하셨는데, 1.클로저가 해당 클래스를 참조하고 있지만 해당 클래스는 클로저를 참조하고 있지 않기때문인가요?2.weak self하지 않을때, sleep(3)에 의해 클로저가 3초정도 클래스를 참조하고 있어 그 사이에 class가 dismiss되어도 self가 nil이 아닌상황이 지속되고, 3초 이후 즉 클로저가 모두 진행된 이후에는 클로저가 클래스를 더 이상 참조하고 있지않아 class가 dismiss할 경우 deinit이 정상작동 되는 것인가요?class ViewController2: UIViewController { var name: String = "뷰컨" func doSomething() { // 강한 참조 사이클이 일어나지 않지만, 굳이 뷰컨트롤러를 길게 잡아둘 필요가 없다면 // weak self로 선언 DispatchQueue.global().async { [weak self] in sleep(3) guard let weakSelf = self else { return } print("글로벌큐에서 출력하기: \(weakSelf.name)") DispatchQueue.main.async { print("메인큐에서 출력하기: \(weakSelf.name)") } } } deinit { print("\(name) 메모리 해제") } } func localScopeFunction2() { let vc = ViewController2() vc.doSomething() } localScopeFunction2()
- 미해결iOS Concurrency(동시성) 프로그래밍, 동기 비동기 처리 그리고 GCD/Operation - 디스패치큐와 오퍼레이션큐의 이해
GCD 질문입니다.
dispatchqueue.global().async 안에 dispatchqueue.global().sync를 하면 교착이 걸릴 수 있어서 안해야한다고 말씀하셨는데요, 제가 이해한 부분이 맞는지 봐주시겠습니까.. main thread에서 dispatchqueue.global().async 를 발견해서 예를들어 gcd에서 task를 thread3에 주고 기다리지않고(async) 곧 바로 return 하였습니다. 그런데 우연히 그 task의 내부인 task(sync)가 thread3에 할당되었습니다. 1. 기다리지 않는다고 했는데 기다려야하는 일이 혼선되어 데드락이 일어나는 것인가요? 2. 처음에 async task가 thread3에 배정된 상태인데, 그 thread3에서 global()을 부를 경우에도 동인한 쓰레드(thread3)로 배정될 수 있나요?
- 미해결iOS Concurrency(동시성) 프로그래밍, 동기 비동기 처리 그리고 GCD/Operation - 디스패치큐와 오퍼레이션큐의 이해
시리얼큐와 Sync
"GCD - 7.(심화) Thread-safe한 코드의 구현과 방법"에서 두번째 강의 "시리얼큐와 Sync"의 7분 44초 부분 질문입니다. ppt 맨아래에 "디폴트 글로벌큐에서의 기다림/시리얼큐에서의 기다림이 아님" 이라고 적혀있는데, 이 부분을 "디폴트 글로벌큐에서의 기다림 그리고 시리얼큐에서의 기다림이 아님" 이라고 이해하는게 맞는건가요? 코드에서 global큐에서 sync 코드를 시작하고 있으니 디폴트 글로벌 큐에서 기다리는게 아닌가 잘 이해가 안가서 질문드립니다.
- 해결됨iOS Concurrency(동시성) 프로그래밍, 동기 비동기 처리 그리고 GCD/Operation - 디스패치큐와 오퍼레이션큐의 이해
global()에서는 배리어가 동작하지 않는 것 같아요
아래는 제가 강의를 듣고 임의로 만들어본 예제입니다. concurrentQueue를 custom 큐로 만들어주면 잘 동작하는 반면 global()을 사용하면 배리어가 동작하지 않았습니다. 왜 이런건가요? import Foundation var shared: Int = 0 let group = DispatchGroup() let concurrentQueue = DispatchQueue(label: "com.raywenderlich.number.isolation", attributes: .concurrent) for _ in (1...30) { concurrentQueue.async(group: group) { print(shared, terminator: "") } } concurrentQueue.async(group: group, flags: .barrier) { print("") print("Barrier In") shared += 1 sleep(3) print("Barrier Out") } for _ in (1...30) { concurrentQueue.async(group: group) { print(shared, terminator: "") } } group.wait()