Posts Tagged ‘development’

MAS Preparation, Part 2

January 27th, 2012

Property List (Info.plist) changes

In the last installment of Preparing for Mac App Store Submission, I discussed the project modifications that are necessary (or recommended) for converting an existing Mac OS X project to one suitable for MAS submission.

This second part describes the changes to the information property list for your application that you should make for successful submission and to eschew rejections for simple issues.  As before, comments about any other issues or different experiences are certainly welcome.

Open the application information property list, usually named ‘Info.plist‘, in your project and follow these steps…

1. Update the bundle version format

First, update the format of the ‘Bundle version’ entry (CFBundleVersion) to contain exactly 3 period-separated integers representing the version number (e.g., “1.01.1“).  It cannot contain alphabetic characters (and although some documentation suggests that it may contain more or fewer integers, we did not take that chance).

For non-MAS applications, the format of this field was not enforced and, in fact, the default ‘About’ box encouraged the use of this field as a standard version description (alphanumeric string) by directly displaying it underneath the application name.  We used a format like, “1.01 (January 2012)”, which is more useful and aesthetically pleasing, but this was cause for rejection.

2. Add an application category

If you do not have one already, you will need to add an ‘Application Category’ entry (LSApplicationCategoryType).  The easiest way to set this value (in Xcode 4) is to select the ‘Summary’ tab for your target and select the appropriate setting in the ‘Application Category’ box.  In the case of Pretty Good Solitaire, we chose ‘Games – Card Games’ (public.app-category.card-games).

Note that Xcode 3 did not recognize this key, so it was necessary to explicitly add it, along with the appropriate category value, as found in the Information Property List Key Reference; fortunately, this is no longer necessary.

3. Set the minimum system version

Next, set the ‘Minimum system version’ entry (LSMinimumSystemVersion) to “10.6.6″, or higher if appropriate.

The Mac App Store does not work on versions of Mac OS X prior to 10.6.6 anyway, and leaving this at a lower setting (even if your downloadable versions support Leopard, Tiger, or even an earlier OS) may be cause for a rejection.

4. Review the supported document types

Finally, review the supported ‘Document types’ entry (CFBundleDocumentTypes), if any.  Remove any document types that will not be supported in your store version.

In our case, we supported a document type for saved games, which is still useful, but also a document type for automatic installation of extra card sets (which can be downloaded), or in the case of Pretty Good MahJongg, types for both extra tile sets and tile matching layouts.  Since downloading or installing any improvement to your application (outside of the Mac App Store) is verboten, we needed to remove this support.

Note that this initially passed muster with our first product, but it was cause for a rejection later on a different product using essentially identical functionality.  There is clearly some subjectivity to the application reviews, so a more thorough (or nitpicky) reviewer may find something previously allowed.  When a rejection can set your release schedule back a couple of weeks or more, it is not worth the risk.

Conclusion

With just these few changes to your information property list, your project should have the necessary application information for submission.  In the next installment, Part 3: Data and Resource guidelines, I will describe the issues you may encounter with your application data.

MAS Preparation, Part 1

January 25th, 2012

Project modifications

In Preparing for Mac App Store Submission, the first set of changes you should make are to the project itself.

This installment describes the project modifications that need to be made to an existing Mac OS X game project.  The general assumptions are that the existing project is working and properly tested, and that, ultimately, you will want to maintain a single set of source code with conditional compilation to differentiate the store version from other builds.  Note that these are the steps that we took for Pretty Good Solitaire Mac Edition; your project may require some adjustments to these steps.  (Comments where any significant change is necessary would be very appreciated.)

So, without further ado…

0. Create a duplicate store project

Before making any other changes, create a duplicate copy of the entire project folder and name the copy appropriately.  In our case, the original folder was ‘Pretty Good Solitaire’ (which builds full and trial versions of the game) and we created a separate ‘pgsse’ (Pretty Good Solitaire [Mac/]Store Edition) folder for MAS modifications.

The version of your project that you will submit to the Mac App Store is a separate SKU (Shelf Keeping Unit), a build that uses slightly different code and configuration and which is distributed via a different channel.  While it is possible to have the store target within the main project, certain features (e.g., Power PC support, Mac OS X 10.5 support, downloadable data) are not supported in MAS, so it is easier to separate them (at first, anyway).  In any event, doing so at the start gives you a safe playground for making changes without messing up your working project.

1. Update the project version number

As just noted, the store build is a separate version and, thus, should have a different version number.  In our case, we decided that odd minor versions (e.g., “1.01″) would represent the store editions, while even minor versions (e.g., “1.00″) represented the direct downloadable editions.

2. Rename the primary build target

