Re: Bundle Reloading
Re: Bundle Reloading
- Subject: Re: Bundle Reloading
- From: glenn andreas <email@hidden>
- Date: Wed, 7 Dec 2005 09:18:14 -0600
On Dec 7, 2005, at 8:44 AM, Josh Ferguson wrote:
I know there has already been a lengthy thread on unloading/
reloading a
bundle. Because of certain constraints, I need to be able to update
and
reload a bundle at runtime. As it currently stands, my framework
downloads an update for itself to a temp directory, moves the old
bundle
to the trash, and copies the new one to the new location. The class
that
I need is loaded dynamically by creating an NSBundle instance using
the
path to my class, then calling [NSBundle load] and
NSClassFromString. It
seems, however, that the first loading of NSBundle is cached in
memory.
When I go to load the bundle again (specifying the path to the new
bundle in the old location), it's still giving me the old bundle. I
know
this because when I grab the CFBundleVersion from the plist it's
giving
me the old version number.
My question is this: what do I need to change in the bundle
(CFBundleIdentifier? Class name? etc.?) to ensure that when I
create the
NSBundle using -[NSBundle bundleWithPath], it actually reloads it in
memory?
The core problem is that Objective-C does not support unloading -
once a class, category, etc... has been loaded, that's it - you can't
remove it.
What you might be able to do, however, assuming that the classes in
the bundle are nice and modular, is effectively treat the new bundle
as a second, completely separate, bundle (and you might need to break
your classes in two to accomplish this).
The idea is that you would treat this "dynamically updated class" as
a class cluster - there would be a public abstract superclass, which
would then instantiate an appropriate subclass. Each subclass would
probably have the version number included with it (as would the
bundle identifier).
So roughly, you'd make your bundle:
com.company.product.myclass.1: (primary class "MyClass1")
@interface MyClass1 : MyClass
and then later you'd have an update that could be downloaded:
com.company.product.myclass.2: (primary class "MyClass2")
@interface MyClass2 : MyClass
Your application would have something roughly this (heavy in pseudo
code due to light in coffee):
@implementation MyClass
+ (id) alloc
{
highestVersion = 0;
for each [NSBundle allBundles] {
if bundle id starts with "com.company.product.myclass" get the
versionNumber
if (versionNumber > highestVersion) {
highestVersion = versionNumber
highestBundle = bundle
}
}
check with server to see if newversion(highestVersion) exists
if newer available {
download new bundle
put it where it needs to be
[newBundle load]
highestBundle = newBundle
}
return [NSClassFromString([higestBundle principleClass]) alloc];
}
@end
Obviously, some of that should probably be cached (since you don't
want to contact a server for each alloc), but that basic structure
should work.
Glenn Andreas email@hidden
<
http://www.gandreas.com/> wicked fun!
quadrium | build, mutate, evolve | images, textures, backgrounds, art
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden