티스토리 뷰

iOS

[iOS] OperationQueue 톺아보기

국산 앨런 2019. 8. 22. 02:44

OperationQueue 란, 

 

동시성(Concurrecny) 프로그래밍 을 위해 iOS 환경에서 지원하는 라이브러리 입니다.

 

동시성(Concurrecny) 프로그래밍에 대한 자세한 설명은 동시성, 비동기 프로그래밍 톺아보기 에서 확인해 주세요 ㅎㅂㅎ

 

OperationQueue

이름을 살펴보면 Opertaion + Queue 인데,

 

말 그대로 대기열(Queue)에 추가한 동작(Operation) 의 실행을 관리하는 추상 클래스입니다.

 

동작에는 연산 객체(Operation Object)가 들어가게 되고, 이는 Foundation 프레임워크의 Operation 클래스 인스턴스입니다.

 

 

대기열(Queue)에서 동작(Operation) 관리

//연산 객체(Operation Object)를 대기열(Queue)에 추가합니다. 
func addOperation(_ op: Operation)
func addOperations(_ ops: [Operation], waitUntilFinished wait: Bool)

//전달한 클로저를 연산 객체(Operation Object)에 감싸서 대기열(Queue)에 추가합니다.
func addOperation(_ block: @escaping () -> Void)

//대기 중이거나 실행 중인 모든 연산(Operation)을 취소합니다.
func cancelAllOperations()	

//대기 중인 모든 연산(Operation)과 실행 중인 연산(Operation)이 모두 완료될 때까지 현재 스레드로의 접근을 차단합니다.
func waitUntilAllOperationsAreFinished()


 

    연산(Operation) 실행 관리
//동시에 실행할 수 있는 연산(Operation)의 최대 수입니다.
var maxConcurrentOperationCount: Int { get set } 

//대기열 작업을 효율적으로 수행할 수 있도록 여러 우선순위 옵션을 제공합니다.
var qualityOfService: QualityOfService { get set }

// 대기열(Queue)의 연산(Operation) 여부를 나타내기 위한 부울 값입니다. 
//false인 경우 대기열(Queue)에 있는 연산(Operation)을 실행하고, 
//true인 경우 대기열(Queue)에 대기 중인 연산(Operation)을 실행하진 않지만
//이미 실행 중인 연산(Operation)은 계속 실행됩니다.
var isSuspended: Bool { get set }

 

 

Example) 매우 큰 이미지 보여주기

 

 

구글에서 이미지 제일 큰놈으로다가 골라줍니다. 이미지를 클릭하시면 이미지 링크를 확인하실 수 있어요

 

 

 

이제 프로젝트를 만들어주고 스토리보드에 버튼과 이미지뷰를 추가해줍니다.

 

이미지 로딩을 위해 버튼의 action을 viewcontroller에 연결해주세요

 

**참고로 보안되지 않은 http 주소에서 파일 다운로드를 할 경우 아래와 같이 info.plist에 add row 해줍니다.

 

 

애플에서 보안은 생명이니까요...

 

@IBOutlet weak var imageView: UIImageView!
@IBAction func touchUpDownloadButton(_ sender: Any) {
    //big image url
    guard let imageURL: URL = URL(string: "https://upload.wikimedia.org/wikipedia/commons/3/3d/LARGE_elevation.jpg") else {
        return
    }
    
    do {
        let imageData: Data = try Data.init(contentsOf: imageURL)
        let image: UIImage = UIImage(data: imageData) ?? UIImage()
        self.imageView.image = image
    } catch {
        print("load image fail")
    }
}

 

코드는 위와 같습니다. URL에서 이미지를 받아오는 로직이어요.

 

바로 실행시켜보겠습니다.

 

 

버튼이...?

 

저 매우 거대한 이미지를 받아오느라 화면이 멈춘것을 (버튼확인) 볼 수가 있습니다.

 

아니 어떤 앱에서 이미지 보여준다고 화면이 멈춰..?

 

맞습니다..  그럼 사용자가 다 도망가겠죠..

 

이걸 고쳐야 하는데 왜 이런 문제가 생겼을까요?

 

let imageData: Data = try Data.init(contentsOf: imageURL)

 

바로 이 부분이 문제입니다.

 

네트워킹 작업을 하면서 imageData를 받아오는 코드가 현재 UI를 담당하는 main thread에서 돌고 있기 때문입니다.

 

여기서 저희가 배운 OperationQueue를 이용해서 이미지 다운로드 받는 작업을 백그라운 스레드로 Queue 에 담아버리겠습니다.

 

main thread 가 아닌 다른 흐름에서 동작하도록 말이죠.

 

OperationQueue().addOperation {
    do {
        let imageData: Data = try Data.init(contentsOf: imageURL)
        let image: UIImage = UIImage(data: imageData) ?? UIImage()
        self.imageView.image = image
    } catch {
        print("image faiil")
    }
}

 

잘- 담겼습니다. 한번 실행을 해볼까요?

 

 

 

오 뭔가..

 

뭔가 멈춤은 없는데

 

내 사진 어딨지?

 

 

음? 

 

UIImageView의 image 를 변경하는 작업, 즉 UI 를 변경하는 작업은 다시 main thread에서 해야하기 때문에 저런... 경고가 뜹니다.

 

OperationQueue.main.addOperation {
	self.imageView.image = image
}

 

image 를 변경하는 부분을 main thread 에서 작업하도록 명시를 해주고 다시 실행을 시켜보겠습니다.

 

 

 

이제 멈춤 현상없이 이미지 다운로드 작업이 잘되는 것을 확실할 수 있습니다

 

간단하게 작업에 대해서 각각 스레드를 지정해주어 보았습니다.

 

활용할 수 있는 방향이 상당히 많을 것 같다는게 느껴지시나요..?

 

오늘은 여기서 마치겠습니다.

 

20000~~

'iOS' 카테고리의 다른 글

[iOS] Navigation Item 톺아보기  (0) 2019.08.22
[iOS] ScrollView 톺아보기  (0) 2019.08.22
[iOS] 동시성, 비동기 프로그래밍 톺아보기  (0) 2019.08.21
[iOS] Photos 프레임워크 톺아보기  (2) 2019.08.10
[iOS] Codable 톺아보기  (0) 2019.08.01
댓글
공지사항