I finally took some time to tidy up code and do some refactoring on Audiobook Binder. ABB was my first major Cocoa/Obj-C project so it was not pretty inside. Not pretty at all. One of the objectives was to split audiobook converter code from app delegate and move converter window to its own .xib file in order to be able to have multiple converters. Not hard but tedious process. And thanks to Vocabulist updating localized .xib files from base version was really easy.

So main feature of Audiobook Binder 2.0: you can have multiple audiobook windows and run multiple audiobook conversions in parallel. It is not available in AppStore yet for several reasons:

  • Developer’s part of AppStore is closed till Dec 28th
  • This release involved a lot of code-pushing and though I tested it fairly well I’d like to be able to fix any missed blunders ASAP. And with AppStore you just can’t do this

So once AppStore is open for business and assuming there are no major blockers I’ll push it for approval by Apple

Trying to set up LaunchAtLogin feature for CodeGofer app I ran into issue. Call to SMLoginItemSetEnabled generated this message in Console:
Attempt to enable file://localhost/Applications/CodeGofer.app/Contents/Library/LoginItems/CodeGoferHelper.app without sandbox from sandboxed app. After some experiments turned out that sandboxing wasn’t enabled for CodeGoferHelp.app target.

Googling for error message didn’t help so I’ll just leave it here along with solution for Google to pick up.

CodeGofer progress

November 5, 2013 — Leave a comment

Work on CodeGofer project progresses slowly but pieces are falling into their places and each day it looks more and more like usable product. Here are some screenshots:

CodeGofer - Search

CodeGofer - Code

CodeGofer - Preferences

Lately I’ve been working on my next project CodeGofer and it involved learning new things in OS X land. Two things I postponed for as long as I could were full text search and In-App purchases. Being prone to NIH syndrome I tried to come up with home made framework for the former but though better of it and did my online research, which yielded a Search Kit, really neat and simple way to do full text search for Cocoa apps. And the latter led to brief but intense struggle with Store Kit. Search Kit will get its own blog post but at the moment I’d like to document my experience with Store Kit and testing in-app purchases. There are quite a few tutorials about iOS in-app purchases but information about how to do it on Mac OS X is somewhat scarce. So here is my woes as of today:

Debug configuration wouldn’t do it

The first show stopper was inability to get products from sandbox environment. I did all by the book but this code

- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response {
    if ([response.invalidProductIdentifiers count] > 0)
        NSLog(@"Invalid product ids: %@", response.invalidProductIdentifiers);

    NSLog(@"Products: %@", response.products);
}

showed that all product ids I had submitted were invalid. I checked and double checked but no luck. Then I switched configuration for “Run” action (Alt+Click on “Run” button and modify “Run” action’s config) to “Release” and voila: response.products were no longer empty. I am not sure why Debug configuration does’t work, I’ll update post once this mystery is solved. And the strange thing: without Xcode Debug configuration works (see below)

Alas attempt to purchase item always ended up with Current receipt invalid or mismatched ds person id. message.

Would you like your receipt?

Some googling turned up the reason for that message: Store Kit checks receipt for IAP against Mac App Store receipt and since we run application from Xcode there is nothing of this kind. I believe that receipts are generated in two cases: when app is purchased from MAS or when app requests it from system notifying it by very specific exit status: 173. I failed to find the way to emulate MAS purchase but exit status turned out to be more fruitful. First of all for testing purposes we do not need full blown receipt checking code. We just need to know if it’s there. I added these lines to the very beginning of applicationDidFinishLaunching method of App Delegate:

    NSURL *url = [[NSBundle mainBundle] appStoreReceiptURL];
    
    if (![[NSFileManager defaultManager] fileExistsAtPath:[url path]])
        exit(173);

When you run application from Xcode its exit status is handled by IDE and what it does is it does nothing. So there are two options:

Do not use Xcode
Build you project using xcodebuild and run application using open. Something like:

xcodebuild -target CodeGofer -config Release && open ./build/Release/CodeGofer.app 

In this case exit code will be passed to the system and handled accordingly.

