본문 바로가기

Swift

SQLite 데이터 값이 제대로 들어가지 않을 때 unsafeBitCast 사용하기

반응형

포인터에 대한 개념이 부족하여 해당함수에 대한 완벽한 이해가 잘 되지 않지만 참고하고 나중을 위해 정리한 글이기 때문에 사실과 다르거나 제가 오해하는 부분이 있을 수도 있으니 참고해주시기 바랍니다.

설명

sqlite 사용하면서 데이터 추가할 때 테이블의 칼럼이 3개 이상일 때에는 마지막 칼럼값으로 값들이 들어가거나 의도하지 않는 값들이 들어가는 것을 확인하였습니다. 그리고 unsafeBitCast 함수를 사용해서 해결할 수 있었습니다.

문제되는 코드

guard prepare(with: sql) else { throw SQLError.prepare }
guard bindText(with: name, at: 1) else { throw SQLError.bind }
guard bindText(with: birth, at: 2) else { throw SQLError.bind }
guard bindText(with: age, at: 3) else { throw SQLError.bind }
guard bindText(with: description, at: 4) else { throw SQLError.bind }
guard step() == SQLITE_DONE else { throw SQLError.step }

private func bindText(with text: String, at index: Int32) -> Bool {
    return sqlite3_bind_text(stmt, index, text, -1, nil) == SQLITE_OK ? true : false
}

// 입력값 : 코코/2016.2.10/3/활발함
// 실제 저장되는 값 : 활발함/활발함/활발함/활발함

추가 및 변경 코드

let SQLITE_TRANSIENT = unsafeBitCast(-1, to: sqlite3_destructor_type.self)

private func bindText(with text: String, at index: Int32) -> Bool {
    return sqlite3_bind_text(stmt, index, text, -1, SQLITE_TRANSIENT) == SQLITE_OK ? true : false
}

// 입력값 : 코코/2016.2.10/3/활발함
// 실제 저장되는 값 : 코코/2016.2.10/3/활발함

공부

결론은 unsafeBitCast 함수로 포인터와 메모리를 관리하는 것으로 생각됩니다. unsafeBitCast 함수는 공식 사이트에서 사용할 때 주의를 하라는 경고메세지가 있습니다. SQLITE_TRANSIENT 말고 SQLITE_STATIC 도 많이 비교되며 사용됩니다.

let SQLITE_STATIC = unsafeBitCast(0, to: sqlite3_destructor_type.self)
let SQLITE_TRANSIENT = unsafeBitCast(-1, to: sqlite3_destructor_type.self)

SQLITE_STATIC, SQLITE_TRANSIENT 차이

SQLITE_STATIC

  • 변경되지 않음
  • 포인터 일정

SQLITE_TRANSIENT

  • 변경될 가능성 있음
  • 변수를 복사함
  • 복사하는 것 때문에 속도가 STATIC 보다 느림

차이에 대한 설명은 SQLite 참고

참고

Swift 4 + SQLite when inserting - Stack Overflow [SQLite] SQLITE_STATIC, SQLITE_TRANSIENT sqlite binding시 마지막 파라미터 차이(SQLITE_STATIC, SQLITE_TRANSIENT) - 일상에서 멍때리기 C 라이브러리를 호출하는 방법 · Out of Bedlam

반응형