RE: Bundle Reloading
RE: Bundle Reloading
- Subject: RE: Bundle Reloading
- From: "Josh Ferguson" <email@hidden>
- Date: Fri, 16 Dec 2005 16:46:00 -0600
- Thread-topic: Bundle Reloading
Glenn,
I'm running into another issue now. What I thought I had working doesn't
seem to be working. It appears that no matter if I change the classname
or the bundle identifier, it never reloads the bundle when I tell
NSBundle to load it. Here's my workflow:
1.) Load bundle 1.0.0.0
2.) Call update function
3.) Download new bundle (1.0.0.1) to temp directory
4.) Decompress new bundle and name it a temporary name (blah.framework)
5.) Try to load the new bundle (with new bundle identifier and
classname)
6.) Grab the new class out of the new bundle
<PROBLEM> the class is never found. Both the -[NSBundle classNamed:] and
NSClassFromString() say that the class can't be found. When I send the
-[NSBundle load] command to the new bundle, I never get a bundleLoaded
notification. If I quit my app and launch again, it will load the new
framework, so there must be a cacheing issue going on. What do I need to
do to make sure that my new bundle does indeed get loaded? What does the
OS use to determine if a bundle is indeed different and needs to be
loaded? Or better yet, what does the OS use to make sure redundant
bundles aren't reloaded (so I can avoid it)? I'm sure that the NSBundle
instance I create is pointing at the proper bundle because it can get
the updated version number from the info.plist.
Thanks for your assistance,
Josh
-----Original Message-----
From: glenn andreas [
mailto:email@hidden]
Sent: Wednesday, December 07, 2005 9:18 AM
To: Josh Ferguson
Cc: email@hidden
Subject: Re: Bundle Reloading
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