I'm new to objective-c and I always have problem with global variable . I don't know where to initialize them . My problem is with an NSString . I wrote this code –
in .h
NSString *session ; // i also #property(retain,nonatomic) and synthesize ...
in viewDidLoad , '
session=#"HEllo";
and in
-(IBAction) showInformations:(id)sender;
{
NSLog(#" informations ok");
NSLog(#"my sesison : %# ",session);
}
But I have a crash in show information :/ session is empty I think . Help please
session = #"hello";
self.session = #"hello";
There is a huge difference between the above two statements. The first one just assigns hello to session. Here the string hello is autoreleased, so session is not valid when you tap the button, as you have not retained session. But in 2nd line self is used. When self is used, it is not just a simple assignment, it is actually a call to accessor method. Here you have used retain in property declaration. So when self is used, the setter for session is called which retains it. So session is valid when you tap the button.
The summery is use right property and use self to avoid many memory problems.
EDIT: As pointed by fluchtpunkt, this explanation is not valid for string literals. I was out of my mind that string literals are special when writing this.
Try setting it using the dot syntax for a property:
self.session=#“Hello”;
This will ensure proper memory management.
There must be another write access to session somewhere in your code. A line of code that looks like session = [NSString stringWith...];
So find the other parts of the code where you assign something to the session variable and replace the wrong memory management over there with proper memory management. The problem is not within the three lines you have shown.
Depending on your code it should be something like
self.session = [NSString stringWith...
or if you like it inconvenient
[session release];
session = [[NSString stringWith...] retain];
Related
This may sound a newbie question however I'm new to iOS dev.
I've following code in my project, the project is ARC enabled, and I get error on its execution (bad access), and would like to understand the cause of the problem and solve it.
on some button press following code is invoked in MTClassA.m file
-(void) someMethod
{
for (int i = 0; i < N; i++) {
...
(param1 and param2 are location variables)
...
mFlickr = [[MTFlickr alloc] initWithParam1:param1 param2:mparam2];
mFlickr.delegate = self;
[mFlickr fetchImages];
}
}
in MTClassA.h header file mFlickr is declared as MTFlickr* mFlickr so default it it with __strong qualifier.
the callback function of fetchImages class is following
- (void)didRecieveImageLinksFromFlickr:(NSArray*)response
param1:(NSString*)param1 param2:(NSString*)param2 {
...
}
So basically I would like to know is it correct to create mFlickr objects this way in for loop and expect the callback to work correctly, if no please suggest what need to be changed ?
P.S. Do I need to change mFlickr to local variable ? If yes how should I be guaranteed that param1 and param2 methods are the one's that I've passed for teach iteration in for loop ?
You are creating multiple instances of the mFlickr object within your loop, and presumably assigning them to the same instance variable. Under ARC an assignment to an instance variable will automatically release the previous value, so your mFlickr objects are getting destroyed as soon as they are created (except the last one).
Presumably your mFlickr object is setting itself as a delegate for a URL request, it is probably this callback which is failing since the request's delegate no longer exists.
If you are creating multiple instances you should store them in an array instance variable. The callback should include a reference to the particular instance that has returned, and at this point, you remove it from the array.
You don't need to change the mFLicker to local variable. The only thing that i found in your code wrong is that, you are immediately setting mFlicker to self after initializing it. i think you must want to set the delegate of the mFlicker that you can do it by
[mFlicker setDelegate:self]
Did you set #property for mFlicker?
.h
#property(nonatomic, retain) MTFlickr *mflicker;
.m
#synthesis mflicker;
I also had similar experience, ARC was releasing my object after initialization.
so try changing your code to
self.mFlickr = [[MTFlickr alloc] initWithParam1:param1 param2:mparam2];
mFlickr.delegate = self;
[mFlickr fetchImages];
I am also not sure but i just wanted to provide some help
What is the proper syntax for accessing an instance variable in Objective-C?
Assume we have this variable:
#interface thisInterface : UIViewController {
NSMutableString *aString;
}
#property (nonatomic, retain) NSMutableString *aString;
and that it is synthesized.
When we want to access it, we first would want to allocate and initialize it. Having programmed in Objective-C for about a month now, I've seen two different forms of syntax. I've seen people do simply aString = [[NSMutableString alloc] initWithString:#"hi"], where they allocate the string like that; I've also seen people start it off with self.aString and then they proceed to initialize their ivar. I guess I'm just trying to figure out what is the most proper way of initializing an instance variable, because with the former example, I have received EXC_BAD_ACCESS errors from it. After prepending the self. though, it didn't appear.
Forgive me if this is a duplicate question, but after reading some posts on SO, it's made me curious. I'm trying to learn the proper syntax with Objective-C because I prefer being proper rather than sloppy.
If you have declared a property and #synthesize it in the .m file, you simply set it like this:
self.aString = #"hi"; // or [[NSMutableString alloc] initWithString:#"hi"];
Using self.varName takes advantage of what your property declaration actually does- it handles retention of the new value (since your property has the retain attribute), releasing the old value, etc for you.
If you just do:
aString = someValue;
... you may be leaking the original value that was in aString, since without using self.aString you are accessing the variable directly vs through the property.
Note the difference between self->varName and self.varName
The first is pointer access. The second is property access.
Why is that important? Pointer access is direct. Property access, on the other hand makes use of getters and setters (be they #synthesized or not). Moreover, as a convenience, the #synthesized accessors take care of the memory mangement for you (i.e. when using self.varName = ...;), whereas varName = ...; does only what it says, i.e. the assignment -> (there lies the explanation for EXC_BAD_ACCESS errors you might be getting).
Syntactically, both forms are correct. If you want to better communicate intent, use self->varName when you want to work directly with the pointer and use self.varName when you want to take advantage of the #property convenience.
Here are all the possible combinations (I think)
OKs and BADs are only correct when aString property has retain attribute:
#property (nonatomic, retain) NSMutableString *aString;
So:
1
aString = [[NSMutableString alloc] init]; //OK:
This is OK but only in the case aString is not pointing to an invalid object or you will loose a reference to that object and it will leak because you won't be able to reach it to release it.
2
aString = [NSMutableString string]; //BAD
Bad because you are suppose to retain aString (as you declared it that way), you are not retaining it and you will get surely get EXC_BAD_ACCESS in the future
3
aString = [[NSMutableString string] retain]; //OK
Same as the first approach, only good if aString is not pointing to a valid object. However I will use the first though.
4
aString = [[[NSMutableString alloc] init] autorelease];//BAD
Same as the second approach.
5
self.aString = [[NSMutableString alloc] init]; //BAD!!
Bad because you are retaining it twice, hence it will lead to memory leaks
6
self.aString = [[NSMutableString string]; //******GOOD!******
This is probably the safest. It will be retained by the property setter and since you are using the setter any other object that could have been pointed by aString will be released appropriately
7
self.aString = [[NSMutableString string] retain]; //BAD
This is retained twice.
8
self.aString = [[[NSMutableString alloc] init] autorelease];//Ok
This is also OK, but I would use the convenience method instead of this long approach :)
Be wary that the #1 and #3 options are perfectly good if you know what you are doing. In fact I use them much more frequently than #6
I personally prefer to use the self. syntax. It just makes it easier to determine that its an instance variable, and not just some other variable in the current scope that will be lost when its NSAutoreleasePool is drained. However, it is correct to use them both ways, and if you are receiving EXC_BAD_ACCESS errors, it is not because you accessed it without using self.. You are correct in saying that you must alloc it, and whichever way you choose to access your variables, keep it consistent or you will receive errors.
I hope this helps.
Always use accessors except in init, dealloc and in accessors themselves. Doing this will save you a lot of headaches like the one you're describing. Also, name your ivars something different than your property (_foo, foo_, mFoo, but not foo).
self.foo is precisely the same as [self foo]. I calls the method foo. self.foo = x is precisely the same a [self setFoo:x]. It calls the method setFoo:. If you synthesized the property foo as a retain variable, then this looks something like:
#synthesize foo = foo_;
- (void)setFoo:(id)value {
[value retain];
[foo_ release];
foo_ = value;
}
This correctly releases the old value of foo_, assigns a new one and retains it.
foo = x (assuming foo is an ivar) does not call any method. None. It just assigns the value of the pointer in x to the pointer in foo. If foo pointed to something that was retained, it's leaked. If the new value you're assigning isn't retained, you'll crash later.
The solution to this is to always use accessors when you can.
Either.
Using the dot syntax is cleaner (to some) and it compiles to the equivalent. i.e self.iVar is the same as [self iVar] and self.iVar = aValue is the same as [self setIVar:aValue];
self.aString is a syntactic sugar to [self aString]. Synthesize a property just create the -aString and -setAString: method (depending on the property you have chosen it while not be the trivial affectation).
Now the question is whether to use the . notation. I suggest you not to use it.
Why? First know that Objective-C aim to be just an addition to C. This mean that every valid C code is also a valid Objective-C code.
Now look at what they have done with the dot notation. The last statement does not hold anymore. You wont distinguish between an access to a field of a C structure and sending objective-c method.
So please don't use the dot notation. Prefer using the [self ..].
I have a NSMutableString var, which I have also synthesized.
This gets set in viewDidLoad
NSLog(#"Var val is %##",curr_rep_date);
I have a button on which i call an IBAction and am trying to access the var value inside this method.
-(IBAction) moreDetails{
NSLog(#"INSIDE IBACTION var val is %#",curr_rep_date);
}
But for some reason, the app crashes (Program received signal: “EXC_BAD_ACCESS”.)
Please help me fix the issue,
are you sure you either use the setter (which hopefully retains the object) when you create the object or create a not autoreleased object?
choose one.
self.curr_rep_date = [NSMutableString string];
curr_rep_date = [[NSMutableString alloc] init];
You're probably storing an object you don't own in an instance variable, so when you try to get at it again later, it's gone because it didn't know you needed it.
The memory management guide offers a simple set of rules you need to follow to get this right.
I am trying to understand how to use blocks on iOS. I have read Apple's docs but, as usual, they are vague and incomplete and several essential bits of information are not mentioned. I have also googled around without success. This is what I am trying to do as an exercise to understand that.
I have created a block to read a string and compare the string to the previous read. If the strings are not the same, return YES, if they are the same, return NO.
This is how I did:
I declared this on .h
BOOL (^differentStrings)(void);
I declared this on .m, inside viewDidLoad in a viewController
__block NSString * previousString;
__block NSString * currentString;
differentStrings = ^(void){
currentString = [self getString];
NSLog(#"%#", currentString); // not printing anything on console
if (![currentString isEqualToString:previousString]) {
previousString = currentString;
return YES;
} else {
return NO;
}
};
This is how I use: I have a thread that does this:
if (differentStrings)
NSLog (#"strings are different);
These are the problems I have:
the block always return YES (strings are different)
I am not comfortable declaring this inside videDidLoad. How should I declare this, so I can use it globally as a method? Should I put this like I would with a method?
I am calling a method "getString" inside the block. Is it OK?
I find strange to declare the block variables on .m. As I see, I should declare the block variables on .h and then just use them on .m. I have tried to do that, but received an error.
I have setup a debugging point on the first line of the block but it is not stopping there;
NSlog line inside the block do not prints anything. Isn't the block being called?
Can you guys help me with this?
You're misunderstanding how blocks work. (Okay, so that's kinda obvious.) In the same way that previousString is a variable pointing to an NSString, differentStrings is a variable pointing to a block. Not the result of running the block, but rather, the block itself. That is, after you do this:
__block NSString * previousString;
__block NSString * currentString;
differentStrings = ^(void){
currentString = [self getString];
NSLog(#"%#", currentString); // not printing anything on console
if (![currentString isEqualToString:previousString]) {
previousString = currentString;
return YES;
} else {
return NO;
}
};
differentStrings is a variable pointing to the block.Thus, when you do this:
if (differentStrings)
…you're simply checking whether differentStrings contains something other than 0 or NULL. Since it contains a block, it is not empty, so it evaluates to true.
Remember: differentStrings is a block variable, not a BOOL variable. It contains a block (a function, if you will), which when called will return a bool. Thus, in order to actually run the block, you need to call it. Like this:
differentStrings();
or, in your case:
if (differentStrings()) {
NSLog (#"strings are different");
}
Edit: As pointed out in the comments, since differentStrings is an instance variable, you need to copy it, just like you'd call retain on any other object assigned to an instance variable. (For technical reasons I won't go into now, you should always use copy with blocks instead of retain.) Likewise, you'll need to call release on it at some point later, perhaps in your dealloc method.
I don't believe you're actually executing the block. I think your code should be
if (differentStrings())
{
NSLog (#"strings are different);
}
Treat a block like a function. I think you were just checking to see whether the block had been defined, not executing it.
Also, if you don't need to access an NSString outside of the block, you could get rid of the __block qualifier and move the currentString declaration inside of the block.
If you need another resource on blocks, I cover them in the fall session of my advanced iOS development course on iTunes U. I describe block syntax in the Understanding Cocoa session, and their use in Grand Central Dispatch within the multithreading session. The course notes also have links to some sample applications that use blocks in different ways.
I also can't recommend highly enough that you watch the WWDC 2010 video sessions 206 - Introducing Blocks and Grand Central Dispatch on iPhone and 211 - Simplifying iPhone App Development with Grand Central Dispatch.
Does anyone know if the following code could be problematic:
NSString *addchar = nil;
if (case1)
addChar = [[firstname substringToIndex:1] capitalizedString];
else
addChar = [[fullname substringToIndex:1] capitalizedString];
Assume that firstname and fullname aren't null or empty. Does initializing the NSString object and setting it to 'nil' cause some possible problem? It seems to cause my app to freeze, but only for a very few users, and only those users, but it doesn't have anything to do with different input strings or empty strings. So I'm trying to isolate the problem, but I don't know the difference between
NSString *addChar;
and
NSString *addChar = nil;
Thanks.
Either form is perfectly acceptable. The problem you're having is elsewhere. I recommend doing some code profiling with Instruments to figure out where this issue is occurring.
Without the nil initializer, in some cases your variable may be initialized with garbage (whatever was in the memory space previously). There are specific rules regarding which types of variables (scope-based, static storage, etc.) are nil-initialized automatically for you, but I've always found that it's easier to explicitly initialize all variables instead of memorizing those rules.
That said, because both branches of your if statement clobber any previous value of addChar, there should not be any case in which you can see an invalid value. But it's certainly not hurting anything to explicitly initialize to nil, and if a future maintainer comes along and changes the code paths you might find that the initializer saves you!
You should always initialize to nil if variable is not initialized otherwise.
You can send messages to nil they will be ignored.
NSString * str = nil;
NSLog(#"%#", [str description]);
Outputs:
2009-12-15 08:59:03.352 x[11775] (nil)
Of course I don't need to call description explicitly, I'm just demonstrating call to nil.
There is no difference here since you don't read addChar in your code. Moreover, the compiler may sometimes initialize addChar to nil for you if you don't do it explicitly (depending on the scope of addChar's declaration).
See related question at this place.
From now on, when you use ARC, the strong, weak, and autoreleasing stack variables are initialized to nil:
https://developer.apple.com/library/ios/releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html#//apple_ref/doc/uid/TP40011226-CH1-SW5
Additionally, since dawn of times, in ObjC the instance variables are initialized to zero:
Are instance variables set to nil by default in Objective-C?