Programming/Swift(iOS)
Swift 오류 처리 - 2
홍열
2021. 4. 6. 09:51
728x90
만약 데이터를 더하다가 오류가 났을때는 이미 추가된 데이터는 어떻게 해야될까요?
1, 이전 데이터로 돌린다.
2. 오류 이전까지만 추가한다.
개발자 혹은 기획이 어떻게 되냐에 다르겠지만, 대부분은 1번을 선택 할 것입니다.
오류 가능성이 있는 연산이 수행되었을 때,
오류가 발생하게 되면, 오류 발생 이전의 객체 상태로 오류 발생 이후의 상태는 동일해야 한다. => 예외 안정성
아래 코드는 append를 하다가 예외가 발생합니다. 과연 어떤 결과가 나올까요?
enum LogError:Error {
case invalidValue
}
struct Log {
var values:[String] = [String]()
mutating func append(messages:[String]) throws {
for message in messages {
let trimmed = message.trimmingCharacters(in: .whitespacesAndNewlines)
if trimmed.isEmpty {
throw LogError.invalidValue
}
values.append(message)
}
}
}
var log = Log()
do {
try log.append(messages: ["Hello World", " ", "show me the money"])
} catch {
print(error)
}
print(log)
결과
invalidValue
Log(values: ["Hello World"])
오류 나기 전까지만 더 해져있습니다.
1. 임시 값을 이용하는 방법 , 최종 연산이 된 후에 값이 변경되게 해야됩니다. (복사본 이용)
mutating func append(messages:[String]) throws {
var temp = values
for message in messages {
let trimmed = message.trimmingCharacters(in: .whitespacesAndNewlines)
if trimmed.isEmpty {
throw LogError.invalidValue
}
temp.append(message)
}
values = temp
}
2. defer block을 이용하는 방법
- 예외가 발생했을 때, 기존 Data를 defer block에서 지워버리는 방법입니다.
func writeToFiles(data:[URL:String]) throws {
var completed = [URL]()
//defer block에서는 defer밖으로 Error를 던질 수 없다.
//try! - 예외가 발생 했을 경우 프로그램 강제 종료
defer {
if completed.count != data.count {
//예외가 발생하면 이전 data를 모두 지우자
print("예외가 발생했습니다. - \(completed)")
for url in completed {
// 1) try! removeItem을 해보면서 예외가 발생하면 프로그램 강제 종료
//try! FileManager.default.removeItem(at: url)
// 2) removeItem에 대한 예외처리
do {
try FileManager.default.removeItem(at: url)
} catch {
print("복구할 수 없는 오류 발생")
}
}
}
}
for (url, contents) in data {
try contents.write(to: url, atomically: true, encoding: .utf8)
completed.append(url)
}
}
do {
try writeToFiles(data: [URL(fileURLWithPath: "/Users/hy/Desktop/a.txt"):"hello world"])
try writeToFiles(data: [URL(fileURLWithPath: "~/b.txt"):"hello world"])
try writeToFiles(data: [URL(fileURLWithPath: "/Users/hy/Desktop/c.txt"):"hello world"])
} catch {
print(error)
}
3. 불변 객체를 사용하는 방법
- 불변 객체를 사용해서 조건 검사후 새로운 객체를 만들면 됩니다.
enum UserError : Error {
case invalidAge
}
struct User {
let name: String
let age: Int
func child(childAge: Int) throws -> User {
if age <= childAge {
throw UserError.invalidAge
}
return User(name: "JR.\(name)" , age: childAge)
}
}
let user = User(name: "Tom", age: 42)
print(user)
do {
let jr = try user.child(childAge: 50)
print(jr)
} catch {
print(error)
}
print(user)