In the new project (of course), rename the primary build target to something appropriate.  In our case, we renamed the full version target to ‘Pretty Good Solitaire store’, which is now the store version.  You could also delete any redundant or obsolete targets remaining in the project.  For example, we deleted the trial version target, as it is built in the original project and the MAS version cannot have any vestiges of a trial version.

Note that this step is not strictly required, but it is a good idea to differentiate between targets, so it is always immediately obvious which project is active, and also to minimize any excess baggage, which reduces the possibility of mistakes.

3. Build with a current Xcode version

Make sure that you build the project with a current version of Xcode.  Submissions to the Mac App Store now require Xcode 4 and, as of this writing, the latest version is Xcode 4.2.1.

If you have an older version of Xcode, this would be a good time to upgrade, and although it will not be mentioned explicitly, you should build the project regularly, ideally after every change, to make sure that the build is not broken and behaves as expected.

4. Define a preprocessor variable

To allow for conditional compilation of certain source code, it is a good idea to define a preprocessor variableAPPSTORE, for any build targets intended for MAS.  In the ‘Build Settings’ for the target (or the whole project, if you prefer), find the setting for ‘Preprocessor Macros’ and add “APPSTORE” to each configuration.  Note that it is common to have different variables for ‘Release’ and ‘Debug’ configurations, so be careful to define APPSTORE for each one without accidentally removing or altering any existing definitions.

Of course, there is no requirement that the preprocessor variable be named “APPSTORE”, but beware that simply using “STORE” results in a naming conflict in the latest Mac OS X SDK.

5. Add necessary frameworks/libraries

In order to test the validity of app receipts, you will need to add the IOKit and Security frameworks and the crypto library.  From the ‘Build Phases’ of the primary target, open the ‘Link Binary With Libraries’ section and, by clicking on the ‘+’ symbol, add ‘IOKit.framework‘, ‘Security.framework‘ and ‘libcrypto.dylib‘.

Note that Xcode 4 adds these frameworks/libraries at the top level of your project; you will probably want to drag them into the ‘External Framework and Libraries’ folder with the other frameworks.

6. Configure debugging symbols

Despite submitting a release version to MAS, Apple requires debugging information to be included with a submission.  To accede to this requirement, you must set ‘Generate Debug Symbols’ to “Yes” and also set ‘Debug Information Format’ to “DWARF with dSYM File” (at least for the ‘Release’ configuration) in the ‘Build Settings’ of the target.

In our original project, we had all debug information disabled and/or stripped from the release builds, but one of our early issues was the lack of the dSYM file with debugging information for Apple.

7. Set correct build architecture

Finally, set ‘Architectures’ to an Intel (only) setting; for our project, that is “32-bit Intel”.

Even if your code and original project supports both PPC and Intel via a “Universal” application, the presence of a PPC build in your submission will result in rejection.  (We found that out the hard/lengthy way.)  At least now there are settings for this; in Xcode 3, you had to use “i386″, which was not even listed as a choice.

Conclusion

At this point, you should have a new project with a store target and all of the build settings configured appropriately.  In the next installment, Part 2: Property List (Info.plist) changes, we will discuss the necessary adjustments and additions to the information property list for your project.

Preparing for Mac App Store Submission

January 23rd, 2012

Making a Mac OS X game project suitable for MAS

If you currently have a Mac product and have not already done so, you may be considering submission to the Mac App Store (MAS).

In the upcoming series of posts, I will be detailing the process that we went through to get Pretty Good Solitaire Mac Edition, and some of our other game products, successfully submitted to MAS.  There were a number of rejections along the way, as the App Store Review Guidelines [note: requires Mac developer agreement], while extensive, are not comprehensive (nor are they 100% consistent, as we had some products accepted and others rejected with identical behaviors).

Over multiple submissions, and fewer rejections, we developed a submission checklist which I will detail roughly (some items are specific to our games) in these upcoming posts:

[Editor: I will link to each section as it is published.]

We have had product in the Mac App Store since launch day, more than a year ago.  If you already have a game that runs on Mac OS X, it makes sense to make the several modifications to get it into MAS, another channel to find customers.  However, in our experience, it is not a viable substitute for direct downloadable sales.  The channel is not (yet) the primary ‘go to’ location for Mac software, although the availability of Lion (Mac OS X 10.7) only on MAS should shift more customers.  Additionally, there is the same downward pressure on pricing (towards free) seen on the iOS App Store, sales are lackluster, and (of course) you are giving 30% directly to Apple.

I would certainly not recommend developing a project solely for the Mac App Store, nor eliminating a direct downloadable sales channel in favor of MAS, but with an existing project it may be worth the fairly limited extra effort it takes to be there, too.

Objective-C: @property gotcha #1

October 26th, 2011

Sometimes “best” practices can bite you.

