How to use FTS in SQLite with Monotouch for iOS

2019-01-26 01:39发布

问题:

I'm looking to build an iOS app using Monotouch that has a rather large sqlite db full of text. I need to provide fast searching over this text.

My best solution right now is the FTS module (preferably version 4). I have read that the default instance of sqlite on iOS does not support FTS. If this is true what is the recommended way to build a custom instance of sqlite with Monotouch? Or can this be done at all?

I found this site describing how to accomplish this with xcode, but it is not clear how I would accomplish with Monotouch.
http://longweekendmobile.com/2010/06/16/sqlite-full-text-search-for-iphone-ipadyour-own-sqlite-for-iphone-and-ipad/

Any help is much appreciated!

回答1:

You would have to do the same thing, build your own libsqlite3.a, and mangle all the public exports so it doesn't conflict with the libsqlite loaded by the system, and then you would need to modify whatever library you want to bind to sqlite to [DllImport ("__Internal")] instead of libsqlite.



回答2:

As I mentioned in my comment above I got this working and since Stack Overflow has really helped me out I wanted to contribute a little to give back to the community.
Disclaimer
This is coming from a .NET developer who is a N00B when it comes to iOS/MacOS/XCode/Monotouch.
Although I tested this out on the iPad simulator I have yet to test it out on an actual device.
End disclaimer

This is a quick how-to compile your own version of SQLite and include it in your Monotouch project with the goal of supporting Full text search.

Step 1: Download the SQLite amalgamation file.

This includes all of SQLite in one file.
http://www.sqlite.org/download.html

Step 2: Compile the SQLite source in Xcode for iOS.

There is a good walkthrough on how to do this here:
http://pp.hillrippers.ch/blog/2009/08/08/Static+SQLite+Library+with+Unicode+Support+for+the+iPhone/

I followed steps 1-5, skipped #6 since we're not adding additional headers.

Instead of using the compile flags used in the walk through I used:
SQLITE_ENABLE_COLUMN_METADATA
SQLITE_ENABLE_FTS4

There may be others you want to add as well.
These compile flags are added in XCode, to the "Build" tab of the project under "Preprocessor Macros".

Once you've compiled this you should have "mylibrary.a".

Step 3: Include this file in your MonoDevelop project
Add mylibrary.a into MonoDevelop as any other file, right click it and make sure the build action is 'Nothing'.

In your project options select "iPhone Build". You need to add additional mtouch arguments. Add the following

-gcc_flags "-L${ProjectDir} -lmylibrary -force_load ${ProjectDir}/mylibrary.a"

Step 4: Build a c# wrapper
You could probably find a good wrapper to include at this point but I just quickly rolled my own.

For a good tutorial on writing an SQLite wrapper in C# check this page out:
http://www.switchonthecode.com/tutorials/csharp-tutorial-writing-a-dotnet-wrapper-for-sqlite

Because your library is a part of the project you don't need to reference the library by name but instead use the "__Internal" keyword. *NOTE THERE ARE TWO UNDERSCORES IN "__INTERNAL" * (Don't ask me how much time I wasted before I realized that)

Here's a sample of one of mine

[DllImport ("__Internal", EntryPoint="sqlite3_open")]  
static extern int sqlite3_open_v2(string filename, out IntPtr db);

There's obviously a lot more to putting together a wrapper, but there's lots of info out there on how to do that. One gotcha is to properly marshal the strings you get returned from SQLite. (see http://blog.gebhardtcomputing.com/2007/11/marshal-utf8-strings-in-net.html for more info on Marshaling)

This was intended to be a quick walkthrough on getting a native library compiled in into MonoDevelop/monotouch, and I hope it helps someone.