Generate receipt for Xcode build on demand
Try to run application and see it fail. Now find the bundle in ~/Library/Developer/Xcode/DerivedData (in my case it’s /Users/gonzo/Library/Developer/Xcode/DerivedData/CodeGofer-gobendvulmorviaazseuzbheeoht/Build/Products/Release/CodeGofer.app), run it once using open, e.g.:

open /Users/gonzo/Library/Developer/Xcode/DerivedData/CodeGofer-gobendvulmorviaazseuzbheeoht/Build/Products/Release/CodeGofer.app

It will generate receipt and it will be successfully picked up by application run from Xcode. Until you perform clean of course. At which point you’ll need to generate new receipt.

With all this bells and whistles I finally got my IAP working in sandboxed environment so now I can happily code further.

Reinventing XCS

September 22, 2013 — 1 Comment

More than two years ago I coded smallish tool for controlling Xcode from command line. It was ruby script talking to Xcode application via AppleScript. I developed it for Xcode3 so when everybody switched to Xcode4 some functionality stopped working because AppleScript support in Xcode was never official and nobody guaranteed compatibility between versions or even availability of AppleScript API.

I performed several half-hearted attempts to fix it, first by figuring out what’s left of AppleScript support in new Xcode, then trying to parse pbxproj file using ruby, and then writing parser in obj-c. Which was waste of time because it’s simple NSDictionary representation that can be parsed by NSDictionary’s dictionaryWithContentsOfFile call. I figured it out while working on my Xcode localization tool project that requires read-only access to the project file. But once started there was no reason not to try modifying the pbxproj file. As a result xcs-objc project was reborn as a xcs2 and started to get some meat around its bones. So far there is only “list” and “rm” subcommands. “rmdir” seems to be obvious for the next step and then I’ll start toying with adding new items to project.

Audiobook Binder 1.18

September 22, 2013 — 8 Comments

New version has been released. For AppStore build the main change is workaround for sandboxing bug that bit updating users. New users should not be affected by it. I also squeezed smallish change: new option to enable/disable file sorting.

Also some changes in non-AppStore build: abbinder has been included in GUI bundle. Add symlink and you’ll always have up to date version of command line utility: ln -s /Application/AudioBookBunder.app/Contents/MacOS/abbinder /usr/local/bin/abbinder. Thanks to Keenan Brock for suggestion

Text2Epub 1.3

September 19, 2013 — 5 Comments

Text2Epub 1.3 has been released and it’s no longer all about plain text any more. This version introduces support for rich-text formats: rtf, doc, docx. Application is now able to convert basic markup to epub form: text colors, font styles (bold, italic, etc), font sizes, text alignment.

Update, Sep 17: I’ve just submitted new version with this issue fixed, it’s in “Waiting for review” state now

I must apologize to Audiobook Binder users I did a sloppy job on releasing version 1.17. While fixing one bug I introduced another one. It does not affect new users only those who upgrade AppStore build from previous version. The bug manifests itself as “Can’t create output file” message immediately after pressing “Bind” button. The workaround is to change destination folder to anything but the current one (e.g. Music). It should fix the issue and after that you can change it back to previous location.

I’m working on a fix and will release it ASAP.

KnockOnD 1.3

September 9, 2013 — Leave a comment

And one more update: KnockOnD got some love too. Changes are:

  • Crash bug on iOS 5 with empty configuration
  • Fixed “inconsistent state” message after deleting a sequence
  • UI fixes for iPhone 5

Updates for several of my applications finally hit the AppStore, so here is short summary:


Audiobook Binder


As I mentioned before: fix for “Can’t create output file” bug, notification centre support, minor bug fixes.


Fb2Epub

  • Options for changing footnotes style: regular, with link back and iBooks(epub3) style.
  • Options for copying directory structure. Useful when you’re converting a bunch of books organized by author or series
  • Fixed crash on yet to be released OS X Mavericks


Text2Epub


Fixed the same crash bug with OS X 10.9 (Mavericks) as for Fb2Epub.