In ios will NSString = NSString cause memory leaks? - ios

I've seen some answers but those didn't expand enough and I think they were before ARC was introduced.
So if I have two NSSstring can I set
string1 =string2;
or
NSString * a1=#"String";
al=#"Lead";
without causing memory leaks or other problems?
Edit: What about view controller or delegate properties set to (copy, nonatomic)?
Edit2: It should be NSString *al=#"String". I hope this doesn't change the idea that it doesn't leak.

No, assigning and re-assigning string literals will not cause a memory leak. You only need to worry about memory leaks when not using ARC and assigning something that uses alloc, retain, copy, mutableCopy or a method prefixed with new.
NSString a1=[#"String" mutableCopy];
al=#"Lead";//This will cause a leak since you called copy above.
See the Advance Memory Management Rules for details.

neither would leak in ARC.
however, you might want to be aware that you are dealing with a reference in this case -- no implicit copy is performed (unless you use a copy or copy-qualified property).
Edit: What about view controller or delegate properties set to (copy, nonatomic)?
for NSStrings? yes, copy should be the default for NSStrings. nonatomic should be the default for everything. of course, there are exceptions to this -- when you might deviate from the defaults.

Your code is safe and will not leak. Cocoa and NSStrings are quite smart about how they deal with these issues.
You can end up with other interesting things happening because NSStrings are immutable, and you can get weirdness if you try to worry about the pointers themselves. But your examples don't suffer from these issues.

Related

How to fix iOS memory leak from _NSCFNumber?

This is my code where I reloads particular sections of _collectionView. When I check memory leaks using Leaks template in Xcode 6.3 Instruments, it shows leak on line
[_collectionView reloadSections:indexToLoad];
and _NSCFNumber as a leaked object.
Here is my code:
NSMutableIndexSet* indexToLoad = [NSMutableIndexSet new];
for (NSInteger index in array) {
if (index != NSNotFound) {
[indexToLoad addIndex:index];
}
}
if (indexToLoad.count > 0) {
[_collectionView reloadSections:indexToLoad];
}
As I read somewhere, "the leaks instrument shows you where a leak was allocated but doesn't show you the line of code that caused the leak", how can I found a cause of leak? Also how to fix this leak?
NOTE: ARC is enabled for class in which this code is running(whole project is ARC enabled). Also this code is running on main thread.
Thanks for answers in advance :)
I notice that you are iterating an array and casing its contents to NSInteger. As you can't add NSInteger to an Objective-C array I'm going to assume that that's an array of NSNumber's which just happens to be the class which is leaking.
When you add an object (e.g. NSNumber) to a collection (i.e. NSArray, NSSet e.t.c) the collection creates a STRONG reference to that object. That means that when that NSNumber falls out of scope ARC or a garbage collector won't come along and release it. This can cause some problems however, one being retain cycles.
What I suspect is happening (I can't be sure without actually testing your full code) is that when the NSMutableIndexSet falls out of scope ARC comes along and tries to release all the NSNumber objects that it contains but finds it cannot as they are still retained by the array. If not then somewhere in code you are hanging on to one or more NSNumber instances and ARC doesn't like it.
Solution:
ARC is not a panacea when it comes to memory management. It makes memory management much more friendly and because of that people tend to assume that they can write any code they like and ARC will take care of the rest. You still need to be aware of your references (strong vs weak) and when to use each one. Also make sure you know what the default state is; for example #property NSNumber *num; is the equivalent of #property (nonatomic, strong) NSNumber *num;

Is this NSString a memory leak?

NSString *pDescText = #"blablabla";
pDescText = [NSString stringWithFormat:#"%# %#",skProduct.localizedDescription,formattedPrice];
Does this produce a memory leak when I reassign pDescText in line 2?
If you are using ARC, you don't need to worry about these kinds of leaks.
If you are using MRC, you don't have a leak because:
You only need to release objects that you have a received a reference to by sending messages which contain new alloc retain or copy. In neither of these lines have you done this so you don't have an owned reference to pDescText. Furthermore, in the first line you are using a string literal, which is something that yo don't have to worry about memory management for.
And I have to say this pDescText is not a good name to use for a variable in Cocoa. We don't use hungarian notation (so the p to indicate a pointer isn't needed) and full, descriptive variable names are the norm. So instead of pDescText a more experienced Cocoa developer would use descriptiveText or even productDescription or description if that is enough for the context.
No, NSString convenience constructors return an autoreleased object.

CFStringRef to NSString ARC leaking. Why?

I have been looking around for the correct way to go from CFStringRef to NSString in ARC to avoid memory leaks and some of the main voted answers suggest:
NSString * string = (__bridge NSString *)cfString;
I am using that approach here but when profiling the app I still get a memory leak in this small method [see attached image].
So, I am not sure how to fix this. Anybody has the solution to this problem?
Thank you
So, apparently adding the CFRelease(ext) before the return fixed the leak. Problem is I don't think I fully understand the reason. I thought that the line:
NSString * extension = (__bridge NSString*)ext
Would take ownership of the Core Foundation ext string and handle the release.
Can anybody explain what is going on here exactly?
As per the de-facto "standard" Cocoa naming convention, functions that contain Create or Copy in their name return an object with a reference count of 1. You have to transfer this reference count into ARC-land so that ARC can take care of it. You use the __bridge_transfer keyword for this purpose.
NSString *string = (__bridge_transfer NSString *)cfString;
Release the ext object or use __bridge_transfer.
Let me explain this a bit in the way I understand it:
__bridge – Normal casting. The retain count of casted object is partially managed by ARC and partially manually. You need to release the existing ownership on the CF side.
__bridge_transfer – “Converts CF object to NS object.” The retain count of casted object is fully managed by ARC. Existing ownership on the CF side is disposed for you.

Guarantee a deallocation in ARC

I'm currently developing a game for iOS and we have a memory leak. Our project is ARC set up. I was wondering on how to ensure memory deallocation. One of the steps I was thinking of taking was convert code of the form:
-(void)methodMethod{
Object* o = [[Object alloc] init];
// Some logic
}
into:
-(void)methodMethod{
Object* o = [[Object alloc] init];
// Some logic
o = nil; // Explicit nil assignment
}
Is there a difference between the two? What other measures should I take to ensure a dealloc in an ARC setup?
We're using the Sparrow Framework.
Both methods do the same thing. Local objects are set to nil by ARC when they leave scope, so putting in a manual nil does nothing.
If you want to find a leak - you are far better off actually running it through Instruments with the Leaks tool and finding out what is being leaked, which will give you a better idea of what is going on. It's quite handy for finding retain-cycles.
As pointed out by Abizem, both methods lead to the same results, and require careful passes through Instruments. The results are not always easy to interpret.
In ARC, you should never see a leak - in the usual obj-C meaning -. Sometimes, iOS instruments can report a leak, but most if not all, this comes from the runtime, and I tend to regard them as beyond my control. What you can see however, is uncontrolled memory increase, which is typical of memory retention. Keeping strong pointers on objects is the obvious reason, which in my case has always been the consequence of : retain cycles in code blocks, and incorrect data structure cleanup, i.e. objects are created, then filled into arrays, dictionary, page control etc... but the later were not emptied properly during the app lifecycle.
Also image processing functions still use standard malloc/free directives embedded into internals UIGraphics lib, so in that case you explicitly need to free the memory (CGImageRelease, etc...). ARC will not help here.
hope this helps narrow down the problem, which as Abizem pointed out, should start with Instruments.
the following is unnecessary but (at least for me) the discussion in the comments was helpful and that's why I leave it
wrap the method in an #autoreleasepool. that will make it 99% percent sure it is being deallocated
-(void)methodMethod{
#autoreleasepool {
Object* o = [[Object alloc] init];
// Some logic
}
}
Both are the same.
A better solution to test your class:
- (void)testDealloc
{
__weak CLASS *weakReference;
#autoreleasepool {
CLASS *reference = [[CLASS alloc] init]; // or similar instance creator.
weakReference = reference;
// Test your magic here.
[...]
}
// At this point the everything is working fine, the weak reference must be nil.
XCTAssertNil(weakReference);
}
This works creating an instance to the class we want to deallocate inside #autorealase, that will be released (if we are not leaking) as soon as we exit the block. weakReference will hold the reference to the instance without retaining it, that will be set to nil.

