티스토리 뷰
Result
어떤 결과값이 성공 or 실패로 나뉜다면 Result로 쓰면 좋음.
기본코드⬇️
더보기
class ViewController: UIViewController {
let centerLabel = UILabel()
override func viewDidLoad() {
super.viewDidLoad()
setUI()
}
}
// MARK: -URLSession
extension ViewController {
func setUI() {
setConstraints()
setAttributes()
}
func setConstraints() {
view.addSubview(centerLabel)
centerLabel.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
centerLabel.centerXAnchor.constraint(equalTo: view.safeAreaLayoutGuide.centerXAnchor),
centerLabel.centerYAnchor.constraint(equalTo: view.safeAreaLayoutGuide.centerYAnchor),
centerLabel.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
centerLabel.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor)
])
}
func setAttributes() {
centerLabel.textColor = .black
centerLabel.textAlignment = .center
centerLabel.numberOfLines = 0
centerLabel.text = "Test"
}
}
Result 타입으로 통신 메서드 만들기
1. 정의
extension ViewController {
private func getQuote(completion: @escaping (Result<Quote, Error>) -> Void) {
let url = URL(string: "https://api.quotable.io/random")
URLSession.shared.dataTask(with: url!) { data, response, error in
guard error == nil else {
print("error")
return
}
guard let response = response as? HTTPURLResponse, (200..<300).contains(response.statusCode) else {
print("response")
return
}
guard let data = data else {
return
}
do {
let quote = try JSONDecoder().decode(Quote.self, from: data)
//🍎 성공일 때
completion(.success(quote))
} catch {
//🍎 실패일 때
completion(.failure(error))
}
}.resume()
}
}
2. 사용
class ViewController: UIViewController {
let centerLabel = UILabel()
override func viewDidLoad() {
super.viewDidLoad()
setUI()
getQuote { [weak self] result in
switch result {
case .success(let quote):
DispatchQueue.main.async {
self?.centerLabel.text = "성공\n \(quote.content)"
}
case .failure(let error):
DispatchQueue.main.async {
self?.centerLabel.text = "실패\n \(error)"
}
}
}
}
}

Custom Error 만들기
1. ⭐️ 반드시 Error protocol을 채택해야 함
//Error protocol을 채택해야 함
enum NetworkError: Error {
case badUrl
case badResponse
case communicationError
case decodeFailed
case noData
// case는 얼마든지 늘리고 줄여도 됨
}
custom Error protocol을 채택해서 메서드 구현하기
private func getQuote(completion: @escaping (Result<Quote, NetworkError>) -> Void) {
let url = URL(string: "https://api.quotable.io/random")
URLSession.shared.dataTask(with: url!) { data, response, error in
guard error == nil else {
//🍎
completion(.failure(.communicationError))
return
}
guard let response = response as? HTTPURLResponse, (200..<300).contains(response.statusCode) else {
//🍎
completion(.failure(.badResponse))
return
}
guard let data = data else {
//🍎
completion(.failure(.noData))
return
}
do {
let quote = try JSONDecoder().decode(Quote.self, from: data)
//🍎
completion(.success(quote))
} catch {
print(error)
}
}.resume()
}
2. 메서드 사용하기 (위와 동일)
class ViewController: UIViewController {
let centerLabel = UILabel()
override func viewDidLoad() {
super.viewDidLoad()
setUI()
getQuote { [weak self] result in
switch result {
case .success(let quote):
DispatchQueue.main.async {
self?.centerLabel.text = "성공\n \(quote.content)"
}
case .failure(let error):
DispatchQueue.main.async {
self?.centerLabel.text = "실패\n \(error)"
}
}
}
}
}
custom Error를 LocalizedError와 사용하기
1. Error 확장
import Foundation
//Error protocol을 채택해야 함
enum NetworkError: Error {
case badUrl
case badResponse
case communicationError
case decodeFailed
case noData
// case는 얼마든지 늘리고 줄여도 됨
}
// localizedDescription를 잘 작성해두면 error를 잘 파악할 수 있음
extension NetworkError: LocalizedError {
var errorDescription: String? {
switch self {
case .badUrl:
return "badUrl 오류입니다."
case .badResponse:
return "badResponse 오류입니다."
case .communicationError:
return "communicationError 오류입니다."
case .decodeFailed:
return "decodeFailed 오류입니다."
case .noData:
return "noData 오류입니다."
}
}
}
2. 사용
class ViewController: UIViewController {
let centerLabel = UILabel()
override func viewDidLoad() {
super.viewDidLoad()
setUI()
getQuote { [weak self] result in
print(result)
switch result {
case .success(let quote):
DispatchQueue.main.async {
self?.centerLabel.text = "성공\n \(quote.content)"
}
case .failure(let error):
DispatchQueue.main.async {
//🍎
self?.centerLabel.text = "실패\n \(error.localizedDescription)"
}
}
}
}
}

Throws
do-catch를 언제 쓸 것인가? 메서드를 사용할 때 쓰고자 한다면!
이렇게 사용하면 메서드 구현부가 아닌 메서드 실행할 때 에러처리를 하게 됨
1. 메서드 구현
throws 함수는 try 키워드를 적어줘야 함
private func throwingGetQuote(completion: @escaping (Result<Data, NetworkError>) -> Void) {
let url = URL(string: "https://api.quotable.io/random")!
URLSession.shared.dataTask(with: url) { data, response, error in
guard error == nil else {
completion(.failure(.communicationError))
return
}
guard let response = response as? HTTPURLResponse, (200..<300).contains(response.statusCode) else {
completion(.failure(.badResponse))
return
}
guard let data = data else {
completion(.failure(.noData))
return
}
completion(.success(data))
}.resume()
}
private func decodedData(data: Data) throws -> Quote {
return try JSONDecoder().decode(Quote.self, from: data)
}
2. 사용할 때
class ViewController: UIViewController {
let centerLabel = UILabel()
override func viewDidLoad() {
super.viewDidLoad()
setUI()
throwingGetQuote { [weak self] result in
switch result {
case .success(let data):
do {
let quote = try self?.decodedData(data: data)
DispatchQueue.main.async {
self?.centerLabel.text = "성공\n \(quote?.content)"
}
} catch {
print("network error")
}
case .failure(let error):
DispatchQueue.main.async {
self?.centerLabel.text = "실패\n \(error.localizedDescription)"
}
}
}
}
}

Error를 switch문으로 처리도 가능
class ViewController: UIViewController {
let centerLabel = UILabel()
override func viewDidLoad() {
super.viewDidLoad()
setUI()
throwingGetQuote { [weak self] result in
switch result {
case .success(let data):
do {
let quote = try self?.decodedData(data: data)
DispatchQueue.main.async {
self?.centerLabel.text = "성공\n \(quote?.content)"
}
} catch {
print("network error")
}
case .failure(let error):
//🍎 error 분기처리
switch error {
case .badResponse:
print("badResponse error")
case .badUrl:
print("badUrl error")
case .communicationError:
print("communicationError error")
case .noData:
print("noData error")
case .decodeFailed:
print("decodeFailed error")
}
}
}
}
}
'순진이의 하루 > study정리' 카테고리의 다른 글
13. async/await_2022.09.19 (0) | 2022.09.19 |
---|---|
12. Collapsed TableView, InfiniteScrollView_2022.09.14 (0) | 2022.09.19 |
9. URLSession_2022.08.31 (0) | 2022.08.31 |
8. 고차함수, UIViewPropertyAnimator_2022.08.29 (0) | 2022.08.29 |
7. UserDefaults, Animation_2022.08.24 (0) | 2022.08.24 |
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크