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.
Related
According to Using Swift with Cocoa and Objective-C you can use takeUnretainedValue() and takeRetainedValue()to tell Swift how to manage the memory of an object for a function like this:
func StringByAddingTwoStrings(CFString!, CFString!) -> Unmanaged<CFString>!
When do I have to use takeUnretainedValue() or takeRetainedValue()?
When I use ARC is it then always takeUnretainedValue()?
You use takeRetainedValue when the unmanaged object has a +1 retain count and you want ARC to take care of releasing the object when you're done. For example, if you call a Core Foundation function with Create or Copy in the name (see Create Rule in the Memory Management Programming Guide for Core Foundation) which returns an unmanaged object for which you are responsible for releasing, you generally use takeRetainedValue so that it is released for you (or, if you don't do this, you have to manually release it yourself with CFRelease or similar function). You use takeUnretainedValue when ownership of the object has not been transferred to you and you therefore do not want ARC releasing the object for you when it falls out of scope.
So, as to when you call takeUnretainedValue vs takeRetainedValue, it simply depends upon what sort of object the called function returns. As a general rule of thumb, if the object was returned from a Core Foundation function with Create or Copy in the name, use takeRetainedValue. Otherwise use takeUnretainedValue.
In terms of what happens if you call the wrong method, if you call takeUnretainedValue when you're passed a +1 object (e.g. an object returned from Core Foundation function with Create or Copy in the name), your app will leak unless you explicitly CFRelease it. You may not immediately notice the occasional leak when running the app, but it can be observed by watching your app's memory usage (e.g. if you profile your app with Instruments). But if you leave these leaks unresolved, your app may eventually receive memory warnings.
On the other hand, if you call takeRetainedValue on an object which has not been retained for you (returned by a function that did not have Create or Copy in its name), the app will likely crash when the object is released. Sometimes this won't manifest itself immediately (not until the last strong reference is resolved), but it will generally result in a catastrophic failure of the app.
So judicious selection of takeUnretainedValue vs takeRetainedValue is very important.
Quoting from NSHipster:
https://nshipster.com/unmanaged/
An Unmanaged instance wraps a CoreFoundation type T, preserving a reference to the underlying object as long as the Unmanaged instance itself is in scope. There are two ways to get a Swift-managed value out of an Unmanaged instance:
takeRetainedValue() returns a Swift-managed reference to the wrapped instance, decrementing the reference count while doing so—use with the return value of a Create Rule function.
takeUnretainedValue() returns a Swift-managed reference to the wrapped instance without decrementing the reference count—use with the return value of a Get Rule function.
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/
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.
I encountered this thing in a book which I am reading and it got me thinking:
"When you allocate a block, it is created on the stack. This means that, even if you were to keep a strong reference to it, calling it later would result in a crash because the memory would be destroyed as soon as you leave the method in which it was defined."
I thought if I have a strong pointer to something, it is kept alive?
Does this mean this does not apply for objects allocated on the stack?
I am trying to think of an example without using blocks...(e.g., of pointer - maybe an ivar- pointing to a stack allocated object which gets destroyed even though the pointer is alive)
Objects are never allocated on the stack in Objective-C. Blocks are special however, since they are stack allocated. So if you want to retain a pointer to a block, you must first copy it by using Block_copy and use the copy, then release it with Block_release. This must be done if the block is to be used after the scope it was declared in is destroyed. More on the matter here: https://developer.apple.com/library/mac/documentation/cocoa/Conceptual/Blocks/Articles/bxUsing.html (under "Copying Blocks"). Yet again though, this does not apply to regular objects.
Blocks can be messaged like objects. To move them from the stack to the heap, just "copy" them.
void (^stackBlock)() = [^(){
NSLog(#"Hello world");
} copy];
~ 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.