SOLVED Qt 5.1 ios How to Bundle and use SQLite database in application



  • I want to store data in SQLite database and I want to write the database file to ios device.
    For Android creating the file in
    @
    QStandardPaths::writableLocation( QStandardPaths::HomeLocation )
    @

    is a working solution but for ios I cannot create the file there. The returned path for the ios device is: "/private/var/mobile/Applications/XXXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX" .

    How can I get a path that i can write to?



  • This functionality is not available in Qt5.1. In any case, the folder you would be looking for is the "Documents" folder, and not the "Home" location. As the "Documents" folder is not part of the application bundle, you will need to do some startup code in your app which checks for the database and copies it to or creates it in the "Documents" folder if it's not already there. To find the path for the documents folder, you'll need to use the following code:

    NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject]);

    To convert the NSString to a QString, you'll need something like:

    static inline QString qt_mac_NSStringToQString(const NSString *nsstr)
    {
    CFStringRef str = reinterpret_cast<const CFStringRef>(nsstr);
    if (!str) return QString();

    CFIndex length = CFStringGetLength(str);
    if (length == 0) return QString();
    
    QString string(length, Qt::Uninitialized);
    CFStringGetCharacters(str, CFRangeMake(0, length), reinterpret_cast<UniChar *>(const_cast<QChar *>(string.unicode())));
    
    return string;
    

    }



  • Do you know if the functionality will be included in Qt 5.2 ?



  • Hi!

    I am using Qt 5.2.0.

    Is it possible to use QtSql with SQLITE on iOS?

    I tried it and my app runs great on the desktop. But it seems, as if the deployment to iOS Simulator does not deploy any sqldriver does it?

    Should it work by copying the sqldrivers folder from
    /Users/jamil/Qt5.2.0_ios/5.2.0/ios/plugins to the .app directory being installed on the device/ simulator and adding
    @app.addLibraryPath(app.applicationDirPath() + "/sqldrivers");@

    Cheers
    jraichouni


  • Lifetime Qt Champion

    Hi,

    Yes it is, but Qt for iOS is a static build so you need to tell Qt to use the static plugin



  • Ah, great!

    But how can I do that?

    Currently my .pro file contains

    QT += sql

    The class calling
    @
    QSqlDatabase::addDatabase("QSQLITE");
    @

    contains @#include <QtSql>@

    How do I tell Qt to use the static sqldriver?
    And where should what be deployed to?

    Cheers
    jraichouni


  • Lifetime Qt Champion



  • Hi, thanks for that, but it's what
    I've tried without success.
    Xcode did not compile that.
    I am going to prepare a small but
    complete example project to list it here
    tomorrow.

    Cheers
    jraichouni



  • Here is an example:
    @

    sqlite_on_ios.pro

    TEMPLATE = app
    QT += qml quick
    QTPLUGIN += qsqlite
    QMAKE_INFO_PLIST += Info.plist
    SOURCES += main.cpp
    RESOURCES += main.qrc
    cache()
    @
    @
    <!-- main.qrc -->
    <RCC><qresource prefix="/"> <file>main.qml</file> </qresource></RCC>
    @
    @
    // main.qml
    import QtQuick 2.0
    Rectangle { id: page; width: 640; height: 1136; color: "red" }
    @
    @
    // main.cpp
    #include <QGuiApplication>
    #include <QQuickView>
    #include <QString>
    #if defined(Q_OS_IOS)
    #include <QtPlugin>
    Q_IMPORT_PLUGIN(qsqlite)
    #include <QSqlDatabase>
    #endif
    int main(int argc, char *argv[]) {
    QGuiApplication *app = new QGuiApplication(argc, argv);
    // QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE", "xa_db");
    QQuickView *view = new QQuickView;
    view->setSource(QUrl("qrc:///main.qml"));
    view->setResizeMode(QQuickView::SizeRootObjectToView);
    view->show();
    return app->exec();
    }
    @
    @
    <!-- Info.plist -->
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
    <key>CFBundleName</key>
    <string>sqlite_on_ios</string>
    <key>CFBundleExecutable</key>
    <string>sqlite_on_ios</string>
    <key>CFBundleIconFile</key>
    <string>sqlite_on_ios</string>
    <key>CFBundlePackageType</key>
    <string>APPL</string>
    <key>CFBundleShortVersionString</key>
    <string>1.0.0</string>
    <key>CFBundleVersion</key>
    <string>1.0.0</string>
    <key>CFBundleIdentifier</key>
    <string>www.sqlite_on_ios.com</string>
    </dict>
    </plist>
    @

    Xcode build results in the following error:
    @
    main.cpp:8:14: fatal error: 'QSqlDatabase' file not found
    #include <QSqlDatabase>
    ^
    1 error generated.
    @


    The minitool builds/ runs in iOS Simulator if I comment lines 5-9 of main.cpp.

    What is needed in addition to use sqlite on iOS?

    Would be really great to get a hint! :-)

    Viele Grüße aktuell aus Berlin ;-)
    jraichouni


  • Lifetime Qt Champion

    You are missing

    @QT += sql@

    in your pro file



  • Alright, missed that and now the same error appears as I got it in my original project yesterday.

    Xcode says:
    @
    Undefined symbols for architecture i386:
    "qt_static_plugin_qsqlite()", referenced from:
    StaticqsqlitePluginInstance::StaticqsqlitePluginInstance() in main.o
    ld: symbol(s) not found for architecture i386
    clang: error: linker command failed with exit code 1 (use -v to see invocation)
    @
    Does anything from my Qt (iOS) Installation (e.g. from plugin sqldrivers) need to be copied/ deployed into the build for iOS Simulator?

    Or do I need to specify the -spec argument within the call of qmake because of that architecture error above?



  • @ QStringList paths = QStandardPaths::standardLocations(QStandardPaths::DataLocation);
    QString dbFile = paths.first().append("/datastore.db");

    QSqlDatabase *database = new QSqlDatabase(QSqlDatabase::addDatabase("QSQLITE"));
    database->setDatabaseName( dbFile );@
    

    Add this to your .pro:
    QT += sql
    QTPLUGIN += qsqlite

    As explained here (inclusing your cross post):
    http://qt-project.org/forums/viewthread/36600/#156960
    ... (by SGaist) using a pointer is not necessary.



  • Tried it, and Xcode fails with below error. Did you try to build it for iOS Simulator?
    @
    Undefined symbols for architecture i386:
    "qt_static_plugin_qsqlite()", referenced from:
    StaticqsqlitePluginInstance::StaticqsqlitePluginInstance() in main.o
    ld: symbol(s) not found for architecture i386
    clang: error: linker command failed with exit code 1 (use -v to see invocation)
    @
    Used as you proposed:
    @

    sqlite_on_ios.pro

    TEMPLATE = app
    QT += qml quick sql
    QTPLUGIN += qsqlite
    QMAKE_INFO_PLIST += Info.plist
    SOURCES += main.cpp
    RESOURCES += main.qrc
    cache()
    @

    My main.cpp:
    @
    // main.cpp
    #include <QGuiApplication>
    #include <QQuickView>
    #include <QString>
    #include <QtPlugin>

    Q_IMPORT_PLUGIN(qsqlite)
    #include <QSqlDatabase>

    int main(int argc, char *argv[]) {
    QGuiApplication *app = new QGuiApplication(argc, argv);
    // QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE", "xa_db");
    QQuickView *view = new QQuickView;
    view->setSource(QUrl("qrc:///main.qml"));
    view->setResizeMode(QQuickView::SizeRootObjectToView);
    view->show();
    return app->exec();
    }
    @



  • I am using a recent version of Qt 5.2.0-dev snapshot (in the title you are writing you are using 5.1).
    For iOS development you should stick to 5.2.0 instead of < 5.2.0.

    edit: yes, I did - works for Mac, iOS Sim and on my iPhone.



  • I am using "Qt 5.2.0 (official release)":http://download.qt-project.org/official_releases/qt/5.2/5.2.0/qt-mac-opensource-5.2.0-ios-x86_64-offline.dmg

    I did not create the thread.

    A very short but complete mini project .pro file & main.cpp would help.

    I mean an example, which runs at your computer. I would launch qmake only to get the .xcodeproject directory to test that.



  • [quote author="jraichouni" date="1389032658"]I am using "Qt 5.2.0 (official release)":http://download.qt-project.org/official_releases/qt/5.2/5.2.0/qt-mac-opensource-5.2.0-ios-x86_64-offline.dmg

    I did not create the thread.[/quote]

    Oh, sorry.

    drop this from your file:
    Q_IMPORT_PLUGIN(qsqlite)

    edit for your edit:

    [quote author="jraichouni" date="1389032658"]
    A very short but complete mini project .pro file & main.cpp would help.

    I mean an example, which runs at your computer. I would launch qmake only to get the .xcodeproject directory to test that.[/quote]

    I already did - the code above works as your main() content.



  • It runs!
    I am a bit confused, as the "Plug & paint example":http://qt-project.org/doc/qt-4.8/tools-plugandpaint.html uses that macro.

    But many thanks for your reply and help!!

    Really interesting would be to be able to use the SQLite Function "load_extension" which is omitted in Standard Qt build.



  • [quote author="jraichouni" date="1389033119"]It runs!
    I am a bit confused, as the "Plug & paint example":http://qt-project.org/doc/qt-4.8/tools-plugandpaint.html uses that macro.

    But many thanks for your reply and help!![/quote]

    You're welcome.



  • "A very short but complete mini project .pro file & main.cpp would help.
    I mean an example, which runs at your computer. I would launch qmake only to get the .xcodeproject directory to test that."

    I just start to use QT 5.2 (with iOS even more) a mini exemple project with all files would be great



  • Hi!

    Take the example in the current thread.

    The important things to consider are:

    .pro file:
    @
    QT += sql
    ios:QTPLUGIN += qsqlite

    deploy the database file via something like:

    databases.files = ../../src/data/xp-apt.sqlite
    ios: databases.path = Documents
    macx: databases.path = Contents/Resources
    QMAKE_BUNDLE_DATA += databases

    note, that the path databases.files is relative to the cwd, in which

    the process qmake runs

    @

    The class implementing the initialisation/ access to the db needs to do the following for instance:
    @
    #include <QtSql>
    (...)

    QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE", "some_name");
    QSqlDatabase db = QSqlDatabase::database("some_name", false);
    QString dbFilePath = "(...)";
    db.setDatabaseName(dbFilePath);
    db.open();
    QSqlQuery *q = new QSqlQuery(db);
    (...)
    @

    Hope that helps!



  • Hi!

    I'm follow this example.
    But It doesn't work for me.

    In Desktop, iOS simulator mode is fine.
    But it doesn't work with my iPad.

    Thanks you if you can help me.



  • I currently work on my work environment and do also have no iPad (iPhone only) but it shall work as described in above posts.



  • Hi, Jamil

    Thanks for your feedback.

    Then I tried with my iPhone5s. And It just work, but my iPadRetina don't.
    Post QT creator error log above:

    This plugin does not support propagateSizeHints()
    &
    Failed to make complete framebuffer object 8cdd

    Thanks again for your help.



  • [Solved]
    Update to QT5.2.1, iPad just work fine.

    Thanks you.



  • Hi,
    Please help. I build my app for iPad, and using database Sqlite.
    Can you explain the QString dbFilePath = "(...)"; why it is "(...)"
    Thanks and regards

    [quote author="Jamil Raichouni" date="1389206294"]Hi!

    Take the example in the current thread.

    The important things to consider are:

    .pro file:
    @
    QT += sql
    ios:QTPLUGIN += qsqlite

    deploy the database file via something like:

    databases.files = ../../src/data/xp-apt.sqlite
    ios: databases.path = Documents
    macx: databases.path = Contents/Resources
    QMAKE_BUNDLE_DATA += databases

    note, that the path databases.files is relative to the cwd, in which

    the process qmake runs

    @

    The class implementing the initialisation/ access to the db needs to do the following for instance:
    @
    #include <QtSql>
    (...)

    QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE", "some_name");
    QSqlDatabase db = QSqlDatabase::database("some_name", false);
    QString dbFilePath = "(...)";
    db.setDatabaseName(dbFilePath);
    db.open();
    QSqlQuery *q = new QSqlQuery(db);
    (...)
    @

    Hope that helps![/quote]


  • Lifetime Qt Champion

    It's a placeholder text that you must replace with the path to your database file



  • Thanks SGaist,
    It works now.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.