24/7 Tech Support

I received an urgent email from a user today that had a slight problem with a registration code. I responded within a couple of hours (today is Saturday) saying that I tested the code and it works fine (I actually did test the code and saw that it worked) and said please try again and if you have problems, please send a screenshot so I can verify the code. The response I got back was “I am very disappointed with your response.” Wow, it is those kind of users that make me want to quit writing and selling software. I generally get back to users within a few hours, 7 days a week; yes, I work a lot and some people appreciate that. Some support tickets take a bit of going back and forth and I’ll work to solve problems as much as it takes. However, getting responses like this make me want to just pack it in.

I generally expect an answer within a few days to any email I sent. (I have, however, been waiting 2 months for a response from IRIS about returning my crappy scanner, but that’s another store and I should just send them a certified letter and demand my money back as the product was falsely represented.) On weekends, I don’t expect any response as normal companies don’t have people working on weekends.

Oh, and ReceiptWallet 2.0 resets the 3 week demo period, so even if I didn’t get back quickly, all users would still have time to use the app before the demo expired.

Uggh.

Background Apps and the iPhone SDK

Yesterday I wrote that I didn’t think background applications were a good idea on the iPhone and I’ve seen some other posts that support my position; anything that makes the phone less stable is bad. A good friend of mine pointed out why a background app would be good, but also reminded me of how this was handled on the Palm OS. Notifications were posted. So an application would register for a notification or set an alarm for a specific time and then would handle that. While I’m not saying the Palm OS was perfect (if you ever wrote Palm OS software, you remember that notifications and alarm callbacks had to reside in the first 16K (or was it 64K) of the application thereby causing you to use jumps to get stuff to work. If you don’t have a clue what I’m talking about, feel lucky.

The iPhone could do something similar (maybe it already does, but I don’t know and even if I did, I couldn’t say publicly until June). I’m sure that the iPhone SDK will mature as time goes on, but I hope that developers remember that the iPhone is a phone and music player first, and an application player second (or third or fourth). If anything takes away from its main purpose, it will hurt the platform.

When my code bites me on the you know what

I released ReceiptWallet 2.0 on Tuesday and the reception has been pretty good. Unfortunately, as with any major upgrade, there are bound to be issues. I’ve been handling the support issues on a case by case basis, and I’ve been scratching my head trying to figure out what could have caused the issues. This afternoon I received a phone call from my uncle who just upgraded and now his data was empty. The good thing about the upgrade is the chances of destroying the data are slim; ReceiptWallet, in most cases, can’t find it. Having visited my uncle back in November and knowing how his system was setup, it made getting him up and running much easier. Then, this evening, it dawned on me the problem, so I tested my theory. In ReceiptWallet and DocumentWallet, I had a preference that let users move the ReceiptWallet or DocumentWallet data folder as people wanted to put it in Documents or on another hard drive. So I moved my data in ReceiptWallet 1.5.2, upgraded to ReceiptWallet 2.0 and saw that ReceiptWallet didn’t find my data. Hmmm…at least I could reproduce it.

I started poking at my code and within a few minutes, saw this:

		[[NSUserDefaults standardUserDefaults] objectForKey:kOldDataLocation];

That’s the whole line. Anyone who knows Cocoa programming knows that this does nothing. The line was supposed to be:

		dataLocation = [[NSUserDefaults standardUserDefaults] objectForKey:kOldDataLocation];

I somehow left off the assignment to the variable.

OK, simple fix. However, this doesn’t really help the people that have already upgraded and our stuck. In addition, I’m not quite ready to put out a 2.0.1 version. So, I added a menu option that says “Open Prior Version Data” which does the magic to open the data file and actually executes the problem line of code from above.

So, I’ve posted the new version as a beta, put a Knowledge Base article about it and put a ReceiptWallet News item about it. I’m hoping that I can simply point people to the beta version and their problems will disappear.

I’ll probably sleep well tonight having found the answer to one of this week’s greatest mysteries.

Writing handheld applications using the iPhone SDK

In the past week since the iPhone SDK event, there has been a lot of discussion about the limitations of the iPhone SDK. I think that the “limitations” are coming from people and developers that have kind of missed the point. The main concern with a cell phone/handheld device is stability, at least that is my take on it. Way back in 1997 when I started working on the Qualcomm pDQ phone (the first Palm OS based smartphone), my main concern was that the phone could not crash as it was a consumer electronics device. (Imagine your TV crashing because you tried to watch an episode of Lost that had some magic encoding in it.) Maybe I was a little before my time, maybe not. The biggest problem with the Palm OS (up until just a few years ago) is that it didn’t have flash based storage, so if the battery died, you’d lose everything. So not only could the phone crash, but sometimes in order to reset the device you had to pull the battery causing you to lose all your data.

I’ve just started to watch the iPhone SDK videos and will start taking a look at the SDK in the near future (I’m kind of working on 3.5 half time projects which leaves virtually no time to think or write this blog :-)).

