XML vs Binary vs SQLite for CoreData

When I started ReceiptWallet almost a year ago, I chose to use the XML format for my CoreData stores. This was mainly because I was unsure of CoreData and if I messed something up, I could look at the file in a text editor and change it. Except for the first few weeks developing, I’ve only touched the data file once for a customer where CoreData improperly encoded an entity and made the XML invalid.

Last week I decided to try the Binary format (I put code in awhile ago to try Binary, XML, or SQLite). Wow, the startup time dropped as CoreData no longer had to parse the XML. Next I tried SQLite and again, it appeared to be a bit faster. So, I’ve decided to make SQLite the default database format for ReceiptWallet and DocumentWallet (it can be changed with a plist change). The only downside to SQLite vs XML and Binary is that an SQLite file can’t be opened by two users at once, so I added a preference that allows the user to share the database (everyone except the primary user has to view it as read only) which changes the database format to Binary if it was SQLite.

So, I’m crossing my fingers that I don’t run into any problems with SQLite; lots of programs use it, so I should be OK. I did have a bug where I used an NSPredicate with “MATCHES” in it where I should have used “LIKE” which failed with the SQLite store. I’m not sure why that worked in the other database formats, but it did.

SetSignature Plugin for Mail

One of the items that Apple has never solved adequately for me is having multiple email addresses in one account with an associated signature for each one. If I had one account for each email address, things would work fine, but I have a large number of email addresses in one account. So, a few months back, I coded up a plugin for Mail that does this automatically. Unfortunately, it stopped working with Mail 3.0 on Leopard, so for the last week I’ve felt like I’ve been typing with one arm behind my back is this plugin is vital to me. I had some time yesterday to fix it for Mail 3.0 and have decided to put it out there as a free product; I don’t want to put out something that relies on unsupported calls and charge for it.

Feel free to use this in anyway you like; use at your own risk and if you have problems with Mail, remove the plugin and try again.

Installation instructions:

  1. Quit Mail
  2. From terminal, type:
    defaults write com.apple.mail EnableBundles 1
    defaults write com.apple.mail BundleCompatibilityVersion 3
    
  3. Download the plugin
  4. Uncompress the plugin and place SetSignature.mailbundle in ~/Library/Mail/Bundles (create the folder if it it isn’t there
  5. Launch Mail
  6. Name your signatures according to your email address, i.e. johndoe@nowheresite.com

Now when you reply to a message, it attempts to set the signature correctly. In addition, when you change the From address, it will attempt to match the signature with that address.

If you have any questions or problems, please post a comment. Since this is free, please don’t bug me too much about it. It works for me and that’s all I’ll guaranteee.

Eating my words about OCR

I’ve said in the past that I thought OCR was pretty ridiculous for receipts as it isn’t 100% accurate and receipts have so many wacky formats. Well, after a lot of work and evaluation, I have managed to integrate the Tesseract OCR engine into ReceiptWallet. It is an open source engine that has OK results for the price. (I did investigate some commercial engines; there are 2 that are on the Mac, and the costs were outrageous and currently one doesn’t even work on PowerPC machines.) As Google continues to work on the engine, I’ll be integrating the new versions into ReceiptWallet.

So, how did I manage to get things to work and get OK results? How about I just say magic? :-). Turns out the hardest part is attempting to recognize merchant names; I cheated on this and simply recognize merchants that the user has already used. This works quite well as I find that I keep going to the same merchants, so while it won’t recognize a merchant the first time you visit it, it has half a chance on subsequent visits.

I’ve been using my ScanSnap for testing and it produces very clear images that the OCR engine seems to like. My DocketPORT, however, has had mixed results. I think I need to change the contrast/brightness settings for better results. I’ll leave this up to beta testers to try out.

My goal is to push out a beta this weekend and see what happens. There is no way that this will be 100% accurate, but it might help a little and then I get to say that it has OCR!

Tired of crappy HP Scanner software

Just about everyday, I get crash reports from customers using HP scanners. The latest one I got, the customer was quite angry at me because DocumentWallet kept crashing. He finally sent the crash log and look at what it contains:

