Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
Tags
- 상태패턴
- 스테이트패턴
- unowned
- 추상팩토리패턴
- 이터레이터패턴
- 데코레이터패턴
- 어댑터패턴
- 컴포지트패턴
- 커맨드패턴
- 템플릿메서드
- SWIFT
- 팩토리메서드패턴
- Mobile
- 스트래터지패턴
- RxSwift
- 전략패턴
- 싱글턴패턴
- WKWebView
- 파사드패턴
- 컴파운드패턴
- ios
- cocoapods
- Lifecycle
- DispatchQueue
- 프록시패턴
- 옵저버패턴
- ViewController
- Scenedelegate
- 디자인패턴
- Xcode
Archives
- Today
- Total
ios dev kangwook.
Swift) Semaphore 본문
Semaphore는 쉽게 말하자면 비동기 구문을 동기화해주기 위한 객체라고 할 수 있다.
동기화가 되면 프로그램은 비동기 구문의 실행을 기다려주기 때문에, 비동기 구문을 사용하더라도 규칙적이고 정확한 프로그램의 개발이 가능하다.
- 초기값을 0으로 가지는 semaphore 생성하는 구문
- value 값은 음수가 되면 안됨
let semaphore = DispatchSemaphore(value: 0)
- semaphore를 대기시키는 구문
semaphore.wait()
- value 값을 +1 해주는 구문
- 초기값이 0이었던 semaphore는 signal()함수를 통해 value = 1이 되므로 대기중에서 깨어나게 된다.
semaphore.signal()
예시
Semaphore를 이용한 비동기 구문의 동기화는 dataTask를 이용한 네트워크 통신에서 많이 쓰인다.
- dataTask의 네트워크 통신은 비동기식이기 때문에 프로그램이 네트워킹하는 동안 기다려주지 않고 다른 프로그램 구문을 실행시켜버리기 때문
즉, 수신받은 네트워킹 결과에 따른 기능을 처리해줄 수 없다!
func ServerConnect(api: String, params: String) -> NSDictionary {
let apiUrl = url + api
var request = URLRequest(url: URL(string: apiUrl)!)
request.httpMethod = "POST"
request.httpBody = params.data(using: String.Encoding.utf8)
var json: NSDictionary!
let task = URLSession shared.dataTask(with request, completionHandler: { data, response, error in
if error != nil {
print("error : \(error)")
return
}
print("Success Request, Params : \(params)")
let responseString = String(data: data!, encoding: .utf8)
print("responseString = \(responseString)")
json = ParsingJSON(data: data!)
})
task.resume()
print("resultJSON: \(json)"
return json
}
- task.resume()을 통해 네트워킹이 시작되지만, 비동기식이기 때문에 네트워킹이 끝나기도 전에 print("resultJSON: \(json)") 구문과 return json 구문이 실행된다.
- 따라서 네트워킹이 끝나기도 전에 json이 사용되기 때문에 json의 값은 nil이 되어 오류가 발생하는 것!
func ServerConnect(api: String, params: String) -> NSDictionary {
let apiUrl = url + api
var request = URLRequest(url: URL(string: apiUrl)!)
request.httpMethod = "POST"
request.httpBody = params.data(using: String.Encoding.utf8)
var json: NSDictionary!
let semaphore = DispatchSemaphore(value: 0) // Semaphore선언
let task URLSession.shared.dataTask(with: request, completionHandler: { data, response, error in
if error != nil {
print("error : \(error)")
return
}
print("Success Request, Params : \(params)")
let responseString = String(data: data!, encoding: .utf8)
print("responseString = \(responseString)")
json = ParsingJSON(data: data!)
semaphore.signal() // Networking이 끝나면 신호 보내기
})
task.resume()
semaphore.wait() // Networking이 끝날 때 까지 대기
print("resultJSON: \(json)")
return json
}
- 비동기식으로 작동하는 dataTask의 네트워킹이 완료될 때까지 기다리기 때문에 print되는 json값과 return되는 json값이 nil이 아닌 정확한 값이 전달되게 된다.
Sample 코드 작성
- Network 버튼을 누르면 Server로부터 데이터를 받아와서 출력
- semaphore를 사용함으로써 해당 네트워킹 작업이 끝날 때까지 기다리게 됨
// ...
func bindEvent() {
// ...
networkButton.rx.tap
.withUnretained(self)
.subscribe(onNext: { _ in
let result = self.network()
dump(result)
}).disposed(by: disposeBag)
}
func network(params: String? = nil) -> Dictionary<String, Any> {
let apiURL = "https://api.itbook.store/1.0/new"
var request = URLRequest(url: URL(string: apiURL)!)
request.httpMethod = "GET"
var json: [String: Any]!
let semaphore = DispatchSemaphore(value: 0)
let task = URLSession.shared.dataTask(with: request, completionHandler: { data, response, error in
if let error = error {
print("error : \(error)")
}
let responseString = String(data: data!, encoding: .utf8)
json = self.parsingJson(text: responseString!)
semaphore.signal()
})
task.resume()
semaphore.wait()
print("ResultJSON: \(String(describing: json))")
return json
}
// ...
참조
'Swift' 카테고리의 다른 글
Swift) Initialization (0) | 2022.10.02 |
---|---|
Swift) Property (0) | 2022.09.25 |
Swift) DispatchQueue (0) | 2022.09.22 |
Swift) Concurrency, GCD (0) | 2022.09.20 |
Swift) Opaque Type (0) | 2022.09.11 |
Comments