Why my Objective-C object doesn't want to be instantiated? - iphone

I've got a problem (in Objective-C/iPhone dev) since more than one week, so I'd be really grateful if someone can help me out.
When I instantiate an object from a class that I've written, it returns me nil, but when I launch the debug mode I actually see in the init method that the attributes of self are correctly initialized and it seems like it doesn't execute the return self instruction.
EDIT:
Thanks for your answers Here is the init code
-(id)initWithDate:(NSString *)aDate
type:(NSString *)aType
amount:(NSString *)anAmount
currency:(NSString *)aCurrency
merchantName:(NSString *)aMerchant
status:(NSString *)aStatus
{
if (!(self = [super init])) return nil;
self->date=aDate;
self->type=aType;
self->amount=anAmount;
self->currency=aCurrency;
self->merchantName=aMerchant;
self->status=aStatus;
return self;
}

Don't use self->instanceVariable.
Just use instanceVariable.

I'd put your code inside the following
if (self = [super init]) {
// Custom initialization
}
return self;
rather than the if (!(self... return nil you have used. But that's just a habit.
I would also avoid the C++ style '->' assignments and instead use self.currency=aCurrency; (or [self setCurrency:aCurrency]; which is closer to the c++ calls I guess) assuming these are declared as #property or have getters and setters.
I'm sure one of those will get you going!

You should write
self.date = aDate;
// etc....
if date etc. is declared as a #property in the #interface, or if it's just a class instance variable, use
date = aDate;
// etc...
Also, if the strings are not declared as #property with retain or copy modifiers, you'll need to manually retain them thus:
date = [aDate retain];

Related

Making Xcode complain about a missing parameter

I am designing a new application by modernizing code I wrote in the past. This old code uses the class/delegate model and I am trying to transform them to use blocks as callbacks, not the delegate stuff.
What I do is to create a property like
#property (nonatomic, copy) void (^onTouch)(NSInteger index);
That would pass to the object using that class a block where code can be inserted and in this case executed on touch.
But my problem is this. When you use delegates and you have a method on the delegate protocol, Xcode will warn if you use that class and forget to implement the delegate protocols. Is that a way to do that with blocks? Or in other words: is there a way to make Xcode complain if a callback block is not defined by the caller?
I mean this would be the correct:
MyClass *obj = [[MyClass alloc] init];
obj.onTouch = ^(NSInteger *index){ //call back code to be executed };
This would be OK too
MyClass *obj = [[MyClass alloc] init];
obj.onTouch = nil;
but this would generate a message
MyClass *obj = [[MyClass alloc] init];
// no callback block defined.
Is this possible?
If you want to enforce setting a certain parameter, I would include it in the initializer.
MyClass *obj = [[MyClass alloc] initWithBlock:^(NSInteger *index) { /* code*/ }];
Then, in MyClass:
- (id)init {
// This will result in a runtime error if you use the wrong initializer.
NSAssert(NO, #"Use initWithBlock instead.");
}
- (id)initWithBlock(initWithBlock:^(NSInteger *)block) {
self = [super init];
if (self) {
self.onTouch = block;
}
return self;
}
Also note, attempting to execute a NULL block results in a crash, so make sure to do:
if (self.onTouch) { self.onTouch(); }
Wherever you run the block.
First, I strongly recommend defining types to represent your blocks - makes them a lot easier to work with, especially if you need to refactor the parameters.
You can't write code that distinguishes between "I set this property to nil" or "the runtime initialized this property to nil", at least not without some crazy runtime code to check the stack. Only option I can think of would be to use the null object pattern. Before I elaborate, bear in mind that I haven't actually tried to test this, but it should work. Define a block that means 'has no value' and set your property to point to that block on init. Then you can compare to that NullBlock at runtime to identify if someone explicitly set the property to nil (because it would be nil at that point) or gave it a real non-nil value.
Alternatively, if you don't mind manually writing your set accessors, you could have a BOOL that tracks if someone set the property explicitly. Then when you call the block just check if someone actually set the value or not.
#synthesize onTouchBlock=_onTouchBlock;
MyBlock _onTouchBlock;
BOOL _onTouchBlockWasSet;
- (void)setOnTouchBlock:(MyBlock)block {
_onTouchBlockWasSet = YES;
_onTouchBlock = block;
}
I would not recommend passing the value in the initializer because that makes it tied to the creation of that object type. If you wanted to change the block in code based on some condition, you'd be back to square one. Also, it prevents you from using storyboards which create that object.

iPhone: Why do I need self.<> in viewDidUnload?

I heard from people that you should use self in viewDidUnload. For instance, this is good:
- (void)viewDidUnload
{
self.object = nil;
self.object2 = nil
}
- (void)viewDidUnload
{
object = nil;
object2 = nil;
}
Is there a difference between the 2? And what is it?
There is a difference. The code that is generated by #synthesize will call release on the references to the objects you have before setting the new value. A call to self.object = nil will effectively both release the reference and set it to nil. Without the self it will just set the reference to nil.
What is almost the same as your second example is this:
- (void)viewDidUnload
{
[object release]; object = nil;
[object2 release]; object2 = nil;
}
Note they are not quite the same - if you had defined a custom getter/setter, or had KVC observers set up around one of those properties the self.object = nil would trigger them, whereas the straight [object release] above would not.
First of all, using self eliminates ambiguity.
- (void)viewDidUnload
{
id object = #"whatever";
object = nil; // This refers to the local variable above
self.object = nil; // This refers to the setter of the ivar belonging to the class
}
Another thing to watch out for is if you have the variables synthesized (meaning if you tell the compiler to generate getter & setter automatically), self.object will invoke the getter/setter, while simply object refers to the actual ivar. To prevent this ambiguity when accessing ivar vs calling the setter, you can write something like this:
self->object = nil; // This refers to the ivar object, not the getter/setter
// Or
#synthesize object = _object; // With this, you refer to the ivar as _object
// Then somewhere else
_object = nil; // This refers to the ivar
object = nil; // Compile error, undeclared identifier
self.object = nil; // This refers to the setter
According to Cocoa coding guidelines, we should avoid using underscores in naming variables though. So personally, if I really need to access the ivar directly (for example, when you are overriding the setter), I prefer using ->.

Objective-C method to nullify object

i have some trouble writing a method in Objective-C to make an object nil. Here is some example :
#interface testA : NSObject
{
NSString *a;
}
#property (nonatomic, retain) NSString *a;
+(testA*)initWithA:(NSString *)aString;
-(void)displayA;
-(void)nillify;
#end
#implementation testA
#synthesize a;
+(testA*)initWithA:(NSString *)aString{
testA *tst=[[testA alloc] init];
tst.a=aString;
return [tst autorelease];
}
-(void)displayA{
NSLog(#"%#",self.a);
}
-(void)nillify{
self=nil;
}
- (void)dealloc {
[a release];
[super dealloc];
}
#end
int main(int argc, char **argv){
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
testA *test=[testA initWithA:#"some test"];
[test displayA];
test=nil;
//[test nillify];
NSLog(#"after setting to nil");
[test displayA];
[pool release];
return 0;
}
Apparently , when I set test object to nil and then call some method on it nothing happens , but if i call nillify instead of directly setting it to nil , displayA method works normally like test object is still there. Is there a workaround for nillify method to function properly ?
Your help is much appreciated !
You can't actually do something like this, because setting 'self' to nil only has any effect within the scope of that method (in your case, 'nilify'). You don't have any actual way to effect the values of pointers located on other parts of the stack or in random places in the heap, for example.
Basically any code that holds a reference to some object is responsible for maintaining and clearing those references itself. If you have some use case where random sections of code may need references to "live" objects of some kind, but where you'd want those object references to go away in response to some external event (maybe a user tracking system or something), you could do something with notifications, but the various modules tracking those "live" objects would still be responsible for listening for notifications and cleaning up references when they received them.
The 'nilify' thing, however, can't possibly work.
You cannot do what you're trying to do. self is just a local reference to an object that actually exists elsewhere. Setting it to nil doesn't mean anything. An object doesn't, in general, own itself, and it certainly doesn't control other objects' references to it. It's up to the owning objects to manage its lifetime.
There are a few things wrong with your code.
First, by convention, class names start with an uppercase letter. Please stick to these naming conventions as it will make it harder for other developers to work with your code (and even confuse you).
Next, your initWithName:... According to the naming conventions, a method with init in its name should be an instance method, not a class method. So either name it newWithName: or turn it into an instance method like this:
-(testA*)initWithA:(NSString *)aString{
self = [super init];
if (!self) return nil;
tst.a=aString;
return self;
}
If you keep it as class method (and name it newWithName:) you should not return a autoreleased object since according to the naming conventions method that start with init... or new... return a retained object. If you do not follow these conventions, the static analyzer will give you "false" warnings and it will become useless for you.
Now for the reason your nillify doesn't work: the self is in fact an argument to a method. Under the hood, your nillify method actually has two arguments that you do not see: the self pointer and the selector pointer. This means, self is actually a variable on the stack. And if you overwrite it, you only overwrite that stack variable but that doesn't influence your test variable which is somewhere else.
As an example, consider a method - (void)foo:(NSString *)bar;. The compiler turns it into the equivalent of the C function (void) foo(id self, SEL _cmd, NSString *bar).

#property retain - iPhone

I am newbie to iPhone programming. I have the following doubt which is stopping me to go ahead. Please consider the following code:
---------.h------
#interface myClass: UIViewController
{
UIImage *temp;
}
#property (nonatomic, retain) UIImage *temp;
---------.m------
#interface myClass
#synthesize temp;
-(void) dealloc
{
[temp release];
[super dealloc];
}
The above is the only program code. Thats it ... nothing else. Do I need to declare [temp release] in dealloc method even though I am not using the property accessor method in my program at all. What if I don't declare [temp release] in dealloc. Will that create memory leak as I am releasing something which I haven't retained as I am not calling property accessor method.
Also when i print retain count for temp why does it show 0 even though it is getting retained in #property.
Thanks in advance
If no value has ever been assigned to (an instance of) myClass.temp, then there won't be a leak. But you should release it in your dealloc.
#property is only a declaration that instance of myClass will have this property. You need to assign it a value before that value gets retained.
myClass *instance = [[myClass alloc] init];
// instance will now retain the value passed in
// and is therefore responsible for releasing it
instance.temp = [UIImage imageNamed:#"whatever"];
// if instance is not retained anywhere else,
// its dealloc will be called
[instance release];
On a sidenote, you should give your classes names that start with an uppercase
letter, i.e. MyClass. Not required, but makes things clearer.
You can also use self.temp = nil; in your dealloc You're sorta not supposed but it kinda works better and looks cleaner. It's a bit of an iffy subject...
What you are doing is correct. Scroll to the "dealloc" section of this Apple Doc: Declared Properties
Soon, however, these properties will be cleaned up automatically when you synthesize them (in the next Cocoa update) -- that being said, a convention I have personally began to follow so that my code works in the future is setting self.temp = nil; in dealloc instead of sending a release message (read the apple doc i posted, it explains this). The accessor method created at runtime releases the object first, so for me and quite a few other devs, this is a better/safer way of cleaning up declared properties in our dealloc.
Your code is correct.
The general rule is that, for all variables you declare in #interface, you must clean them up in -dealloc. Some variables will need to be released, others just need to be nil'd out, depending on how you've declared the #property.
In your example above, temp may never have been given a value explicitly by you, but the ObjC runtime will have initialized the value of temp to nil when an instance of your class gets allocated.
Sending a -release to a nil object is generally not a problem, so the [temp release] is fine. It's a no-op. When temp has a non-nil value in -dealloc, the [temp release] gets to do its job of freeing up the memory.
If you need temp to have a non-nil value on creation, you'll need to implement the -init method and make sure it gets some value. While your class is legitimate & functional without an -init method, you really should get in the habit including one in every custom class you design.
You'll need the default initializer at a minimum: -init. You may also want to design a more detailed initializer that could be used to give your temp ivar an a value, like -initWithImage:
Here's what you should also be including in your class:
#implementation MyClass
...
- (id) init {
self = [super init];
if (self != nil) {
// The minimal default initializer.
// temp will already have a value of nil, so you don't need necessarily
// need to do anything more, unless temp needs a real value on initialization.
}
return self;
}
- (void) dealloc {
...
}
#end
To implement a more detailed initializer, which would be known as the designated initializer, you would to something like this:
#implementation MyClass
...
- (id) initWithImage:(UIImage *)newImage {
self = [super init];
if (self != nil) {
temp = [newImage retain];
}
return self;
}
// Implement the default initializer using your more detailed initializer.
- (id) init {
// In this default initializer, every new instance comes with a temp image!
return [self initWithImage:[UIImage imageNamed:#"foobar"]];
}
- (void) dealloc {
...
}
#end
Here, the designated initializer -initWithImage: is the authoritative initializer. All other initializers, including -init, get implemented using -initWithImage:.
You get to exercise a lot of discretion over whether to implement any initializers beyond the minimal default initializer. Maybe -init is good enough for your purposes. That's fine. Sometimes more detailed initializers make using the class more convenient. Experience (and the Force) will be your guide.
Note that I didn't use the generated property accessor in either initializer method. If you aren't required by circumstances, you should generally avoid using property accessors in -init methods and -dealloc, primarily because of potential pain-in-the-ass issues with side effects of automatic key-value coding notifications.
The initializer and dealloc methods play a special role in a class. As the class designer, it is your responsibility to set and clean up instance variables in these methods. A good rule of thumb is to leave the use of synthesized property accessors for the callers of your class, and the implementation of other methods in the class.
When doing initialization of an instance, or deallocation, you can and should touch the ivars directly. They're yours. You declared them, so you can handle them directly. When implementing other methods in your class, you generally should use the property accessors.
JeremyP's link to the Cocoa Conceptual documentation on objects is a good one. You should definitely read the sections on Objects, and periodically re-read it as you gain more experience writing custom classes of your own. Eventually, it will all start making sense.

How should I handle a failure in an init: method in Objective-C?

Let's say I'm building a new class for the iPhone in Objective-C. In one of my init methods I want to manually allocate some memory. So, I might have something like this:
- (id)initWithSomeObject:(SomeObject *)someObject {
self = [super init];
if (self != nil) {
myObject = someObject;
[myObject retain];
if ( (memory = calloc(1, sizeof(SomeStruct)) == NULL) {
// What should I do here to clean up
[self release];
self = nil;
}
}
return self;
}
Now, assuming that the calloc() could fail, and that failing to allocate memory is catastrophic for my object, what should I do inside the if-body to clean up properly? Is there an Objective-C idiom or pattern that I should be using?
Edit: I included the code posted by Rob Napier. But, I still have to release myObject, right? Or does the added code somehow trigger dealloc()?
Yes, you should release yourself and then return nil.
[self release];
self = nil;
See Issues with Initializers in the Concepts in Objective-C Programming guide.
You need to clean up anything you need to and then set the self reference to nil. Apple Dev Portal has an article:
Link
I just tried. -dealloc gets called due to [self release], so myObject would not need to get released in initWithSomeObject. To be sure, you might move myObject = [someObject retain]; (I prefer that style in case -retain might fail for some reason) below the call that might fail (if that's possible).