IOS UIkit- 2

김정현·2023년 4월 18일
0

UIKit

목록 보기
7/14

Dispatch Queue

대부분의 UI는 메인스레드에서 작동을 해야한다.
메인스레드가 중지하게되면 모든 작업들이 일시적으로 멈춰버리기 때문에 이를 해결하기위해 다른 스레드에 코드를 맡기고 결과값을 메인 스레드가 처리하게끔 한다.

import UIKit

class ViewController: UIViewController {
    
    @IBOutlet weak var finishLabel: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
}

    @IBAction func action1(_ sender: Any) {
        simpleClosure {
            //DispatchQueue.main.async { ,이쪽에 기입해도 됨
            self.finishLabel.text = "끝"
        }
    }
    
    func simpleClosure(completion: @escaping () -> Void) {
        
        DispatchQueue.global().async {  //메인 스레드가 아닌 다른 스레드에게 작업을 맡김
            
            for index in 0..<10 {
                Thread.sleep(forTimeInterval: 0.1)  //0.1 초씩 늦게 실행 되게 함, 메인스레드 자체를 멈춰버리기 때문에 모든게 멈춰버림
                print(index)
            }
            
            DispatchQueue.main.async {  //메인 스레드에게 completion 클로저 수행을 맡김
                completion()
            }
         }

    }

DispatchGroup

어떤 작업을 하는 것들을 묶어서 표현하고 싶다면 그룹으로 묶으면 된다.

@IBAction func action2(_ sender: Any) {
        
        let dispatchgroup = DispatchGroup()  //dispatch 그룹을 형성 (비었음)
        
        let queue1 = DispatchQueue(label: "q1") //queue1은 작업자 
        let queue2 = DispatchQueue(label: "q2")
        let queue3 = DispatchQueue(label: "q3")
        
        queue1.async(group: dispatchgroup) { //dispatch 그룹에 queue1 을 넣고 작업을 실행한다.
            for index in 0..<10 {
                Thread.sleep(forTimeInterval: 0.1)
                print(index)
            }
        }
        
        queue2.async(group: dispatchgroup) {
            for index in 10..<20 {
                Thread.sleep(forTimeInterval: 0.1)
                print(index)
            }
        }
        
        queue3.async(group: dispatchgroup) {
            for index in 20..<30 {
                Thread.sleep(forTimeInterval: 0.1)
                print(index)
            }
        }
        
        dispatchgroup.notify(queue: DispatchQueue.main) {  //그룹에 작업이 끝나면 출력한다. , main스레드에서 queue가 작업을 실행하게함
            print("끝")
        }
     }
}

queue1, 2, 3들은 메인이 아닌 새로운 스레드를 생성한 것이다. 결과적으로 ui를 출력하기 위해서는 메인 스레드로 정보를 옮겨야하고, 그냥 단순 계산같은것은 여기서 다 처리할 수 있다.

만약

queue1.async(group: dispatchgroup) {
	DispatchQueue.global().async {  //이렇게 하면 다른 스레드에게 이 작업을 맡겨버림 
            for index in 10..<20 {
                Thread.sleep(forTimeInterval: 0.1)
                print(index)
            }
        }
     }   
  
        }

이렇게 다른 스레드에게 작업을 맡긴다면 notify는 작업이 끝난줄 알고 종료해버린다. 그럴때

dispatchGroup.enter()  //작업을 시작함
dispatchGroup.leave()  //작업을 끝냄

이런식으로 작업의 시작과 끝을 알릴 수 있다.

sync

async와 다르게 작업을 다 처리할 때 까지는 여러개의 작업자든 한개이건 상관없이 작동을 멈춘다.
가장 중요한 작업을 실행할 때 사용하게 된다.

  • sync는 sync의 내용이 끝날때까지는 스레드가 락이 걸린다.

-같은 큐에 같은 큐가 들어감

queue1.sync {
            for index in 0..<10 {
                Thread.sleep(forTimeInterval: 0.1)
                print(index)
            }
        
------------------------------- 여기까지 실행되고 deadlock이 걸려버림
        queue1.sync {
            for index in 10..<20 {
                Thread.sleep(forTimeInterval: 0.1)
                print(index)
            }
        }
  }
  • deadlock: 상대 작업이 끝날때까지 서로 계속 기다리는 상태

바깥에 queue1이 실행되는 중이기 때문에 내부에 sync때문에 오류가 발생함
이런 이유로 메인 스레드는 끝나는게 없기 때문에 sync를 사용할 경우 반드시 에러가 발생한다.

qos(우선순위)

작업을 수행하는 우선순위를 설정한다. 절대적으로 보장하지는 않는다.

qos: DispatchQoS <- command+control 우클릭해서 들어가면 순위를 볼 수 있다.

queue2.async(group: dispatchgroup, qos: .background) {   //우선 순위 가장 낮음
            for index in 10..<20 {
                Thread.sleep(forTimeInterval: 0.1)
                print(index)
            }
        }

0개의 댓글