Instead of recreating an object over and over again, is there a way I can check if an object exists in an if statement?
Thanks!
Assuming your object reference is set to nil if there is no object, then you can use
NSThing *myobj = nil;
if (!myobj)
myobj = [[NSThing alloc] init];
[myobj message];
Depends on your situation. You could use a static variable, i.e.
- (void) doSomething
{
static id foo = nil;
if (! foo)
foo = [[MyClass alloc] init];
// Do something with foo.
}
The first time -doSomething gets called, MyClass will be instantiated. Note that this isn't thread-safe.
Another way is to use a singleton. Possibly a better way is to instantiate the object when the application has finished launching and pass the object to any other objects that might need it.
The thread safe common way to initialize some instance using GCD is as follows:
static dispatch_once_t once;
dispatch_once(&once, ^{
obj = [NSSomeThing new];
});
Related
I'm reading through a book trying to brush the dust off of Objective-C, and I ran into this question while reading how to implement a singleton. This is the implementation as they have it in the book:
+ (ClassName *)sharedClass {
static ClassName *sharedClass = nil;
if (!sharedClass) {
sharedClass = [[super allocWithZone:nil] init];
return shared store
}
My question is, why would they set it to nil each time the method is ran, then check if it's nil, which it now obviously is, and create a new instance? That sounds like it defeats the whole purpose of a singleton, to only have one instance of a class. I've noticed a ton of questions related to singleton implementation, but none specific to this aspect of it. Believe me, I combed through before posting.
The static variable is set to nil only for the first time. Once the sharedClass instance is instantiated, you will alway have the same instance whenever you invoke [ClassName sharedClass].
You should use thread-safe pattern to use singleton pattern.
+ (instancetype)shared {
static id shared = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
shared = [[self alloc] init];
});
return sharedInstance;
}
This will prevent possible crashes.
I've got a class method that uses dispatch_once to create a static object. Inside the dispatch_once block I use [self class] and was wondering if I need to use a weak reference to self to avoid a retain cycle?
+ (NSArray *)accountNames{
static NSArray *names = nil;
static dispatch_once_t predicate;
dispatch_once(&predicate, ^{
names = [[[self class] accounts] allKeys];
names = [names sortedArrayUsingSelector:#selector(caseInsensitiveCompare:)];
});
return names;
}
If I use a weak reference to self I get a warning:
+ (NSArray *)accountNames{
static NSArray *names = nil;
static dispatch_once_t predicate;
__weak TUAccount *wself = self;
dispatch_once(&predicate, ^{
names = [[[wself class] accounts] allKeys];
names = [names sortedArrayUsingSelector:#selector(caseInsensitiveCompare:)];
});
return names;
}
Incompatible pointer types initializing 'TUAccount *__weak' with an expression of type 'const Class'
Because I get a warning I don't think I need to use a weak reference to self in this case but I wanted to see what you guys thought.
There is no reason to worry about a retain cycle here, because it's meaningless to retain or release a class object -- retain and release simply have no effect.
Your attempt at making a weak reference is wrong, because you are taking a class object self and trying to cast it to an instance of TUAccount. The two are completely different things.
Also, you can simplify:
names = [[[self class] accounts] allKeys];
Since self is already a class, [self class] == self, so do this instead:
names = [[self accounts] allKeys];
I have checked one more time iOS SDK Docs and found next:
Objective-C Objects
In a manually reference-counted environment, local variables used within the block are retained when the block is copied. Use of instance variables within the block will cause the object itself to be retained. If you wish to override this behavior for a particular object variable, you can mark it with the __block storage type modifier.
If you are using ARC, object variables are retained and released automatically as the block is copied and later released.
Note: In a garbage-collected environment, if you apply both __weak and __block modifiers to a variable, then the block will not ensure that it is kept alive.
If you use a block within the implementation of a method, the rules for memory management of object instance variables are more subtle:
If you access an instance variable by reference, self is retained;
If you access an instance variable by value, the variable is retained.
The following examples illustrate the two different situations:
dispatch_async(queue, ^{
// instanceVariable is used by reference, self is retained
doSomethingWithObject(instanceVariable);
});
id localVariable = instanceVariable;
dispatch_async(queue, ^{
// localVariable is used by value, localVariable is retained (not self)
doSomethingWithObject(localVariable);
});
Conclusion: I assume that there is no problem with using self in block. It will be retained and after execution released.
Moreover, you are not storing block in memory and using it directly. So it is copied to the heap, executed and pushed from it. I don't see any retain cycles.
Hope I am right!
is smth. like this legit? it compiles and looks running ok, but is it ok? (aim setting myself to nil, inside my method)
i mean iam setting myself static to nil, in a method
static MyClass * StaticInstance = nil;
+ (MyClass *) sharedStaticInstance
{
if (StaticInstance == nil) {
StaticInstance = [[MyClass alloc] init];
}
return StaticInstance;
}
- (void) killStaticSelf
{
StaticInstance = nil;
}
and later
[[MyClass sharedStaticInstance] doSmth]; // our static instance is created
[[MyClass sharedStaticInstance] killStaticSelf]; // now its killed inside itself method
[[MyClass sharedStaticInstance] doSmth]; // now it should recreate again
Its having a memory leak.
You should dealloc the StaticInstance first and then you should assign nil to it.
Yes, that's how it's done. I use the sharedStaticInstance often, though I don't usually create a destructor it's probably a good idea, as long as all references to the shared instance in this class pass through sharedStaticInstance first.
EDIT: I just noticed that killStaticSelf is an instance method - it should be a class method I believe, but there shouldn't be any issue either way.
[MyClass killStaticSelf];
Even as the function stack closes, since sending messages to nil doesn't cause issues in Objective-C.
your sharedInstance method is not thread safe so you could get a race condition in this code:
if (StaticInstance == nil) {
StaticInstance = [[MyClass alloc] init];
}
- (void) killStaticSelf
{
StaticInstance = nil;
}
the above code has a leak since you do not provide StaticInstance as a retain property (apparently). You could instead wrap your singleton code in a property but that uses the same static instance.
It's legit, but you need to release the variable before setting it to nil, to avoid memory leaks if you're not using ARC.
Though comprehension of such singleton usage logic is beyond my humble brain abilities.
I would like to know how to create an object of the specified Class in objective c. Is there some method I am missing in the runtime docs? If so what is it? I would like to be able to do something like the following:
NSDictionary *types;
-(id<AProtocol>) createInstance:(NSString *) name
{
if ((Class cls = [types objectForKey:name]) != nil)
{
return new Instance of cls;
}
else
{
[NSException raise:#"class not found" format:#"The specified class (%#) was not found.", name];
}
}
please note that name is not a name of the class, but an abbreviation for it, and I cannot do what is indicated in Create object from NSString of class name in Objective-C.
A simple [[cls alloc] init] will do the trick.
As cobbal has mentioned [[cls alloc] init] is usual practice. The alloc is a static class method, defined in NSObject, that allocates the memory and init is the instance constructor. Many classes provide convenience constructors that do this in one step for you. An example is:
NSString* str = [NSString stringWithString:#"Blah..."];
Note the * after NSString. You're working essentially with C here so pointers to objects!
Also, don't forget to free memory allocated using alloc with a corresponding [instance release]. You do not need to free the memory created with a convenience constructor as that is autoreleased for you. When you return your new instance of cls, you should add it to the autorelease pool so that you don't leak memory:
return [[[cls alloc] init] autorelease];
Hope this helps.
I have seen a lot of talk about dynamic typing in objective-c. But i haven't seen any examples of what i think it is supposed to be.
lets say I have a generic function that is supposed to juggle two objects (one gets allocated and the other gets freed) and the calling object attaches it self to the newly alloced object. Both are inherited from class0
Please feel free to interpret this however you want if you think it will explain something!!
If the class is picked at runtime, how do i deal with the arguments list (? is a placeholder for now)
How do i alloc a object who's class is not defined until runtime?
-(void) juggle:(?*)objclass1:(?*)objclass2{
? temp = [? alloc] init];
objclass1 = temp;
[temp release];
[objclass2.view removefromsuperview];
[self.handle insertsubview:objclass1.view];
}
I have no idea what the code you have there is trying to do, it is not syntactically valid, and manipulating views has nothing to do with your questions. Anyway, if you really don't know the type you generally use "id" which is type cast to a "void *" for codegen. It has the special property that it is assumed to receive any message, so it does not trigger compiler warnings for unknown messages.
In order to instantiate a class you just need to be holding the "Class" object for it. In Objective C all instances of a class refer to a Class object (the isa pointer in the legacy runtime), which also responds to methods. So in other words, in the following code:
NSArray *myObject = [[NSArray alloc] init];
NSArray is actually an object. So this will generate equivalent code results:
Class myClass = [NSArray class];
NSArray *myObject = [[myClass alloc] init];
or even
Class myClass = NSClassFromString(#"NSArray");
NSArray *myObject = [[myClass alloc] init];
Which uses the function NSClassFromString which walks into the runtime and finds a class with the name you pass in.
All objects return their class if use the class getter, so to instantiate an object that is the same class as an existing object like this:
- (void) leakObjectWithSameClassAs:(id)object {
[[[object class] alloc] init];
}
This is what i have now
- (void)flipfromv1tov2:(UIViewController*)v1:(NSString*)nib1:(UIViewController*)v2{
if(v1 == nil)
{
UIViewController *newview = [[[v1 class] alloc] initWithNibName:nib1 bundle:nil];
v1 = newview;
[newview release];
}
[v2.view removeFromSuperview];
[self.view insertSubview:v1.view atIndex:0];
}
I cannot verify it yet because I have a linking problem...I added this func to my root controller but for some reason I get a warning that the function is implicitly declared. And the build fails because the function call never get linked to anything