CGImageRelease in Swift - ios

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/

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.

Typedef NSArray of type in Objective C

It has been a long time since I have worked in Objective C but now I am using it because I need to write something that will remain mostly source compatible for future versions. I want to create an init method that allows me to init my viewController with an array of my custom model object. In Swift I would do it like this:
typealias Stack = [StackBarTabItem]
…
func init(stacks:[Stack])
But how would I typedef an NSArray like that? I am pretty sure I can't do something like typedef NSArray<StackBarTabItem> Stack; so what is the syntax in objective c?
Until iOS 9 and Xcode 7, this isn't officially supported. One way to do this is to subclass NSArray or NSMutableArray and enforce typing in your subclass, but this isn't really recommended. One way to deal with the fact that NSArray can only hold ids is to use respondsToSelector before calling a method on any of the objects in the array.
This solution isn't really a substitute for a good typing system, but it's a common practice to get around this limitation. Thankfully, generic support is getting added soon!
Objective-C is dynamically typed. You simply do not check for it.
Asking the audience on talks and in internet fora, the real danger that code will be shipped with a typing bug is minimal and by far lower than other sources of errors. Simply do not care about this.
Ask yourself: How could that happen without getting a runtime error at the very beginning of your next program run?

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.

Trying to Understand CFTree Documentation

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.

ARC in iOS questions

~ Will ARC always release an object the line after the last strong pointer is removed? Or is it undetermined and at some unspecified point in the future it will be released? Similarly, assuming that you don't change anything with your program, will ARC always be the same each time you run and compile your program?
~ How do you deal with handing an object off to other classes? For example, suppose we are creating a Cake object in a Bakery class. This process would probably take a long time and involve many different methods, so it may be reasonable for us to put the cake in a strong property. Now suppose we want to hand this cake object off to a customer. The customer would also probably want to have a strong pointer to it. Is this ok? Having two classes with strong pointers to the same object? Or should we nil out the Bakery's pointer as soon as we hand off?
Your code should be structured so the answer to this doesn't matter - if you want to use an object, keep a pointer to it, don't rely on ARC side effects to keep it around :) And these side effects might change with different compilers.
Two strong pointers is absolutely fine. ARC will only release the object when both pointers are pointing to something else (or nothing!)
ARC will implement the proper retains and releases at compile time. It will not behave any different than if you put them in there yourself so it will always do the same compilation and to answer your question should always behave the same. But that said it does not mean that your object will always be released immediately after the pointer is removed. Because you never call dealloc directly in any form of objective C you are only telling it that there is no reference count and that it is safe to release. This usually means that it will be released right away though.
If you pass an object from one class to another and the receiving class has a strong property associated with it and the class that passes it off eventually nils its pointer it will still have a reference count of at least 1 and will be fine.
Ok, first this answer might helpt you also a little bit: ARC equivalent of autorelease?
Generally after the last strong variable is nilled, the object is released immediately. If you store it in a property, you can nil the property, assign it to something like __strong Foo *temp = self.bar; before you nil, and return that local __strong variable (although arc normally detects the return, and inferes the __strong byitself).
Some more details on that: Handling Pointer-to-Pointer Ownership Issues in ARC
DeanWombourne's answer is correct; but to add to (1).
In particular, the compiler may significantly re-order statements as a part of optimization. While method calls will always occur in the order written in code (because any method call may have side effects), any atomic expression may be re-ordered by the compiler as long as that re-order doesn't impact behavior. Same thing goes for local variable re-use, etc...
Thus, the ARC compiler will guarantee that a pointer is valid for as long as it is needed, no more. But there is no guarantee when the pointed to object might be released other than that it isn't going to happen beyond the scope of declaration. There is also no guarantee that object A is released before B simply because A is declared and last used before B.
IN other words, as long as you write your code without relying on side effects and race conditions, it should all just work.
Please keep you code proper as it has diffrent behaviour on diffrent complier.

Resources