views:

107

answers:

1

Hi guys, I have this very strange problem, I'm new to objective-c and it probably comes from depths which I don't comprehend yet.

So, in my header file I declare the variable

NSString *curTitle;

then in .m file I synthesize it:

curTitle = [[NSString alloc] init];

after that in other method I assign it:

curTitle = string; // string is an instance of NSString

and at the end of the day when I'm trying to assign

slide.title = curTitle; //slide is a managed object (CoreData)

I'm getting this error: * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Unacceptable type of value for attribute: property = "title"; desired type = NSString; given type = __NSCFDictionary; value = { }.'

Interesting fact that in iphone SDK 3.2 it worked, but after I installed SDK 4 I have this error

Another interesting fact that if make my curTitle property of my class (with @property and @synthesize) it also works

Any ideas? Thanks

+2  A: 

When an object seems to change class, it's almost always because it has been deallocated, and another object is now residing on the same memory location. All object variables are actually pointers to memory locations (that's what the * means), and unlike in many other languages you have to always remember that you're working with memory locations. (Well, not always, once you get the hang of it. But definitely when you're debugging.)

To debug these problems, it can be very useful to use NSZombie. Just search SO or the web for info.

then in .m file I synthesize it: curTitle = [[NSString alloc] init];

This is not synthesizing. What you are doing here is merely assigning a value to the variable. More precisely, you create an object somewhere in memory (alloc) and initialize it (init) and then you set the value of curTitle to point to that memory location.

There is no need for you to have this line in your code at all.

curTitle = string;

Here you are overwriting the old value of curTitle with a pointer to another string. Your problem is most likely that that other string later gets deallocated, and the memory location gets reused to hold another object (a dictionary in this case). (If you don't know about the retain/release mechanisms, you need to read up on those to understand what happens.)

slide.title = curTitle;

Since curTitle is pointing to a memory location that has been re-used to hold a random object (or even worse: garbage) this line will fail. In fact, you're lucky that it fails, because if it didn't (if the location hadn't been reused yet) it would be even harder to detect the bug.

What you should do is to declare a property, then synthesize it and access the variable through the property:

self.curTitle = aString;

This will make sure that you actually copy and take ownership of the string so that even if the original string is released, you will still have a valid copy.

Felixyz
Thank you Felixyz a lot for this answerYou are right, my 'string' variable was deallocated, so I solved it changing curTitle = string;with curTitle = [string copy];can you please explain me or give some reference when I should use property, and when I should not?Thanks indeed, your help appreciated))
Burjua
@Aristarh: curTitle = [string copy]; The problem is, now you have a retained copy of the string, and if you don't release it later, you will have a memory leak. That's why it's crucial to understand the memory handling rules: http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmObjectOwnership.htmlThere's lots of information on SO:http://stackoverflow.com/questions/3266467/what-exactly-does-synthesize-do/3269636#3269636http://stackoverflow.com/questions/2423990/memory-management-in-objective-c/
Felixyz
Yes, I understand this, but I understand that property also need to be released in class dealloc method, so I can't understand the difference of this aproaches, sorry((
Burjua
If you're releasing it in the dealloc, all is fine. However, you must also release it if you ever overwrite the value with a new one (you must then release the old one and copy the new one). To make this easier, it's good to create a setter method, that you use every time you want to set a new value. That method takes care of releasing the old and retaining/copying the new value. And that's one of the things synthesized properties do for you!
Felixyz
Ok, thank you for your help, now it's clearer)))
Burjua