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.
Related
I have the following code:
NSDictionary *dict = #{ #"myKey" : #"myValue" };
Should I release dict using release or autorelease?
Or I do not own the object, so I should not release it myself?
Note: I use manual reference counting (ARC is disabled).
No, you must not release a NSDictionary created with the literal syntax. The Clang documentation tells that dictionary literal expressions expand to +[NSDictionary dictionaryWithObjects:forKeys:count:], so you do not own the object.
No Objective-C literal expands to an expression creating an owning reference.
Even if you have ARC disabled (which you should have it enabled), you do not need to release it because you do not own the object. You only own the object when you created it through alloc or new.
I asked the question too early, sorry. But here's the answer:
I tried analyzing it myself, since I cannot find references (maybe because of the vague keyword #{}).
When adding autorelease to the dictionary created by #{ #"myKey" : #"myValue" }, the app crashes. I also ran the code through Xcode's Static Analyzer, and it gave a Memory issue.
So, we do not need to release objects retrieved using #{}, similar to NSString from #"".
I also tried it for NSArray using #[]. The same behavior applies.
We do not need to release them ourselves.
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.
I am trying to make a CFTree that holds strings as nodes. I am having trouble understanding the documentation for the class. Here is the link: https://developer.apple.com/library/mac/documentation/corefoundation/Reference/CFTreeRef/Reference/reference.html#//apple_ref/c/func/CFTreeSetContext
When you create a CFTree you call CFTreeCreate and pass in an allocator and a context. The allocator parameter I understand, but I don't understand the context argument.
Here are the fields you need to fill in in a context before you pass the context to CFTreeCreate:
version - this one I understand, I just make it version 0
info - Will I just set this to the NSString? Isn't that not OK because I need to use the __bridge or something? I'm kind of confused about this one
retain - Does ARC take care of retaining even though this is a Core Foundation class? I'm not sure what to put here
release - same as above
copyDescription - Not sure what the point of this field is or if I need it for what I'm trying to do.
Will I just set this to the NSString? Isn't that not OK because I need to use the __bridge or something?
If you want to do that, you'll have to do a non retaining bridging cast. Because NSString is toll free bridged with CFStringRef, in the tree, you can treat your NString as a CFStringRef and set the retain and release functions to CFRetain and CFRelease respectively - I think it should be OK, the prototypes look compatible.
Does ARC take care of retaining even though this is a Core Foundation class?
No, it doesn't, but if you set the retain and release functions as I suggested, you should be OK.
copyDescription - Not sure what the point of this field is or if I need it for what I'm trying to do
It just spits out a description, in the same way as -description does for a Cocoa object. You can leave it null, but if your info is an NSString something like this will do the trick:
CFStringRef* copyDescription(void* info)
{
return CFStringCreateCopy(someAllocator, (CFStringRef) info);
}
I haven't tried it, so it might not work.
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.
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.