Hello Swift community, I'm looking for advice.
I want to write Swift code that adapts to the various versions of SQLite found in various iOS/macOS versions, as well as it adapts to custom SQLite builds (latest release + SQLCipher).
By "adapt", I mean:
- At compile-time: expose or not Swift APIs depending on the underlying SQLite version.
- At compile-time: branch depending on the underlying SQLite version.
- At run-time: branch depending on the underlying SQLite version.
Precisely speaking, I already know how to do this. In the schematic sample code below, we have four functions f1, f2, f3, and f4.
- f1 is always available for custom builds, but only available on some iOS/macOS version
- f2 is always available, but branches depending on the iOS/macOS version
- f3 is available for custom builds with specific SQLite compilation option, and some iOS/macOS versions
- f4 is always available, but branches depending on the SQLite version
#if CUSTOM_SQLITE_BUILD // Set in OTHER_SWIFT_FLAGS
// Using custom SQLite build
func f1() { 🐵 }
func f2() { 🐶 }
#if SQLITE_ENABLE_FTS5 // Set in OTHER_SWIFT_FLAGS
func f3() { 🦊 }
#endif
#else
// Using SQLite shipped with operating-system
@available(...)
func f1() { 🐵 }
func f2() {
if #available(...) { 🐶 }
else { 🦁 }
}
@available(...)
func f3() { 🦊 }
#endif
func f4() {
if sqlite3_libversion_number() < ... { 🐷 }
else { 🐰 }
}
So it is totally possible, and it indeed works today. But there are problems:
- f1 and f2 are declared twice.
- codes chunks
,
and
are duplicated.
- f2 and f4 are pursuing the same goal. f2 uses compile-time checks, and f4 uses run-time checks. Compile-time checks are supposed to be better, but they create code duplication. So run-time checks are sometimes preferred - for no clear reason.
With C/Objective-C, which have access to C #define
, all of those problems are solved:
// C code
#if SQLITE_VERSION_NUMBER > ...
void f1() { 🐵 }
#endif
void f2() {
#if SQLITE_VERSION_NUMBER > ...
🐶
#else
🦁
#endif
}
#if SQLITE_ENABLE_FTS5
void f3() { 🦊 }
#endif
void f4() {
#if SQLITE_VERSION_NUMBER > ...
🐷
#else
🐰
#endif
}
But I'm not here to complain about the lack of C #define
.
I come to you today because until now, I could deal with code duplication (worst examples so far one, two).
But recently a user came with a reasonable request that would duplicate whole files (all files starting with FTS5 in this directory).
Now this becomes serious. This message has three goals:
- Listen to good advice
- Raise the awareness that consuming C APIs is not always easy.
- Maybe get in touch with an available core-team member so that we could discuss in details an eventual solution.
Thanks for reading!