Why setting value with "self" cause memory leak?

I need to understand why in this code i get a memory leak if i assign value to ws_data variable using self.ws_data and not if i use only ws_data.
self.ws_data is a #property (copy)NSString *, released on dealloc.
dispatch_queue_t ws_queue = dispatch_queue_create("ws check win", NULL);
dispatch_async(ws_queue, ^{
self.ws_data = [[NSString alloc]initWithContentsOfURL:url];
});
dispatch_release(ws_queue);
Thank you!
self.variableName accesses the variable through its accessors. Because your ws_data NSString is set to copy in its property declaration, the string is retained when you set it through that declaration.
Not using self. references the ivar without going through those accessors. It also means the variable isn't copied, so it will vanish when references to it disappear (like at the end of your method).
Odds are you want the copy. You just need to release it when you're done, as you do in your dealloc.
Are you retaining it somewhere else, making this access a second retention?
If I understand things correctly (and I quite possibly don't as I've not be doing iOS development for very long at all) in this instance, as you're using the copy attribute on the property, what you're doing when you use self.ws_data is effectively calling the copy method on an already alloced NSString, which is creating a separate instance of the NSString with a retain count of one.
However, the original NSString (that's being alloced in your above sample) isn't being released at any point, hence the leak.
You could use...
self.ws_data = [[[NSString alloc]initWithContentsOfURL:url] autorelease];
...instead, I'd have thought.

Resources