One Mac developer has posted a list of its feature requests for the iPhone SDK. These requests are coming for a Mac developer and NOT a handheld developer or average consumer. As someone that has written handheld applications for the last 13+ years, I know that desktop development is completely different from handheld development. While the tools may be the same and it may use the same language, there are tons of differences. The primary concerns with handheld apps are stability and ease of use with limited screen real estate and input mechanisms. I hope that Apple ignores most of the requests from developers to give root access on the iPhone, allow access to the entire filesystem, and the ability to run background apps, just to name a few. These items will (not can) cause instability in the phone and provide a poor user experience that will reflect poorly on Apple. Furthermore, one app touching the entire phone could cause other applications to have problems and then people would come running to me (kind of like they do on the desktop, but more so).

Maybe I’m just jaded, but I want a stable, well functioning iPhone with good applications. I don’t want a bunch of hackers or desktop developers writing crap for the iPhone. I guess we’ll just have to wait and see how the market shakes out.

(I double checked this post and all the information above comes from public sources; I highly respect the agreements I sign, either physically or virtually, and I hope that others do the same.)

Important lesson in using NSLocalizedString

In ReceiptWallet 2.0, I use an ellipses in a number of places for menu items, window titles, etc. I switched all my source files to UTF-8 and started using ellipses in the NSLocalizedString macros to make localization easier whenever I get to that point. Well, despite using UTF-8 for the file encoding, something went horribly wrong that I didn’t notice until today. The ellipses caused a bunch of my menu items to take on names of other things, like Scan Receipt became Combining Documents…. Huh, I thought. So after a bunch of research, I found the solution. 1) Replace … with \\U2026 and 2) In my script phase where I run genstrings to generate the Localizable.strings file, add a -u flag. While that seems like an easy fix, I almost went bonkers today as I’m nearing the ReceiptWallet 2.0 release and this would have been bad.

Package Based Documents

There have been a number of postings about having a Cocoa document based application where the documents are packages. None of the posts seemed to nail exactly what I wanted, so I managed to piece together a bunch of posts and came up with some sample code to demonstrate it. I used this as a basis for ReceiptWallet 2.0, but have made a bunch of changes since then. Feel free to use this code in any way you see fit, but I make no promises of how well it will work for anyone besides me.

Grab the source

PDFKit is borked

I love that Apple has lots of frameworks for me to use in my apps and gives me things for free such as PDF viewing and manipulation. This is with PDFKit. The problem with PDFKit is that it isn’t very tolerant of PDFs created from various other applications. I reported a bug with this back in the 10.4 era and it got fixed; I simply added a keyword to a PDF using Preview and it crashed (this is the same thing I do in ReceiptWallet). Now, I was pointed to another PDF that has the same behavior. The steps to reproduce this are quite simple:

  1. Download the IRS W-9 form
  2. Open it in Preview (on 10.5.2)
  3. Choose Tools->Inspector
  4. Click on the keywords tab
  5. Click the + button
  6. Add a keyword
  7. Do a Save As and give it a name
  8. Watch Preview crash
Exception Type:  EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x00000000dce481a4
Crashed Thread:  0

Thread 0 Crashed:
0   libSystem.B.dylib             	0x952773af szone_free + 2101
1   com.apple.CoreFoundation      	0x9155c826 _CFRelease + 342
2   ...ple.ApplicationServices.ATS	0x906240d4 FindNameAsCFString + 1432
3   ...ple.ApplicationServices.ATS	0x90623acc ATSFontGetPostScriptName + 76
4   libCGATS.A.dylib              	0x9364e8e5 get_name_with_name_code_nl + 250
5   libCGATS.A.dylib              	0x9364ea67 ats_name_handler_get_postscript_name + 23
6   libCGATS.A.dylib              	0x9364fd48 get_postscript_name + 49
7   com.apple.CoreGraphics        	0x924f0cd3 CGFontNameTableCreate + 322
8   com.apple.CoreGraphics        	0x924f0b73 CGFontGetPostScriptName + 29
9   libPDFRIP.A.dylib             	0x18bd81a9 PDFFontType1EmitDefinition + 57
10  libPDFRIP.A.dylib             	0x18bd6674 write_definition + 55
11  libPDFRIP.A.dylib             	0x18bd4c38 PDFFontEmitDefinitions + 22
12  libPDFRIP.A.dylib             	0x18bd6197 emitFontDefinition + 17
13  com.apple.CoreFoundation      	0x9155f1fc CFSetApplyFunction + 140
14  libPDFRIP.A.dylib             	0x18bd61db PDFFontSetEmitDefinitions + 60
15  libPDFRIP.A.dylib             	0x18bd2f8b PDFDocumentFinalize + 385
16  libPDFRIP.A.dylib             	0x18bd1c0e pdf_Finalize + 28
17  com.apple.CoreGraphics        	0x925567bf CGContextDelegateFinalize + 55
18  com.apple.CoreFoundation      	0x9155c786 _CFRelease + 182
19  com.apple.CoreGraphics        	0x925567ac CGContextDelegateFinalize + 36
20  com.apple.PDFKit              	0x902a418a -[PDFDocument(PDFDocumentInternal) writeToConsumer:withOptions:] + 1491