In Apple iOS documentation, they strongly recommend the use of declared properties to automatically generate access methods to class variables.  In header files, you would have something like this:

@interface MyClass
{
    IBOutlet UIView* view;
}

@property (nonatomic, retain) IBOutlet UIView* view;

@end

 

Technically, this generates access methods named ‘view’ and ‘setView’, but in practice one generally accesses the class variable with the dot notation (i.e., ‘self.view’) .  The implementation of this class (minus any explicit methods) would be:

@implementation MyClass

@synthesize view;

@end

 

Accessing the variable with dot notation calls the access methods (as does calling them explicitly, obviously), but simply using ‘view’ (without the ‘self’ reference) accesses the variable directly, omitting any other functionality associated with the accessors, such as (in the above example) retaining the new view.  This is generally a poor practice except in initialization and deallocation routines, where it is preferred.

So, in order to assure that one does not accidentally skip the accessors, the recommended best practice is to use the ability of @synthesize to generate accessors that access a slightly different variable name.  In other words, instead of ‘view’ and ‘setView’ referencing the ‘view’ variable, they can be instead made to access ‘view_’:

@synthesize view = view_;

 

This is, in theory, a good idea because one can only access the variable directly with the explicit addition of an underscore (in this case), and simply referencing ‘view’ instead of ‘self.view’ should produce a compiler error.  (Note that we use a trailing underscore because leading underscores already have a specific meaning in our coding guidelines.)

Problem: If you modify the class implementation as noted above to put this into practice, you introduce a bigger problem into your code.  It turns out that @synthesize actually creates a class variable if none of the specified name exists, but it does not generate a warning or error if the one of the ostensible name does exist.  In other words, the above line would create a new ‘view_’ class variable, and create accessor methods, despite the fact that ‘view’ already exists.  The ‘view’ and ‘setView’ methods modify ‘view_’, so ‘self.view’ does the same, but failing to ‘self’ reference, rather than generating the intended error, actually modifies the orphaned ‘view’ variable.  Instead of having an extra compiler check, you instead have two very similar variables in the same class and any error becomes even harder to diagnose.

If the @property/@synthesize combination essentially replaces normal variable declarations, it obviates the whole issue of these declarations.  This seems rather silly/weird, since declaring [class] variables is a staple of C[++], and the method of doing this in Objective-C is one of the first lessons taught.  Nevertheless…

Solution: To make this idea an actual best practice, at least for simple classes, omit the entire parenthesized section of the class declaration and just declare all variables via @property/@synthesize statements.  You would end up with something like the following:

@interface MyClass
@property (nonatomic, retain) IBOutlet UIView* view;
@end
@implementation MyClass
@synthesize view = view_;

- (id)init
{
    self = [super init];
    if ( self )
    {
        view_ = nil;
    }
    return self;
}

- (void)dealloc
{
    [view_ release];
    [super dealloc];
}

@end

 

All (or most) other references to the class variable would be via dot notation, ‘self.view’, which would (of course) modify the ‘view_’ variable via accessors, as desired.

Happy coding!

Ten Little Images (or so), Part 2

October 21st, 2011

Making sense of launch image requirements for iOS universal applications.

When developing a “universal” application for iOS, an app that will run on all (current) iOS devices, one of the first things you have to consider are the initial branding graphics for your game. These include the launch images for each device (and orientation), in addition to the application icons.

The first part of this article dealt with application icons for a universal iOS app.  This part concerns the launch images, which are static full-screen graphics displayed by iOS itself while the app is loaded and initializes itself, before it has any opportunity to show other graphics.

On an iPad, your application could start in any of four different orientations, two vertical (portrait) and two horizontal (landscape), so you will want one portrait (iPad) launch image and one landscape launch image.  (Technically, you can specify a different launch image for each of the four orientations, but it seldom, if ever, makes a difference beyond portrait or landscape.)  On an iPhone or iPod touch, an application only launches in a portrait orientation, with the home button at the bottom, but these smaller devices may (or may not) have a Retina display, so you need to provide both a normal portrait launch image and a high resolution version.

The purpose of launch images is to provide immediate visual feedback to the user when an application icon is tapped.  Apple’s iOS Human Interface Guidelines document, which is very good in many respects, recommends that the launch image be identical to the first screen of the application, or even simpler, omitting information that is not guaranteed static.  For a game, however, ignore this advice; the launch image is a defacto splash screen, so rather than being simple and unobtrusive, launch images for a game application should be eye-catching.  (We actually do create a “first screen” that replicates the launch image, but can smoothly add information such as version number and build/release date.)

