• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: "weak link" framework refs for 10.1 compatibility?
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: "weak link" framework refs for 10.1 compatibility?


  • Subject: Re: "weak link" framework refs for 10.1 compatibility?
  • From: Piers Uso Walter <email@hidden>
  • Date: Sun, 10 Nov 2002 12:34:40 -0500

Dan Wood wrote:

I'm trying to add some AddressBook framework and NSAppleScript functionality to my app, but still allow for 10.1 compatibility. I'm making sure that no 10.2-specific methods get called in my code, and that's straightforward, but what is a problem is the constants (e.g. the Address Book constants in ABGlobals.h, or NSAppleScriptErrorMessage) are declared within the frameworks, that cause the bundle not to load in 10.1.

This is exactly what we wanted to do and we've come up with the following solution.
We've isolated the address book functionality into two platform specific bundles, one for 10.1 and one for 10.2. Each bundle is built using the matching OS version and is linked against the address book framework of that OS version. Both bundles have the same interface, so that the application can use either one. The application ships with both bundles and determines at run time which one to load, using the following method:

- (void)_loadAddressBundle
{
NSArray *addressBundleNames = [NSArray arrayWithObjects:@"AddressBundle_10.2.bundle", @"AddressBundle_10.1.bundle", nil];
NSBundle *mainBundle = [NSBundle mainBundle];
NSString *bundlePath = [mainBundle bundlePath];
NSString *addressBundleBasePath = [NSString stringWithFormat:@"%@/Contents/Resources", bundlePath];
int i, count;
NSBundle *addressBundle; // will be loaded from a platform specific bundle
#if ! DEBUG
// We do not want to send bundle loading errors to /dev/null in debug versions
int fd_devnull;
int fd_stderr;
int fd_stderr_new;
#endif // ! DEBUG

// Initially we used the NSAppKitVersionNumber in order to decide which bundle version to load (NSAppKitVersionNumber < 645.3: AddressBundle_10.1.bundle, NSAppKitVersionNumber >= 645.3: AddressBundle_10.2.bundle). This works without any problems, but is not very elegant from a conceptual standpoint. It is somewhat far-fetched to use the AppKit framework version in order to deduce which address framework may be present in a system.
// Our new approach tries to load an address bundle, starting with the latest one and falling back to earlier versions, if necessary. Each address bundle is linked against its matching address framework. If this framework is not available, the bundle cannot be loaded (unfortunately, NSBundle writes an error message to stderr in this case, which we have to "remove"). By testing the results of the bundle loading operation, we can determine the success, and decide to fall back to an earlier bundle version, if necessary. This is a much cleaner solution because it actually (implicilty) tests the version of the address framework.

#if ! DEBUG
fd_devnull = open("/dev/null", O_WRONLY, NULL); // this file descriptor points to /dev/null
fd_stderr = dup(STDERR_FILENO); // this file descriptor points to wherever stderr points to
#endif // ! DEBUG

count = [addressBundleNames count];
for (i = 0; i < count; i++) {
// Try loading an address bundle (going from newest to oldest one):
NSString *addressBundleName = [addressBundleNames objectAtIndex:i];
NSString *addressBundlePath = [[NSString stringWithFormat:@"%@/%@", addressBundleBasePath, addressBundleName] stringByResolvingSymlinksInPath];

addressBundle = [NSBundle bundleWithPath:addressBundlePath];
if (nil != addressBundle) {
// We've found a bundle.

#if ! DEBUG
// Temporarily redirect stderr to /dev/null (because NSBundle writes an error message to stderr if a bundle can't be loaded and we do not want to see this error message in non-debug versions):
fd_stderr_new = dup2(fd_devnull, STDERR_FILENO); // stderr now points to /dev/null
#endif // ! DEBUG

// Try to load the bundle:
addressController = [[[addressBundle principalClass] alloc] init];

#if ! DEBUG
// Restore stderr:
fd_stderr_new = dup2(fd_stderr, STDERR_FILENO); // stderr now once again points to wherever it pointed to before
#endif // ! DEBUG

if (nil != addressController) {
break;
}
}
}

#if ! DEBUG
fd_stderr_new = close(fd_devnull);
fd_stderr_new = close(fd_stderr);
#endif // ! DEBUG

if (nil == addressController) {
ILRunLocalizedAlertPanel(@"No Local Address Book Title", @"No Local Address Book Message", nil, nil, nil, addressBundleBasePath);
return;
}
} // -_loadAddressBundle



I hope this helps.


With kind regards

Piers Uso Walter <email@hidden>
ilink Kommunikationssysteme GmbH
_______________________________________________
cocoa-dev mailing list | email@hidden
Help/Unsubscribe/Archives: http://www.lists.apple.com/mailman/listinfo/cocoa-dev
Do not post admin requests to the list. They will be ignored.

  • Follow-Ups:
    • Re: "weak link" framework refs for 10.1 compatibility?
      • From: Bill Cheeseman <email@hidden>
References: 
 >"weak link" framework refs for 10.1 compatibility? (From: Dan Wood <email@hidden>)

  • Prev by Date: Re: Using "IMP" to speed up loops?
  • Next by Date: Re: Creating new instances of a window?
  • Previous by thread: Re: "weak link" framework refs for 10.1 compatibility?
  • Next by thread: Re: "weak link" framework refs for 10.1 compatibility?
  • Index(es):
    • Date
    • Thread