Filed as Radar (Apple’s Bug Reporter) bug # 5784122. I don’t even enough a way around this. I could try to re-write the PDF, but if the PDF has filled in information, it will become toast. Do I have to write my own PDF code to handle this? Apple has so many technologies that some of the most useful (at least to me) get neglected; there is so much focus on the glitzy stuff that the basics get ignored.

Caught cheating

No, I didn’t cheat in school, I cheated in failing to fix a ReceiptWallet feature. When I was working on ReceiptWallet to move it to document based, I didn’t fix the AppleScript support. When ReceiptWallet was a single window application, the scripting support was global; with document based, the scripting had to be specific to a library. As anyone that has written AppleScript support, it is a royal pain in the you know what. I was hoping that no one would notice this, but even before the end of the ReceiptWallet beta, I had someone send me email about it. Damn, I guess I had to fix it.

So, I spent the last 2 days fixing the AppleScript support so that people can bulk load receipts and documents in ReceiptWallet. I’m quite pleased with it, but it was much harder to implement than I’d expect.

Writing documentation

I have the daunting task of writing the documentation for ReceiptWallet. While I have some as well as some knowledge base articles, the docs need an overhaul. I wrote the previous version of the docs for Apple Help by hand. This time, I was going to look for a tool to do it. I found 3 options. HelpLogic, Simple Help Editor, and Mac Help Writer. The UI on the first two makes me want to barf. They say that they’re cross platform programs. For most programs, “cross platform” means “we have a crappy Mac UI in order to get it to work on Windows”. This isn’t true for all applications, but for many.

I tried to overlook the UI of these apps and the cost wasn’t an issue, but I couldn’t figure out how to use either program and HelpLogic kept saying that it couldn’t save my preferences and to check permissions. Not a good start. So I gave Mac Help Writer a try. It looked like it would work even if it did require me to use the format the author of the app wanted. I could live with that. However, there were 2 major flaws with the program. First is I couldn’t create ordered lists and second I couldn’t insert graphics. I went ahead and bought it and figured that I’d edit the files by hand after creating them.

Right before I went to bed and after I cranked out a bunch of help, I figured it out! I would use tokens and then search and replace later. So I’d encode < as %% and > as %%%; I’d search for the latter first and everything would work out.

To make things even easier, I created a shell script (with the help of Jerry Brady of Blue Circle Technologies) that automates the process after I use Mac Help Writer to generate the help.

#!/bin/bash
path_to_script=$(cd ${0%/*} && echo $PWD/${0##*/})
path_to_script_parent=`dirname "$path_to_script"`

cd $path_to_script_parent
cp -f Images/* ReceiptWallet\ Help/images/
cp -f Styles/* ReceiptWallet\ Help/styles/
cd ReceiptWallet\ Help/

WEBROOT="pages"
FILES=`find $WEBROOT -type f | grep html$`


for F in $FILES
do
    echo "    processing: $F"
    /usr/bin/perl -i -p -e "s/%%%/>/g" $F
    /usr/bin/perl -i -p -e "s/%%/
  • /
  • /g" $F done cd ../.. rm -rf Resources/English.lproj/ReceiptWallet\ Help mv Help/ReceiptWallet\ Help Resources/English.lproj/
  • This makes my markup look kind of funny, but it seems to work and I’m now more than half way through my help!

    Does beta mean anything anymore?

    I’m currently testing ReceiptWallet 2.0 beta and have been getting reports from people that say they’re using ReceiptWallet 2.0 (not saying beta) and are mad that they have problems. While I can understand being mad about having problems, but that’s why it is in beta so that people test it. I have several warnings indicating that the software is not finished and to backup data, but people seem to ignore those warnings. In my preferences, I have “Look for Beta Versions and Releases” as an option; I’m not sure people understand what Beta means, so I’ve changed it to “Look for Untested Versions and Releases”. Could that be clearer? When my website is redone, I’ll also make sure that any references to beta also indicate “untested”.

    I think that developers have diluted the term beta by just throwing stuff out there and getting people to try it; for instance, look on VersionTracker for items that are beta versions. They are just mixed in with everything else and the unsuspecting consumer, says “oh, a new version, let me get it.” without realizing that beta means “untested”. I don’t throw my beta versions on VersionTracker because I want people to make a conscious effort to get the versions.