Accessing an SQLite Database in Swift
While you should probably use one of the many SQLite wrappers, if you wanted to know how to call the SQLite library yourself, you would:
Configure your Swift project to handle SQLite C calls. If using Xcode 9 or later, you can simply do:
import SQLite3
Create/open database.
let fileURL = try! FileManager.default
.url(for: .applicationSupportDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
.appendingPathComponent("test.sqlite")
// open database
var db: OpaquePointer?
guard sqlite3_open(fileURL.path, &db) == SQLITE_OK else {
print("error opening database")
sqlite3_close(db)
db = nil
return
}Note, I know it seems weird to close the database upon failure to open, but the
sqlite3_open
documentation makes it explicit that we must do so to avoid leaking memory:Whether or not an error occurs when it is opened, resources associated with the database connection handle should be released by passing it to
sqlite3_close()
when it is no longer required.Use
sqlite3_exec
to perform SQL (e.g. create table).if sqlite3_exec(db, "create table if not exists test (id integer primary key autoincrement, name text)", nil, nil, nil) != SQLITE_OK {
let errmsg = String(cString: sqlite3_errmsg(db)!)
print("error creating table: \(errmsg)")
}Use
sqlite3_prepare_v2
to prepare SQL with?
placeholder to which we'll bind value.var statement: OpaquePointer?
if sqlite3_prepare_v2(db, "insert into test (name) values (?)", -1, &statement, nil) != SQLITE_OK {
let errmsg = String(cString: sqlite3_errmsg(db)!)
print("error preparing insert: \(errmsg)")
}
if sqlite3_bind_text(statement, 1, "foo", -1, SQLITE_TRANSIENT) != SQLITE_OK {
let errmsg = String(cString: sqlite3_errmsg(db)!)
print("failure binding foo: \(errmsg)")
}
if sqlite3_step(statement) != SQLITE_DONE {
let errmsg = String(cString: sqlite3_errmsg(db)!)
print("failure inserting foo: \(errmsg)")
}Note, that uses the
SQLITE_TRANSIENT
constant which can be implemented as follows:internal let SQLITE_STATIC = unsafeBitCast(0, to: sqlite3_destructor_type.self)
internal let SQLITE_TRANSIENT = unsafeBitCast(-1, to: sqlite3_destructor_type.self)Reset SQL to insert another value. In this example, I'll insert a
NULL
value:if sqlite3_reset(statement) != SQLITE_OK {
let errmsg = String(cString: sqlite3_errmsg(db)!)
print("error resetting prepared statement: \(errmsg)")
}
if sqlite3_bind_null(statement, 1) != SQLITE_OK {
let errmsg = String(cString: sqlite3_errmsg(db)!)
print("failure binding null: \(errmsg)")
}
if sqlite3_step(statement) != SQLITE_DONE {
let errmsg = String(cString: sqlite3_errmsg(db)!)
print("failure inserting null: \(errmsg)")
}Finalize prepared statement to recover memory associated with that prepared statement:
if sqlite3_finalize(statement) != SQLITE_OK {
let errmsg = String(cString: sqlite3_errmsg(db)!)
print("error finalizing prepared statement: \(errmsg)")
}
statement = nilPrepare new statement for selecting values from table and loop through retrieving the values:
if sqlite3_prepare_v2(db, "select id, name from test", -1, &statement, nil) != SQLITE_OK {
let errmsg = String(cString: sqlite3_errmsg(db)!)
print("error preparing select: \(errmsg)")
}
while sqlite3_step(statement) == SQLITE_ROW {
let id = sqlite3_column_int64(statement, 0)
print("id = \(id); ", terminator: "")
if let cString = sqlite3_column_text(statement, 1) {
let name = String(cString: cString)
print("name = \(name)")
} else {
print("name not found")
}
}
if sqlite3_finalize(statement) != SQLITE_OK {
let errmsg = String(cString: sqlite3_errmsg(db)!)
print("error finalizing prepared statement: \(errmsg)")
}
statement = nilClose database:
if sqlite3_close(db) != SQLITE_OK {
print("error closing database")
}
db = nil
For Swift 2 and older versions of Xcode, see previous revisions of this answer.
C++: How to improve performance of custom class that will be copied often?
Ideally you'd have all the information necessary to setup Bar
at the time Foo
is constructed. The best solution would be something like:
class Foo {
Bar b;
public:
Foo() : b() { ... };
Foo(const Foo& f) : b(f.a, f.b) { ... };
}
Read more about constructor initialization lists (which has no direct equivalent in Java.)
Using a pointer pb = new Bar(arg1, arg2)
will actually most likely deteriorate your performance since heap allocation (which could involve, among other things, locking) can easily become more expensive than assigning a non-default constructed Bar
to a default-constructed Bar
(depending, of course, by how complex your Bar::operator=
is.)
Default constructor in C
You can create initializer functions that take a pointer to a structure. This was common practice.
Also functions that create a struct and initialize it (like a factory) - so there is never a time where the struct is "uninitialized" in the "client" code. Of course - that assumes people follow the convention and use the "constructor"/factory...
horrible pseudo code with NO error checking on malloc or free
somestruct* somestruct_factory(/* per haps some initializer agrs? */)
{
malloc some stuff
fill in some stuff
return pointer to malloced stuff
}
void somestruct_destructor(somestruct*)
{
do cleanup stuff and also free pointer
free(somestruct);
}
Someone will probably come along and explain how some early C++ preprocessors/compilers worked to do this all in C.
Type trait to identify types that can be read/written in binary form
Given a 1st parameter of s
, the read
method:
Extracts characters and stores them into successive locations of the character array whose first element is pointed to by
s
So your real question is: If I have initialized an object by writing a string of bytes to it's address, is it valid?
This is the concept of Value Representation. And the value representation of Trivially Copyable types is such that:
Copying the bytes occupied by the object in the storage is sufficient to produce another object with the same value
Thus you want to ensure that your object is Trivially Copyable this isn't per say a standard concept but it can be succinctly defined as:
- Every copy constructor is Trivial or deleted
- Every move constructor is Trivial or deleted
- Every copy assignment operator is Trivial or deleted
- Every move assignment operator is Trivial or deleted
- At least one copy constructor, move constructor, copy assignment operator, or move assignment operator is non-deleted
- Trivial non-deleted destructor
The spirit of the assertion that at least one Trivial initializer exists for the object boils down to these requirements of a Trivially Copyable type, it's non-static members, and any of it's base classes:
- It's given Trivial Initializer is, or behaves as, the corresponding default intializer
- It has no virtual methods
- It has no members of a volatile-qualified type
As far as the requirement of a Trivial destructor:
- The destructor is not user-provided (meaning, it is either implicitly declared, or explicitly defined as defaulted on its first declaration)
- The destructor is not virtual (that is, the base class destructor is not virtual)
- All direct base classes have trivial destructors
- All non-static data members of class type (or array of class type) have trivial destructors
Having fully defined what it means to be a Trivially Copyable type, it is impossible for a "type trait or concept" to determine whether all of these requirements are met in all cases, for example: A type that defines a Trivial Initializer with a signature that matches the default initializer may or may not be Trivially Copyable contingent on the code which initializes the type in that initializers body; For such a type, the only way to determine if it's Trivially Copyable is human inspection of the initializer. If however you are willing to tighten the requirements to what is detectable, is_trivially_copyable
will guarantee that your type is Trivially Copyable.
Related Topics
Querying in Firebase by Child of Child
Which Value Types in Swift Supports Copy-On-Write
Disable Bounce Scrolling for Wkwebview in MACos
Swiftui Pass Two Child Views to View
Code Highlighting in Latex for Swift
How to Use Spritekit Archives with Skspritenode Subclasses
Expression Pattern of Type 'String' Cannot Match Values of Type 'Nsstoryboardsegue.Identifier
Type of Optionals Cannot Be Inferred Correctly in Swift 2.2
How to Catch Error When Setting Launchpath in Nstask
How to Customize the Font and Appearance of a Uialertcontroller in the New Xcode W/ iOS8
Unit Testing Wknavigationdelegate Functions
Testing If a Decimal Is a Whole Number in Swift
Nscollectionviewitem Never Instantiate
Swiftui: Localizedstringkey with Indices
Swift Realm: After Writing Transaction Reference Set to Nil
Swift - Encode and Decode a Dictionary [String:Any] into Plist