Again, the assumptions here are that you are creating a “universal” application, supporting iOS 3.2 (the minimum version for iPad), and want to be sure to have your branding artwork shown in the best light on all three types of devices. If you are supporting only iPad (no small screens or Retina displays) or only iOS 4+ (no backwards compatibility), then there are fewer conflicts and caveats, but this article should still be helpful.

Launch Image Artwork Specifications

All launch images (and icons) must be in PNG format (24-bit), with no transparency.  The naming conventions for launch images, specifying which graphics to display on each device and supported orientation, are more restrictive than for icons.  In fact, the default launch image base name is (unimaginatively) “Default”.  For somewhat more descriptive naming, we use the project name (“DemolishPairs” herein) as the base name, though the modifiers are mostly fixed (and somewhat ugly).

For a complete set of launch images, we have the following (4) launch image files:

  1. DemolishPairs-Portrait.png [768x1004] – This is the launch image for portrait orientations on the iPad.
  2. DemolishPairs-Landscape.png [1024x748] – This is the launch image for landscape orientations on the iPad.
  3. DemolishPairs~iphone.png [320x480] – This is the (portrait) launch image for the older iPhone and iPod touch.
  4. DemolishPairs@2x~iphone.png [640x960] – This is the (portrait) launch image for newer iPhone and iPod touch devices with a Retina display.  (It is also the ugliest required filename, but at least it is better than ‘Default@2x~iphone.png‘.)

Note that the portrait restriction for non-iPad devices is limited only to launch images; universal applications can (and usually should) support all four orientations, portrait and landscape, on iPhone and iPod touch devices.  For other background graphics, there are usually six different images: portrait and landscape each for iPad, iPhone, and iPhone (Retina) devices.

Project Configuration for Launch Images

Once you have the launch image artwork, it is necessary to include all of these files in the Xcode project, so they will be copied to the compiled bundle.  If you choose to use the ‘Default’ naming, this is all that is required.  However, we chose to use a different base file name, so we have to add a ‘Launch image‘ (UILaunchImageFile) string entry, with the value “DemolishPairs“, to the project’s ‘Info.plist‘ file.

Caveat #1: Xcode 4 allows you to drag launch image files to the ‘Summary’ page of a target’s configuration, and it will automatically add these files to the project.  Unfortunately, Xcode only understands the ‘Default’ naming, so it will name the iPad launch images ‘Default-Portrait~ipad.png’ and ‘Default-Landscape~ipad.png’.  These names are invalid on iOS 3.2, which does not recognize the ‘~ipad’ modifier for launch images, so if you use this shortcut and default naming, you still need to remove the “~ipad” part of each filename for backwards compatibility.

Corollary: Choosing not to use the default base file name for launch images (i.e., adding a valid UILaunchImageFile entry) causes Xcode to become confused and show no launch images on the ‘Summary’ page.  Our recommendation is to edit directly on the ‘Info’ page and ignore the ‘Summary’ page altogether.  (Xcode also has trouble with the “pretty” property values if the .plist file ends with anything other than “Info.plist“.)

More observant readers may have noticed that the two iPad launch images allow 20 pixels for the status bar (on the top), while the iPhone/iPod touch do not.  In order for those launch images not to lose 20 points (20 pixels for non-Retina, 40 pixels for Retina displays) hidden underneath a status bar, you need to hide the status bar on launch.  This is done by adding a ‘Status bar is initially hidden‘ (UIStatusBarHidden) boolean entry set to YES.  (Of course, you could compensate with the artwork, too, I suppose.)

Caveat #2: Hiding the status bar works fine for iPads running iOS 3, which (correctly) just turns the reserved status bar area black, displaying the launch image correctly regardless.  Unfortunately, iOS 4 ill-advisedly attempts to use the entire screen when the status bar is hidden, thus invalidating all of the Apple recommendations for launch image size.  The result is a stretched launch image which, because aspect ratio is preserved, extends off the right edge of the screen.  The only way to make launch images behave the same on all iPads is to not hide the status bar.  Fortunately, this can be done without invalidating the previous change by adding an iPad specific version of the property, UIStatusBarHidden~ipad, and set its (boolean) value to NO.  (Xcode itself does not understand the setting, so it has no “pretty” name, but iOS handles it just fine.)

Caveat #3: When entering property names for the Info.plist, especially for those specific to iPad (or iPhone), note that the names are case-sensitive.  In particular, the modifier is “~ipad” (or “~iphone“); if you capitalize the ‘P’ out of habit, the entire property will be ignored (on any device).

