[Swift] 정체불명의 Dictionary 업데이트 런타임에러
이번 글은 개인적으로 빡쳐서 쓰는 한탄글이다 -_-;
종종 Swift는 아직 준비가 덜되었다고 떠벌리고 다녔는데 이번에는 정체불명의 오류로 인해 다시금 준비가 덜 되었다고 이야기를 해야 할 것 같다. 이번 글은 Swift의 Dictionary(사전형)의 아이템을 업데이트 할 때 발생하는 EXC_BAD_ACCESS에 관한 이야기이다.
컴파일러 최적화 오류일 가능성도 있기 때문에 몇 가지 환경 설명이 필요하다.
아래와 같은 식의 코드가 있다.
우선 private 로 선언된 전역변수인 _sharedInstance는 싱글턴 객체를 저장해 두기 위한 녀석이다. 그리고 class var로 선언된 sharedInstance 프로퍼티는 이 싱글턴 변수를 리턴하기 위한 녀석이다. 따라서 이 둘은 싱글턴 패턴을 위한 것인데 이것이 과연 문제에 영향을 끼치는지는 파악되지 않은 상태이다.
문제의 코드는 doSomeWork 메소드이다. 여기서는 내부 프로퍼티로 존재하는 self.dict에 값을 넣는 역활을 한다. 그런데 이 메소드가 없는 키(key)를 만들 때는 문제가 없다가 이미 존재하는 키의 데이터를 바꾸려고 하면 EXC_BAD_ACCESS 오류가 발생했다. 즉 아래와 같은 식의 코드가 실행되면 죽었다는 말이다.
그런데 이 문제는 나만 겪은건 아니었나 보다. 관련된 stackoverflow.com의 스레드를 두 건 찾았다.
끙끙거리며 오랜 시간 삽질을 하다 결국 다른 방법으로 시도해 봤다. 바로 Dictionary 대신 NSMutableDictionary를 사용해 보는 것.
코드를 아래와 같은 식으로 고쳤다.
...
개인적으론 위 stackoverflow의 댓글들 처럼 컴파일러 버그 혹은 파운데이션 버그로 추측된다. 문제가 생길 아무런 이유가 없으니까.
하아.......... 삽질로 허비한 내 수 시간을 돌려줘~~~!!
[관련글] 스위프트(Swift) 가이드
[관련글] Swift - 컬렉션 타입(Collection Types)
[관련글] [Swift] 좀 더 단순한 싱글턴 패턴(Singleton Pattern)
종종 Swift는 아직 준비가 덜되었다고 떠벌리고 다녔는데 이번에는 정체불명의 오류로 인해 다시금 준비가 덜 되었다고 이야기를 해야 할 것 같다. 이번 글은 Swift의 Dictionary(사전형)의 아이템을 업데이트 할 때 발생하는 EXC_BAD_ACCESS에 관한 이야기이다.
컴파일러 최적화 오류일 가능성도 있기 때문에 몇 가지 환경 설명이 필요하다.
- 사용하는 Xcode 는 버전 6.1.1이다.
- 프로젝트 코드는 Objective-C 코드와 Swift코드가 섞여있다.
아래와 같은 식의 코드가 있다.
private SomeClass _sharedInstance = SomeClass()
class SomeClass {
private var dict = [String:String]()
class var sharedInstance: SomeClass {
return _sharedInstance
}
...
func doSomeWork(name: String, work: String) {
...
self.dict[name] = work
...
}
}
이 코드 만으론 용도가 좀 불분명 하겠지만 그냥 그러려니 하자. 실제로 문제가 생긴 코드와 구조가 거의 동일하다.우선 private 로 선언된 전역변수인 _sharedInstance는 싱글턴 객체를 저장해 두기 위한 녀석이다. 그리고 class var로 선언된 sharedInstance 프로퍼티는 이 싱글턴 변수를 리턴하기 위한 녀석이다. 따라서 이 둘은 싱글턴 패턴을 위한 것인데 이것이 과연 문제에 영향을 끼치는지는 파악되지 않은 상태이다.
문제의 코드는 doSomeWork 메소드이다. 여기서는 내부 프로퍼티로 존재하는 self.dict에 값을 넣는 역활을 한다. 그런데 이 메소드가 없는 키(key)를 만들 때는 문제가 없다가 이미 존재하는 키의 데이터를 바꾸려고 하면 EXC_BAD_ACCESS 오류가 발생했다. 즉 아래와 같은 식의 코드가 실행되면 죽었다는 말이다.
SomeClass.sharedInstance.doSomeWork("some name", work: "foobar")
...
SomeClass.sharedInstance.doSomeWork("some name", work: "fooooobaaaaaar")
만약 dict를 var가 아닌 let으로 선언했다면 이미 빌드 단계에서 에러가 발생했을 것이니 관련이 없다. 문제는 왜 값을 업데이트 할 때만 이런 문제가 생기느냐는 점이다. (참고로 updateValue 같은 메소드로 호출해도 동일한 결과였다)그런데 이 문제는 나만 겪은건 아니었나 보다. 관련된 stackoverflow.com의 스레드를 두 건 찾았다.
- http://stackoverflow.com/questions/26809986/exc-bad-access-on-ios-8-1-with-dictionary
- http://stackoverflow.com/questions/26787070/exc-bad-access-when-updating-swift-dictionary-after-using-it-for-evaluate-nsexpr
끙끙거리며 오랜 시간 삽질을 하다 결국 다른 방법으로 시도해 봤다. 바로 Dictionary 대신 NSMutableDictionary를 사용해 보는 것.
코드를 아래와 같은 식으로 고쳤다.
private SomeClass _sharedInstance = SomeClass()
class SomeClass {
private let dict = NSMutableDictionary()
class var sharedInstance: SomeClass {
return _sharedInstance
}
...
func doSomeWork(name: String, work: String) {
...
let d = self.dict as [String:String]
d[name] = work
...
}
}
이 코드로 테스트 해 보니 아무런 문제가 없었다....
개인적으론 위 stackoverflow의 댓글들 처럼 컴파일러 버그 혹은 파운데이션 버그로 추측된다. 문제가 생길 아무런 이유가 없으니까.
하아.......... 삽질로 허비한 내 수 시간을 돌려줘~~~!!
[관련글] 스위프트(Swift) 가이드
[관련글] Swift - 컬렉션 타입(Collection Types)
[관련글] [Swift] 좀 더 단순한 싱글턴 패턴(Singleton Pattern)
댓글