Trying to Understand CFTree Documentation - ios

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.

Related

obejective c - Portential leak of an object stored into

I am trying to Run the code but its reporting the memory leaks when using static analyzer. on this line as Potential leak of an object stored into 'encodedData'
return encodedData;
use __bridge_transfer
Using __bridge_transfer ensures that ARC will release the object for you. Without __bridge_transfer, you must release the returned object manually.
__bridge,__bridge_transfer keywords are used to tell to ARC system how to handle your non-objective-c pointers. In essence, if you use __bridge, you are telling to ARC not to deal with the ownership of the converted pointer because you will free it from non-objective-c code, most likely with a free() or a CFRelease... type function. __bridge_transfer, on the other hand, transfers the ownership to ARC and ARC will free your objective-c (and thus also the original non-objective-c) object via the standard release mechanism when the references to that object hits zero.
Reference
The problem is that you create your string using CoreFoundation methods. And by default ARC doesn't know what to do with it. So, you're responsible for either manually managing the memory for the created object (using CFRelease for example), or handing it over to ARC.
The later is, I believe, the way to go in your case. You can do it, as others have already noted, using __bridge_transfer.

CGImageRelease in Swift

In Objc I use CGImageRelease method after the treatment of an image. But in Swift this method is not available.
On the Apple documentation after Retaining and Releasing Images there is a 2 Objective-C symbols hidden
My question is, why is there no more CGImageRelease in Swift ? And have we to call another method to replace it ?
Thanks !
CGImage is now managed by ARC. CGImageRelease() is no longer required on it. You can know this by looking in CGImage.h and noting that it includes the macro CF_IMPLICIT_BRIDGING_ENABLED. This indicates that Apple has audited this file to make sure it conforms to memory-management naming conventions so ARC can memory manage objects returned from functions in this file.
EDIT: I was reading over this and realized I was misleading. I don't mean to say that CGImageRelease isn't needed in ObjC (which is pretty much what I implied here…) I just mean that because of the auditing, Swift is able to handle it. In ObjC code, you still need to release these objects.
There is no more CGImageRelease in Swift, and there is no another method to replace it.
Swift uses ARC exclusively, so there’s no room for a call to CFRelease or __bridge_retained.
For types returned from C functions, we can call takeRetainedValue() / takeUnretainedValue() to get a Swift-managed value.
With the macro CF_IMPLICIT_BRIDGING_ENABLED, that turn on the Clang arc_cf_code_audited, Swift can handle the memory management for return value
For detail: https://nshipster.com/unmanaged/

Non-ARC to ARC: Pointer to a pointer to an object (**)

I am trying to convert an iOS project into ARC.
I am using the compiler flag for some of the files.
But one of the files contains a variable declared within a method like the following:
aClass **obj;
With ARC turned off, it gives an error:
"pointer to non-const type without explicit ownership"
I could silence the warning by doing this:
aClass *__strong* obj;
Which I believe is not a good practice as far as ownership is concerned.
But the error didn't exist in non-ARC environment.
My question is simply as follows:
How would I change from non-ARC to ARC setup the declaration of the object without having to use *__strong*?
i.e., how could I declare (or make changes to declaring) aClass **obj under ARC without have to use *__strong*, which I am sure I have read somewhere it is not a good practice to do but I forgot where I read it.
And:
Why didn't it give error under non-ARC environment.
TL;DR: You probably don't want a pointer to a pointer unless you can avoid it. It's pretty poor design to do so under a system where memory is managed for you. This answer explains more: Pointer to a pointer in objective-c?.
More Details
Under non-ARC, the system leaves retain/release up to you so it doesn't matter who owns a pointer. You, the programmer, owns it. In ARC land, the system needs to know when to retain or release, and it can't always infer which class/object has ownership over a particular object. Other classes may need the reference but the class that declared it is done with the object already. Basically, the __strong tells the declaring class that it should be in charge of managing the pointer. It 'overrides' the ownership of the pointer in a way. So that's a way to get around it. The best way to get around it would be to refactor the code to not use explicitly managed memory, but how you've fixed it will work if that's not possible/too hard.

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.

Releasing Singletons

I was wondering how you would release a singleton
+ (DSActivityView *)activityViewForView:(UIView *)addToView withLabel:(NSString *)labelText width:(NSUInteger)labelWidth;
{
// Not autoreleased, as it is basically a singleton:
return [[self alloc] initForView:addToView withLabel:labelText width:labelWidth];
}
When analysing this using the analyse tool i get the following error :
Potential leak of object on line 90. which is the line that returns.
I have tried autorelease that solves the error message problem but im not convinced its the right solution since i read that autoreleasing singletons is not good. Would someone be able to assist me in identifying how best to release this object?
Thanks
The reason why the analyzer gives you the warning is, basically, the method name:
+ (DSActivityView *)activityViewForView:(UIView *)addToView withLabel:(NSString *)labelText width:(NSUInteger)labelWidth;
according to Objective-C conventions, all method names starting with "create"/"new"/... return a retained object; your method falls under the category of convenience constructors, which are expected to return autoreleased objects, hence the warning.
On the other hand, you say this is a singleton, but in fact it is not. So, you could possibly end up calling this method more than once and thus have an actual leak. A basic way to make your method safer (and more singleton-like) is:
+ (DSActivityView *)activityViewForView:(UIView *)addToView withLabel:(NSString *)labelText width:(NSUInteger)labelWidth;
{
static DSActivityView* gDSActivityViewSingleton = nil;
if (!gDSActivityViewSingleton)
gDSActivityViewSingleton = [[self alloc] initForView:addToView withLabel:labelText width:labelWidth];
return gDSActivityViewSingleton;
}
This would both make the analyzer relax and give you more safety in front of the possibility of misuse of the method.
Use autorelease. There's no reason not to. Basically ownership of the object belongs to the object, so you're never going to be able to manually release it. As its a singleton it doesn't matter if you don't own it because presumably next time you call it and need it in scope you'll use another convenience method and it will get instantiated again.
If you want to have ownership of the object then you will need to instantiate it as normal and then you will be able to retain and release it.
Also, read sergio's edit about it not being a "proper" singleton. :p
Also, if you can, convert to ARC and you won't have to worry about this!
U are doing it wrong. Consider:
If you calling activityViewForView multiple times, you won't get get the same object over and over again. It only would initialize a new object and give you the pointer to it!!!
To make this thing a singleton, you have to store the created object in a constant variable and make sure, you have a reference to this object all the time your app is running (for instance declare your pointer to this object in appDelegate).
Then every time you call activityViewForView you have to check the constant variable if it is pointing to a valid object. If so, return the valid object, if not, create it and store it in your constant static variable (creation is done only once).
If you do use ARC you're all set. If not, release your object (use dealloc method)

Resources