Technical notes:  The above information has been thoroughly tested using Xcode 4.0, specially created launch images, and both the iOS Simulator and a variety of physical devices.  The launch images were designed to be distinguishable from each other, with single pixel borders for detecting stretching and clipping.  Results were confirmed for iOS 4 on the simulator for all three types of devices: “iPad”, “iPhone”, and “iPhone (Retina)”, as well as on an original iPad (iOS 3.2), a second generation iPod touch (iOS 4.2.1), an iPhone 4 (iOS 4.2.6), and an iPad 2 (iOS 4.3.5).  [Editor's note: We have no plans to upgrade any device to iOS 5.x in the immediate future.]

Making sure that your application icons and launch images look great is an early step in creating a compelling game experience, and I hope that both parts of this article help you develop a universal iOS application without falling victim to one of the potential iOS pitfalls with your branding graphics.  As always, questions and comments are happily accepted.

Ten Little Images (or so), Part 1

October 20th, 2011

Making sense of icon image requirements for iOS universal applications.

If you are developing (or considering) a “universal” application for iOS, an app that will run on all (current) iOS devices, one of the first things you have to consider are the initial branding graphics for your game.  These include the icons, in various sizes, and the launch images for each device.

The icons, of course, are displayed on the home screen of the device to represent the game, but they can also be shown (in different sizes) on the search page (as well as in Settings, if appropriate).  The launch images are stand-in graphics that are displayed in a static fashion while the app is loaded and initializes itself.  On an iPad, there need to be launch images for each orientation (portrait and landscape), while the iPhone and iPod Touch only launch in portrait orientation.  For more variety, though, the iPhone 4 and 4th generation iPod Touch have the Retina displays, with higher resolution, requiring still more images.

The assumptions here are that you are creating a “universal” application, supporting iOS 3.2 (the minimum version for iPad), and want to be sure to have your branding artwork shown in the best light on all three types of devices.  If you are supporting only iPad (no small screens or Retina displays) or only iOS 4+ (no backwards compatibility), then there are fewer conflicts and caveats, but this article should still be helpful.

Icon Artwork Specifications

All icon (and launch) images must be in PNG format (24-bit), with no transparency.  Although there are naming conventions for automatically loading different files according to the device type, arbitrary (descriptive) file names for icons are preferred and more reliable.  In our case, we use the project name (“DemolishPairs” herein) as a base name, with “ipad”, “iphone”, and “retina” used as modifiers.

For complete icon coverage, with no scaling performed by iOS, we have the following (8) icon files:

  1. DemolishPairs.png [512x512] – This is the largest (current) icon size for iOS applications; generally, the artwork should begin at this size (or larger) and be scaled down to the other sizes.
  2. DemolishPairs_ipad.png [72x72] – This is the application icon for the iPad, as shown on the home screen.
  3. DemolishPairs_ipad_small.png [50x50] – This is the application icon for iPad, displayed in search results.
  4. DemolishPairs_iphone.png [57x57] – This is the application icon for the older (non-Retina) iPhone and iPod touch.
  5. DemolishPairs_iphone_small.png [29x29] – This is the search results icon for the older iPhone and iPod touch.
  6. DemolishPairs_retina.png [114x114] – This is the application icon for the newer (Retina) iPhone and iPod touch.
  7. DemolishPairs_retina_small.png [58x58] – This is the search results icon for iPhone/iPod touch with Retina displays.
  8. iTunesArtwork [512x512] – This is (in our case) a copy of ‘DemolishPairs.png‘ with a very specific filename (note: no file extension, not even ‘.png’) for ad-hoc distribution and/or submission to the App Store.

Note that most games will not have Settings packages, but those that do can use the 29×29 icon [5] for all older displays, including iPad, and the 58×58 icon [7] for all Retina displays.  (Document icons have different requirements but are generally unnecessary for games, so they are not covered here.)

Project Configuration for Icons

Once you have the icon artwork, it is necessary to include all of the icon files in the Xcode project, so they will be copied to the compiled bundle, and then modify the project’s ‘Info.plist‘ file (by whichever name) to indicate the icon image filenames.  There are two possible entries that indicate icons, and since we are specifying multiple image files (and by Apple recommendation), we will add an ‘Icon files‘ (CFBundleIconFiles) array with six entries:

  • DemolishPairs_ipad.png
  • DemolishPairs_ipad_small.png
  • DemolishPairs_iphone.png
  • DemolishPairs_iphone_small.png
  • DemolishPairs_retina.png
  • DemolishPairs_retina_small.png

Caveat:  ‘DemolishPairs_ipad_small.png‘ must appear before ‘DemolishPairs_iphone.png‘ in the list; otherwise, iOS 3.2 (iPad) will incorrectly select the 57×57 icon instead of the 50×50 icon when displaying search results.

Although the CFBundleIconFiles array takes precedence, there is still a minor reason to add the (singular) ‘Icon file‘ (CFBundleIconFile) string, with “DemolishPairs.png” as the value.  Xcode 4 uses this image file as the default icon for the target application in the project; if it is missing or empty, the last entry in the array is used.  This (currently) has no practical impact on the application itself, but supplying a reference (512×512) icon within the bundle is not a bad thing.

Of course, if one is building an application for only iPad devices, the number of icons necessary is reduced, but I would still recommend getting a complete set of the above icon sizes from your artist anyway (just in case).  On the other hand, if one is building an application for only iPhone devices, shame on you; there is no excuse for not supporting the iPad nowadays.

Technical notes:  The above information has been thoroughly tested using Xcode 4.0, specially created test icons, and both the iOS Simulator and a variety of physical devices.  The icon images were designed to be distinguishable from each other, with single pixel borders for detecting stretching and clipping.  Results were confirmed for iOS 4 on the simulator for all three types of devices: “iPad”, “iPhone”, and “iPhone (Retina)”, as well as on an original iPad (iOS 3.2), a second generation iPod touch (iOS 4.2.1), an iPhone 4 (iOS 4.2.6), and an iPad 2 (iOS 4.3.5).  [Editor's note: We have no plans to upgrade any device to iOS 5.x in the immediate future.]

In our next installment, Ten Little Images (or so), Part 2, I discuss the requirements and caveats of launch images in universal iOS applications.

Carbon nibs update

October 3rd, 2011

A spurious warning appears to be spurious.

In my last post, Carbon nibs under Lion, I gave a solution to the problem of Carbon nib (interface) files not being supported in Xcode 4, while Xcode 3 would not run under Mac OS X 10.7 (Lion).  That solution was to run Interface Build 3.2.6 and convert the nibs to a newer format.

Toward the end of the post I mentioned that many windows in the converted nib files produced a warning: “This window’s content rectangle does not lie entirely on the screen with the menu bar and may not be completely visible for all screen resolutions and configurations.“  In testing, these files did not exhibit any errant behavior, but shipping a product, even a beta, with build warnings is against our development guidelines.

Since that post (and in preparation for a proper build, without warnings), I did a little research and experimentation and discovered that the problem appears to be a minor issue with the conversion, where the resulting data is aberrant enough to generate a warning, but is handled correctly in the resulting application.  Although I did not dig deeply enough to identify the exact source of the problem, it is related to window positioning (as one may have guessed).

The solution, oddly, is simply to open the offending nib file, select the (or each) window, click on the Size (ruler) tab in the Inspector, and then drag the window position image, even slightly.  As far as I can discern, any movement (within the simulated window) fixes the problem; at least, it fixed it for all of my affected windows.  Clearly, the size of the windows was not the issue, since that was not changed, and the position should never have been a problem, either, for windows with the ‘Center’ attribute enabled (as most of mine were).  I also note that the windows I created from scratch since moving to this Lion/IB 3.2.6 setup were unaffected.

One other idiosyncrasy to note is that the build process also produces the following message: “View is clipping its content.“  It is not a warning, just a message, and I assumed that it was related to the above warning until the warnings were fixed.  It is a straightforward message, albeit with no reference to the specific view involved, so I looked into find the problem there as well.

As it turns out, there is a very useful tool with IB 3.2.6 to assist with this.  Select ‘Layout->Show Clipping Indicators’ to enable a feature that displays a small “+” at the bottom of any view that is clipping its content.  I never noticed this setting before, and it can be very handy.  Alas, it also reveals (in our case) that the messages are just pointless chatter, since they are being given for list views with extra columns that are intended to scroll horizontally.  Fortunately, they do not produce a warning message, so the messages are easily ignored; in fact, they only appear on the full build log, so I may have never noticed them had I not been debugging a nearby warning.

[The most meaningful comment that I received for the last post was (seriously), "I've a cockroach on my pillow.  Wanna see it?"  The days of technical development posts may be numbered.]

Carbon nibs under Lion (Mac OS X 10.7)

September 28th, 2011

Apple’s overly aggressive deprecation sucks.

If you are still maintaining a Carbon application for Mac OS X, you may have stumbled upon a serious issue with handling of nib (interface) files in Xcode 4 under Lion, and if you have not yet, you probably will soon.  Hopefully, this post will help you resolve problems or avoid some of the pitfalls.

The Problems

Apple marches forward and aggressively deprecates development technology.  In this particular case, they release Xcode 4 and only allow submissions to the Mac App Store from the latest version, forcing developers to upgrade.  We are maintaining and enhancing a product that was developed using Carbon, based on Apple’s (then) recommendation for cross-platform products, and was about 90% complete when they announced its deprecation in favor of Cocoa.

Additionally, we upgraded to Lion (to properly provide customer support), unaware that the latest version of Xcode 3, version 3.2.6, would not install or run on Lion.  Instead, we could only download and install Xcode 4.1, which does not provide support for Carbon nib files.  With Snow Leopard, we could download both versions normally, but from Lion, the Xcode 3 download link is removed and Xcode 4 is only available via the Mac App Store.  More accurately, the installer is available via the Mac App Store; you still need to find it in Launchpad and run it before Xcode is ready.

There are two particular problems that occur with Carbon nibs in Xcode 4.1:

First, there is no editing capability for modifying them, so when you highlight a Carbon nib, the editing window only displays an Interface Builder icon, but (importantly and annoyingly) there is no message that editing is not supported.  Unless you already know that is the case, you will waste some amount of time attempting to figure out how to activate the “integrated” Interface Builder.

Second, the build tools provided cannot process the older nib files, so you will get a message similar to the following: ‘error: ibtool could not strip “Main.nib” because it is not a valid Interface Builder document.

Of course, there are a few obvious options here.  If you stop upgrading your development system, you can still build on Xcode 3.2.6 under Snow Leopard, except that you cannot submit to the Mac App Store.  You may be able to have both versions in parallel, but that is not an option on Lion at all, and the nib build issue still exists in Xcode 4 (although the solution to that is provided below).  Finally, you can give in to Apple’s strongarm tactics and rewrite your application to use Cocoa, but that is not always feasible, economically or otherwise.  (In our case, we are trying to maintain our products and support our customers while we rewrite it with Cocoa.)

Or, I suppose, you could flip Apple the bird and abandon their Mac platform; that has crossed my mind more than once, but it is not really an option for us.  Instead, I found a way to resolve the two main problems above, without too much effort.  (That is, it will be fairly easy for you readers; it took me significant time to figure this all out.)

The Solution

To resolve the inability to edit Carbon nib files within Xcode 4, take advantage of the fact that Interface Builder was an external tool with Xcode 3, and that it does run in Lion.  Simply copy Interface Builder 3.2.6 from a (Snow Leopard) partition on which it is installed to the Lion partition.  It should be located (by default) in the ‘/Developer/Applications’ folder, and note that it must be copied to the same directory on the Lion partition after Xcode 4.1 is installed.  (It will not run properly from a different folder, and the Xcode installer apparently removes it [so make a backup copy].)  Since Xcode will no longer launch (the external) Interface Builder automatically, you will probably want to make an alias for it in a convenient location.

Then, to resolve the build problems with the older nib files, you must use the separate Interface Builder tool to covert your nib files to a newer (XIB) format.  This is accomplished by opening each nib file in IB, selecting ‘File->Save As…’ from the menu, changing the ‘File Type’ to “Interface Build Carbon Document (XIB 3.x)”, and saving.  You will then need to open your project in Xcode, add all of the new .xib files to it, and delete the older .nib files.  Clicking on one of the .xib files in Xcode will show/edit it as an XML file (instead of just an icon) but, of course, you will probably only want to edit it in your newly installed IB3.

There may (read: probably will) be other issues, both with Xcode 4 itself and with the newer SDKs.  For example, we use one (and only 1) function defined in ‘QuickdrawAPI.h’, which has been removed from the OS X 10.7 SDK, so we had to back down to the 10.6 SDK (plus each SDK has different versions of the zlib library available).  Also, several of our windows from (converted) nib files produce a new warning: “This window’s content rectangle does not lie entirely on the screen with the menu bar and may not be completely visible for all screen resolutions and configurations.“  (We dynamically adjust most of our windows anyway, so it appears to make no difference, but we have yet to eliminate these warnings.)

Nevertheless, making the above changes will allow an older Carbon-based application to be built on Lion using Xcode 4.1, leaving you free to discover more fun and excitement.

[If you find this information useful, please leave a meaningful comment.]

10 Years of the GDcard Library

September 26th, 2011

We celebrate a decade of collaboration with Goodsol.

Time really does fly when you are having fun (and doing what you love).  It was 10 years ago today that we delivered the first properly functional version of a playing card library, then named PGScard.dll, to Goodsol Development.  We have been working with them ever since, improving this library, which is used heavily in Pretty Good Solitaire, writing new games (see below), and extending the product line to include Mac OS X (and, soon, IOS), as well as our Windows products.

Back then, the whole nation was still asking questions, like ‘Where do we go from here?‘  We were facing a bit of a crisis here as well, as our primary external opportunity was stopped in the midst of economic uncertainty, and our main internal project was rendered unpalatable for release, so we were available immediately when Thomas Warfield inquired.  (The subject line of my reply was, “Work?  Did you say work? <g>“.)

In the intervening years, the library was renamed to GDcard, had numerous extensions and updates, and has been in every PGS release (for Windows) in the last decade.  The current version, GDcard 2.09, has not required any modifications in the past 4 years, but it still draws cards and provides other related functionality in the latest release, Pretty Good Solitaire 13.1.0 (with 770 games), published last week (almost 10 years to the day after the initial agreement).

This first project led to many others with Goodsol (in roughly chronological order):

… and several products to be announced later.  All of the above games have trial versions available for download (at the links provided).  We also created MahJongg Patience (a smaller version of PGMJ) for the original (retail) MahJongg Master, published in 2003 by eGames.  (I now see that we are averaging more than one new SKU per year.)

I do not expect to be exchanging diamond jewelry, or even tin or aluminum gifts, but I do look forward to much more productivity and success from this arrangement in the future.  Thanks, Thomas and Anne!

Disk Images Revisited

February 9th, 2010

There are some issues under Snow Leopard.

In a blog post last year, I gave detailed instructions on Making Mac Disk Images Pretty.  Unfortunately, I have discovered that the most recent version of Mac OS X has some issues of which developers should be aware when using that technique (not that there is any obvious alternative).

I recently upgraded my development system to Mac OS X 10.6 (Snow Leopard).  Apple is fairly aggressive with requirements for its development tools,  and I need to upgrade in order to use the latest iPhone SDK.  Of course, I already had a Snow Leopard partition that I had used for testing, so I knew that our software would work, and I never experienced any previous problems.

When the time came to build an update for one of our products (FreeCell Plus 4.00/4.01), I had a few minor niggles with Xcode 3.2.1 (the latest version), described later, but I got the product built and packaged properly.  Then it was time for testing on our other supported versions of Mac OS X, Tiger (10.4) and Leopard (10.5), and I was surprised to learn that, although the software itself ran flawlessly, the disk images showed no background image when mounted, and the folder size was wrong.  The icons were in the correct locations, relative to the top left corner of the window, so the formatting was not entirely ignored, just effectively ignored.

After some research into the problem, I found the answer in this DropDMG forum thread, where it is stated that Apple has confirmed this as a bug in Snow Leopard.  I moved DropDMG over to my Leopard partition, rebooted to that version of Mac OS X (10.5), and build my packages there.  That solved the problem, and the background images showed in all supported versions of OS X.

Conclusion: In order to have background images appear in disk images on older versions of Mac OS X, you must build the disk image under Leopard or earlier, not Snow Leopard.

Caveats: Sometimes, when opening a prepared disk image under Snow Leopard, there is a blank space on the bottom (probably not coincidentally exactly the same size as the folder toolbar), which does not appear on other versions of Mac OS X.  Also under 10.6, the folder toolbar includes a slider control for quickly changing icon sizes (a.k.a., fouling up your layout).  I have not been able to determine the cause of the former issue (yet) nor the reason for the latter.  (How often does one actually change icon sizes that this is even remotely necessary?)

There were some build issues with Xcode 3.2.1 under Snow Leopard.

As I mentioned, I experienced a couple minor build issues after the upgrade to Xcode 3.2.1, both of which were addressed, albeit with differing degrees of success.

First, the default compiler in the latest version of Xcode is GNU 4.2, which is incompatible with the 10.4 (universal) SDK, and the very first build let me know that.  Faced with a choice, downgrading the compiler to GNU 4.0 versus upgrading to the 10.6 SDK, I chose the latter, which I saw as the path of least resistance (see “Apple is fairly aggressive with requirements for its development tools” above).  Unfortunately, at least for our project, the 10.6 SDK does not function as advertised and, despite properly setting the target OS to 10.4 (and obviously not using any 10.5 or 10.6 features), a product built with the 10.6 SDK will not run under Tiger (period), although it does work under Leopard.  I switched (back) to GNU 4.0 and the 10.4 SDK and all was well.

Second, the latest version of Xcode upgrades its tools (obviously), and one seemingly innocuous change to the linker was to eliminate the need for the “-mlong-branch” compile option for certain object files (generally kernel files, which means primarily for Apple and not so much for the rest of us).  Unfortunately, a warning message was added to that effect, yet Apple did not update its PPC object files accordingly.  As a result, every time one links a universal binary (supporting PPC), the linker throws this warning: “Object file compiled with -mlong-branch which is no longer needed.“  The only permanent solution is to recompile certain (protected) development files oneself, or wait until Apple fixes the problem.

The latter issue is extremely annoying to me, because now I am in the position of either ignoring linker warnings, which I never advise, or spending hours (or days) figuring out how to rebuild a portion of the development tools.  Can you say, “not my job“?  Personally, from my experience of Apple over the last few years, my bet is that this problem will soon be addressed by a campaign to suggest that developers should not continue to be stuck in the past supporting PPC systems.

Does anybody want a piece of that action?