[Swift5] NSNumber의 Bool과 Int의 판정(Alam ofire)
배경.
API 통신에 Alamofire를 사용하는 경우
파라메터(body)를 [string:Any]로 변환해서 건네드려야 합니다.
그때
예컨대 아래의 예.
struct Todo: Codable {
let id: String
let title: String
let number: Int
}
let todo: Todo = Model(id: "ssss", title: "hogehoge", number: 8)
let data: Data = JSONEncoder().encode(todo)
let parameter: [String:Any] = try? JSONSerialization.jsonObject(with: data, options: .allowFragments)
print(parameter)
// jsonに変換
// ["id": "ssss", "title": "hogehoge", "number": 8]
모델에는 String 및 Int만 있으면 위 절차에서 변환할 수 있습니다.문제는 아래처럼 볼형에 들어갈 때.
struct Todo: Codable {
let id: String
let title: String
let number: Int
let isDone: Bool
}
let todo: Todo = Model(id: "ssss", title: "hogehoge", number: 8, isDone: true)
let data: Data = JSONEncoder().encode(todo)
let parameter: [String:Any] = try? JSONSerialization.jsonObject(with: data, options: .allowFragments)
print(parameter)
// jsonに変換
// ["id": "ssss", "title": "hogehoge", "number": 8, "isDone": 1]
// isDoneがfalseなら0,trueなら1に変換されてしまう
앞에서 말한 바와 같이 부울형은 인트형으로 전환되어 원래 값이 부울인지 인트인지 판별할 수 없는 문제에 부딪혔다.해결책
결론적으로 말하자면, 상술한 절차를 거친 후
CFBooleanGetTypeID
와 CFGetTypeID
를 취득하고 그 값을 비교함으로써 원래의 값이 Bool인지 Int인지 판정한다.코드는 아래와 같다.
func isBoolNumber(number: NSNumber) -> Bool {
let boolID = CFBooleanGetTypeID()
let numID = CFGetTypeID(number)
// 元の値がboolだとboolIDとnumIDが異なる値になる
return numID == boolID
}
이 성립의 이유는 Json Serialize가 변환된 후의 값에 차이가 있기 때문이다.위의 변환 후number 및 isDone 유형 및 값에 주목
number: NSNumber 8
isDone: NSNumber YES
원래 Bool 값이었다면,Time
NSNumber YES
휴가NSNumber NO
이렇게이쪽 차이를 이용하면 위와 같이 다양한 ID를 얻으면 값이 달라져요.
판정할 수 있다.
전역 코드
모델에 디렉터리라는 변수를 준비해서 변환할 복제자를 정의했습니다.
struct Todo: Codable {
let id: String
let title: String
let number: Int
let isDone: Bool
var dictionary: [String: Any]? {
guard let data = try? JSONEncoder().encode(self) else { return nil }
return (try? JSONSerialization.jsonObject(with: data, options: .allowFragments)).flatMap { data in
if let datas = data as? [String: Any] {
return convertNSNumberToBool(value: datas)
}
return data as? [String: Any]
}
}
// Boolの場合はBoolに変換を行う
func convertNSNumberToBool(value: [String: Any]) -> [String: Any] {
let array = value.mapValues { value -> Any in
// 値がNSNumberの場合は判定の関数を行う
if value is NSNumber {
if isBoolNumber(number: value as! NSNumber) {
return value as! Int == 0 ? false : true
}
// jsonの階層は2階層以上の場合に対応
} else if value is [String: Any] {
return convertNSNumberToBool(value: value as! [String: Any])
}
return value
}
return array
}
// NSNumberがboolかintか判定を行う
func isBoolNumber(number: NSNumber) -> Bool {
let boolID = CFBooleanGetTypeID()
let numID = CFGetTypeID(number)
return numID == boolID
}
}
위의 방법조사를 많이 했지만 이런 방법이 아니면 할 수 없었어요
더 똑똑한 방법이 있다면 꼭 알려주세요.
Reference
이 문제에 관하여([Swift5] NSNumber의 Bool과 Int의 판정(Alam ofire)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/t0_inoue/articles/2de0edd38f58ad텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)