Ok, I have read a lot of posts and resources about this but I am STILL having the same issue. I have a few NSString variables that I need to be class-wide variables used in multiple places throughout the class. I have tried many combinations of settings. First of all, I do have the strings declared in the interface like so:
#interface iCodeViewController : UIViewController <NSXMLParserDelegate> {
NSString *myString;
}
I have also added the property as follows (I have tried with and without the property and synthesizing)
#property (readwrite, retain) NSString *myString;
I have also tried, (nonatomic, retain), (nonatomic, copy), (readwrite, copy).
Then in the .m file:
#synthesize myString;
I have tried:
self.myString = #"whatever";
myString = #"whatever";
I have also tried with and without allocating memory to it by:
myString = [[NSString alloc] init];
What am I missing??
After I have 'supposedly' set the string variable in one method, I try to check it in another with if ([myString isEqualToString:#"blah blah"]) and when I put in a breakpoint and hover over myString it is always showing 'invalid summary.
Thanks!
use below
#property (nonatomic, retain) NSString *myString;
self.myString = [NSString stringWithString:#"whatever"];
for more read the SO post
Invalid Summary in NSString assignment
Can you place the class code here? The way you are handling your myString is perfectly fine.
One possibility I can think of is that you are forgetting to return self from the init method.
There could be other possible memory related mess some where in your code.
I was able to reproduce the invalid summary by initializing an NSMutableString to size 100 and only appending to it. I found the problem went away when I called
[mutableString setString:#""];
prior to
[mutableString appendString:string];
Related
How to copy NSString data to my custom object's NSString property?
I have an object question with NSString *text and KDoctor *doctor properties.
KDoctor is an object with two properties: NSString *name and UIImage *photo.
self.question.doctor.name=#"abc";
NSLog(#"doctorname: %#", question.doctor.name);
Output is:
doctorname: (null)
Why? How could I solve this problem?
my guess is that question.doctor != self.question.doctor
or
question == nil
or
question.doctor == nil
It seems you have something wrong declaring the properly. Are you defining "question" property like this?
In your header:
#class KonsQuestion
#interface YourClass : NSObject {
KonsQuestion * _question;
}
#property(nonatomic, retain) KonsQuestion * question;
In the implementation file:
#implementation YourClass
#synthesize question = _question
#end
In this case you should use always self.question to use the getter and setters generated and use [_question release] in the dealloc method
I have the following code in my .h file:
#interface Utils : NSObject {
NSString *dPath;
}
#property(nonatomic, retain) NSString *dPath;
And in my .m file:
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
dPath = [[documentPaths objectAtIndex:0] stringByAppendingPathComponent:kDatabaseName];
[dPath retain];
Why do I have to retain dPath if it's already defined as (nonatomic, retain)?
If I don't add the [dPath retain]; I get some strange, random errors and the application crashes when using this variable in other functions. I guess that's because of some autorelease somehere but I don't have any.
So, what is the (nonatomic, retain) doing anyway? Is it really necessary the [dPath retain]; or am I just hiding something else with that?
Because the code isn't calling the dPath property's setter method, it's just setting the instance variable dPath directly:
dPath = [[documentPaths objectAtIndex:0] stringByAppendingPathComponent:kDatabaseName];
[dPath retain];
So it has to be retained manually.
You will be able to (in fact you need to) omit the retain call if the property setter was used like this (notice the self.):
self.dPath = [[documentPaths objectAtIndex:0] stringByAppendingPathComponent:kDatabaseName];
or like this (notice the setDPath:):
[self setDPath:[[documentPaths objectAtIndex:0] stringByAppendingPathComponent:kDatabaseName]];
The setter retains the NSString for you so you don't have to do it yourself.
A nice little practice to follow in order to avoid the confusion, is to affix an underscore to your ivar name to indicate it's an ivar:
NSString *dPath_;
Then synthesize your property like this, to associate it with your differently-named ivar:
// self.dPath is the property, dPath_ is the ivar
#synthesize dPath = dPath_;
Then modify your dealloc method, as well as any other code that directly references the instance var, to use the affixed name instead:
- (void)dealloc {
[dPath_ release];
[super dealloc];
}
try setting and getting it with
self.dPath
If you want to call the property setter method, which will invoke the retain, then you want to write:
self.dPath = ...
Jamming stuff into a variable with:
dPath = ...
completely ignores the properties of this instance variable. Which is why you ended up needing to do the retain manually.
This is the code. It is pretty straight forward. I made two classes one is returning the error and hydrate the iVar of another class (TheView) and show it to the User. however I cant figure it out why the View return Null at all time. Thanks is advance guys.
#interface AccountControllerModel : NSObject {
NSString *anError;
}
#property (nonatomic, retain) NSString *anError;
AccountControllerModel.m
#synthesize anError;
- (void)uploadFailed:(ASIHTTPRequest *)theRequest{
RegistrationViewController *regoVC = [[RegistrationViewController alloc] init];
[regoVC manageTheError:#"THIS IS AN ERROR"];
[regoVC release]; regoVC = nil;
}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#interface RegistrationViewController : UIViewController {
NSMutableString *test;
}
#property (nonatomic, assign) NSMutableString *test;
#synthesize test;
-(void)viewDidLoad {
test = [[NSMutableString alloc] init];
}
-(void)manageTheError:(NSString *)theError{
self.test = [NSMutableString stringWithFormat:#"%#",theError];
resultOfRegistration.text = [NSString stringWithFormat:#"%#",self.test];
NSLog(#"test is %#",self.resultOfRegistration.text); //It comes back Null
}
Alex is right, some clarification on what's not working would help but by looking through I may have found your error. [[NSNotificationCenter defaultCenter] postNotificationName:#"Blah" object:self], you have object set to nil which could be your issue with the notification.
There are a number of problems with your code.
#property (nonatomic, assign) NSMutableString *test;
Two things here, one, exposing a NSMutable* object in a property is never a good idea, two you should 'copy' value objects, especially because this is how you're treating it in your code. Make this #property (nonatomic, copy) NSString *test;
regoVC.test = [NSMutableString stringWithString:self.anError];
You're assigning an autoreleased object to an assign property, this is a leak, the change above will fix that.
NSLog(#"test is %#",test); // It is perfect as you expect
test isn't in scope here, but I'd assume that was supposed to be regoVC.test, these other changes should remedy the situation.
I'm moving my initial steps in the Core Data realm (and I'm quite new to iPhone development, too) and I found a behavior I cannot explain.
I declared a subclass of a NSManagedObject and defined a few properties, some of them of type NSString *, MyObject.h is something like:
#interface MyObject : NSManagedObject {
}
#property (nonatomic, retain) NSString *contentFile;
#property (nonatomic, retain) NSString *contentPath;
#property (nonatomic, retain) NSDate *creationDate;
#property (nonatomic, retain) NSString *name;
#end
Now, if I try to create an object instance and assign a value to the name property, when I try to print back the content of the property it seems it's mangled.
In the AppDelegate, where the whole Core Data stack is defined, I write:
MyObject *newObject = [NSEntityDescription insertNewObjectForEntityForName:#"MyObject"
inManagedObjectContext:self.managedObjectContext];
newObject.name = #"Testing";
NSLog([NSString stringWithFormat:#"Name: %s\n", newObject.name]);
What I get in the output console is
2009-08-24 20:03:55.176 MyApp[15727:20b] Name: ‡}00»
I can't understand if I'm doing something wrong or if I forgot something. Anyone can help, please?
You need to use the %# format specifier in stringWithFormat:, since NSString is an Objective-C object:
NSLog([NSString stringWithFormat:#"Name: %#\n", newObject.name]);
%s is used for C-strings (char*s). For more info look at String Format Specifiers.
The correct format specifier for Objective-C objects is %#, not %s.
You should use %#, not %s. %s is for char* strings. You're passing in an objective-c object.
I have a table view that when loading creates a person object
Person.h
#import <UIKit/UIKit.h>
#import "TwitterHelper.h"
#interface Person : NSObject {
NSDictionary *userInfo;
NSURL *image;
NSString *userName;
NSString *displayName;
NSArray *updates;
}
/*
#property (retain) NSString *userName;
#property (retain) NSString *displayName;
#property (retain) NSDictionary *userInfo;
*/
#property (nonatomic, copy) NSURL *image;
#property (retain) NSArray *updates;
- (id)initWithUserName:userName;
#end
Person.m
#import "Person.h"
#implementation Person
/*
#synthesize userName;
#synthesize displayName;
#synthesize userInfo;
*/
#synthesize image;
#synthesize updates;
- (id)initWithUserName:(NSString *)user{
userName = user;
userInfo = [TwitterHelper fetchInfoForUsername:user];
displayName = [userInfo valueForKey:#"name"];
image = [NSURL URLWithString:[userInfo valueForKey:#"profile_image_url"]];
updates = [TwitterHelper fetchTimelineForUsername:userName];
return self;
}
- (void)dealloc
{
/*
[userName release];
[displayName release];
[updates release];
[userInfo release];
[image release];
*/
[super dealloc];
}
#end
Inside my UITableView method cellAtRowForIndexPath I am creating each person object and assigning the image property like so...
Person *person = [[Person alloc] initWithUserName:userName];
NSData *data = [[NSData alloc] initWithContentsOfURL:person.image];
[data release];
When I run this in Instruments it highlights the NSData *data... row saying that is where the leak is.
Why is it leaking there?
First, you need to understand the difference between instance variables and properties and getter/setters.
instance variables (ivars) are variables stored in
your object. You access an ivar from within a method simply by naming it (eg "userName").
properties define an
interface to your object, allowing
information to be read and/or written
to your object.
getters/setters implement that interface and may use an ivar as backing storage
You access a property by using a getter/setter, either explicitly (eg [self userName]) or (equivalently) using dot syntax self.userName. Note that these two notations are exactly identical. You declare a property (ie, you declare an interface to your object) using #property in the interface of your object, something like:
#property (copy) NSString* userName;
This declartion is essentially equivalent to typing:
- (NSString*) userName;
- (void) setUserName: (NSString*) theUserName;
You implement a property, either by using #synthesize (which simply tells the compiler to write the getter/setter for you) or by implementing it yourself (ie, you write methods implementation for userName and setUserName). There is also a rarely used third option, #dynamic, which tells the compiler you will handle the methods at run time, essentially just silincing the warning you would otherwise get.
Next, you need to read and understand the memory management rules. Its only 9 short paragraphs, go read it now, I'll wait. Done? good.
Further, you need to know that you should not use getters/setters in either the init or dealloc routines.
So your init routine should look something like this:
- (id)initWithUserName:(NSString *)user{
userName = [user copy];
userInfo = [[TwitterHelper fetchInfoForUsername:user] retain];
displayName = [[userInfo valueForKey:#"name"] copy];
image = [[NSURL URLWithString:[userInfo valueForKey:#"profile_image_url"]] copy];
updates = [[TwitterHelper fetchTimelineForUsername:userName] retain];
return self;
}
Note that you take ownership of each value you store in an ivar with retain or copy. Generally, you use copy for NSString to convert an NSMutableStrings into NSStrings you own, rather than retain which would leave you holding a reference to a possibly mutable string. The same issue applies to NSArray/NSDictionary, but we will assume TwitterHelper intends to hand off the fetched data.
Your dealloc will have to release the various ivars:
- (void)dealloc
{
[userName release];
[displayName release];
[updates release];
[userInfo release];
[image release];
[super dealloc];
}
Anywhere else in your code you would use self.userName to access or change the properties, rather than access the ivars directly.
Note that you might consider not storing the displayName (and similarly image) at all, but simply implement a property getter that retrieves it from userInfo. To do this, delete the displayName ivar, change the property to:
#property (readonly) NSString *displayName;
remove the #synthesize displayName, and add a manual getter:
- (NSString*) displayName
{
return [userInfo valueForKey:#"name"];
}
and remove the release in dealloc.
Note that you do not need to retain/release the value in displayName - you return a value that the receiver does not own and it is up to them to copy/retain it if they want to keep it.
If you choose to create a property, you should use:
self.image = [NSURL URLWithString:[userInfo valueForKey:#"profile_image_url"]];
in your init message and not
image = [NSURL URLWithString:[userInfo valueForKey:#"profile_image_url"]];
Setting the value without the self prefix will not call the copy or retain message, and will create a memory problem (not necessarily a leak).
This might be what Instruments is pointing you to.
(This obviously applies to all properties!)
Alternatively, if you don't want to use the accessor, then retain or copy the value retrieved, e.g.:
image = [[NSURL URLWithString:[userInfo valueForKey:#"profile_image_url"]] retain];
You are calling alloc on Person but not releasing it. You've leaked your person object.
(in your cell configuration)