Thread 0 Crashed:
0   HP All-in-One Scan DS          	0x058f1240 0x57a4000 + 1364544
1   HP All-in-One Scan DS          	0x057b84fc BroadcastMessage__12LBroadcasterFlPv + 108
2   HP All-in-One Scan DS          	0x057bc604 BroadcastValueMessage__8LControlFv + 52
3   HP All-in-One Scan DS          	0x057e8388 HotSpotResult__11LPushButtonFs + 24
4   HP All-in-One Scan DS          	0x057bcbc8 ClickSelf__8LControlFRC15SMouseDownEvent + 184
5   HP All-in-One Scan DS          	0x057c2d6c Click__5LPaneFR15SMouseDownEvent + 140
6   HP All-in-One Scan DS          	0x057c96ec Click__5LViewFR15SMouseDownEvent + 76
7   HP All-in-One Scan DS          	0x057c96ec Click__5LViewFR15SMouseDownEvent + 76
8   HP All-in-One Scan DS          	0x057bdc38 ClickInContent__13LGrafPortViewFRC11EventRecord + 232
9   HP All-in-One Scan DS          	0x05874bec DoMouseDown__15CHPGrafPortViewFR11EventRecord + 236
10  HP All-in-One Scan DS          	0x0584b4e0 ScanWindowEventHandler__FP25OpaqueEventHandlerCallRefP14OpaqueEventRefPv + 304

Yes, folks, that means that HP’s software crashed DocumentWallet. It’s hard to convince user’s that my app isn’t causing the problem, but that’s reality. Vendors make crappy Mac scanner software and should be ashamed. They never expect people to use the TWAIN drivers because they suck so much and apparently never get tested.

HP, are you listening? Please fix your TWAIN drivers so that they don’t crash app’s that make scanner calls using proper TWAIN interfaces.

Exceptions and error handling

One of the things users hate to see are bugs in programs, so there are many techniques for attempting to catch them before a user sees them. One that is routinely used is exception handling. However, some developers like to use exception handling instead of preventing the issue or gracefully handling it. For example, I was working on code to present errors (in a worst case scenario) to users and trapped the error handling. As I did this, I kept noticing strange exceptions being thrown when my app started. Turns out that Apple uses exceptions (which are benign) in Core Data for its parsing of XML. Personally I don’t think this is a great way of handling things, but who am I to judge?

On the same topic, I had a rash of users complain that they lost data in my apps. I was very perplexed as I’d never seen this. I took a look at the code where I save out the data and noticed that I had put the entire save routine along with some other routines in an exception block with the save being at the end. This meant that if there was a problem with the first chunk of code, the data would never get saved. While I still have no idea what would cause the first chunk of code to fail, I pulled the save out of the exception handling and have yet to receive a problem report (knock on wood).

So the moral of the story is to carefully watch how exceptions are used and don’t go overboard with exception handling.

Opened my own store

My software sales have been doing well in the past 12 months which meant that my rate for eSellerate went up (the initial rate is a teaser rate). I could handle the initial rate even though it was a bit steep for the pieces I use, but the new rate was a 50% increase and that really hurt. So on Sunday, I started figuring out how to put up my own store. I looked at a few eCommerce solutions and settled on Zen Cart. I then setup a merchant account with PayPal as it was easy, had decent rates, and I never see the credit card numbers. Today I finally got the pieces together to integrate my registration codes into my store. To make people feel safe, I bought an SSL certificate (a wildcard one). I really didn’t need one as I don’t see credit card numbers, but I think it was worth the investment. There is still more work to be done to the store, but I think it is good enough for now. So without further ado, I present my web store.

Failing the first test to become one of my customers

Just when I thought that ReceiptWallet and DocumentWallet were the easiest to use applications I’ve ever created, I had a user contact me saying that he couldn’t install the software. The installation couldn’t be easier. You mount the disc image and look at the picture:

Picture 1.png

Just drag the icon to the applications folder, open the applications folder and double click ReceiptWallet. Should I have a video to show people how to do this? Unfortunately for this customer, he had trouble with that step. I’m very scared about the questions this user will ask in the future if he failed the first test.

Scanner drivers suck

I’ve probably written this before, but most scanner drivers for the Mac are garbage. This includes drivers from the major vendors such as HP, EPSON, and Canon. I’ve been pleased with the drivers from Sysscan for my DocketPORT and the Fujitsu ones are OK. I keep seeing crash reports with my products that clearly point to the scanner drivers. One that came in today looks like:

Thread 0 Crashed:
0   <<00000000>> 	0xffff926c __bigcopy + 300 (cpu_capabilities.h:194)
1   <<00000000>> 	0xffff9188 __bigcopy + 72 (cpu_capabilities.h:194)
2   com.hp.HPScanPro               	0x0379fb54 TwainEvents::SendEvent(TW_IDENTITY*, unsigned long, unsigned short, unsigned short, char*, unsigned short*) + 176 (TwainEvents.cpp:126)
3   com.hp.HPScanPro               	0x0379e320 DS_Entry + 792 (SampleDS.cpp:156)
4   org.twain.dsm                  	0x97f9a7e4 EntryDS(TW_IDENTITY*, TW_IDENTITY*, unsigned long, unsigned short, unsigned short, char*) + 180
5   org.twain.dsm                  	0x97f998b8 DSM_Entry + 456
6   ...gtenterprises.receiptwallet 	0x00014724 -[Scanner aquireNativeXfer:] + 356

What does this mean? It means that ReceiptWallet sent a TWAIN command and TWAIN passed it to the HP Software. HP’s software crashed likely while copying some memory. The thing that gets me about this crash is the crash shows the file name where the crash happened, “SampleDS.cpp”. HP didn’t even bother to rename the Apple sample code. While this may seem like a minor thing, if they overlooked such a minor thing, what else did they overlook?

I had a customer tell me yesterday that he was relieved to see my comments about the HP drivers on my FAQ because he thought he was the only one that had issues with them.

Then I’ve seen EPSON drivers where they incorrectly implemented part of the TWAIN driver; there are 2 choices for scanning, Memory Based and Native Transfer. If you use Native Transfer with some EPSON scanners, you get a yellow background. This is reproducible outside of my application, so I know it isn’t my problem. So I had to implement code for Memory Based transfers which was a pain.

Why, oh why, can’t scanner vendors focus less on they’re “pretty” interfaces (I say that factitiously as the interfaces look like crap) and more on functionality? On the consumer level scanners, how many people play with all the controls? Most don’t, so the driver should just have a scan button, maybe a preview and ability to crop, but anything more than that is overkill and prone to making things more complex.

Think first, code later

Several weeks ago, I was working on reports for ReceiptWallet and thought I had it all done in one weekend. The following Monday I realized I missed a part, handling sub items. I poked at it a few times and got nowhere. I then thought about the problem for 3 days and figured it out (all without coding). I told my wife that it would take me 1 hour to finish it. So the following Saturday, I got up, coded for 1 hour (exactly) and said that I was done. I went to test it and it didn’t work. Damn. I had breakfast, thought a little more about the problem, came back, added one line of code and then everything worked.

While it is obvious to think first, I’m not sure a lot of developers do that to solve complex problems. For me, these types of problems are all consuming and I must solve them before I can move on. Luckily no one complex problem seems all that difficult to me; I may not want to code it, but that’s another story. Not wanting to code something has more to do with tediousness than complexity.

Long story short, think first.

Bulk Email Program in a flash

I decided to put my ReceiptWallet program on MacZOT! to give it some extra marketing and see how things go. While (obviously) I won’t make as much as if I sold it directly, I’m expanding my customer base. As part of this, I had to implement some new systems in order to handle the orders as MacZOT! gives me a CSV file of orders that I download, insert the serial numbers, re-upload, and then have to send out the orders. I have a MySQL database and php frontend that I use for my normal orders and that works quite well. So I had to figure out the MySQL syntax (I’m still learning it) to import the CSV file into my database as a first step. That wasn’t too difficult, but required a bunch of trial and error. The next part was, “how am I going to send out the registration codes?”. The normal answer would be to write a script to do this. For some reason, I really hate scripting because I’m not familiar with the syntax (AppleScript, perl, php, etc.), so it takes a lot of time to get a working script. So, I decided to write my own “bulk email” program. No, this is not a spamming program. It’s a program that takes the CSV file and a message and customizes each message with info from the CSV file. So, using the Message Framework built into OS X, I was able to whip up the program in about an hour. I even made it so that the fields can be customized and the program can be re-used for when I send out update information or the like. I really should learn some of the scripting languages, but sometimes the quick and dirty way is the way to go.