I am working on an iPhone app which does some video processing, I had to include to classes that are not ARC compliant ( dealloc , releasing stuff ). So I manually went and made them arc compliant.
Later on I discovered the compiler flag for any class that can make it non ARC in an ARC project -fno-objc-arc.
My question is, if I do flag those classes with the compiler flag, what are the reprecussions of this? performance hit? is it a good idea? my app iOS 5.0 and up. I couldn't find any resources that talk about pros and cons of doing this.
You ask:
If I do flag those classes with the compiler flag, what are the repercussions of this?
The only thing I believe you need to worry about is to make sure that the non-ARC library follows Cocoa naming conventions associated with memory management (e.g. only return objects with +1 retainCount if the name begins with alloc, new, copy, or mutableCopy). Otherwise your ARC won't be able properly manage the resulting object. Most well written classes will conform to this pattern, so you should be perfectly ok using the fno-objc-arc flag, but it depends entirely upon the class in question.
[Is there a] performance hit?
There are no practical performance issues.
[Is] it a good idea?
All things being equal, I generally like to convert the code to ARC. A couple of situations where I might refrain from converting:
It is a library for which there is active development, and if I create my own personal ARC fork, I'll lose out on the future revisions of the library.
The library is incredibly complex and/or has constructs that are not easily converted to ARC.
Bottom line, if I can convert to ARC, I will. Usually in this process, I'll do the necessary testing to make sure I'm comfortable with the library, that there are no leaks, etc., so it's a productive (if annoying) process to go through. We're all responsible for the code we include in our projects and I don't think one should ever integrate code without going through some due diligence that is a natural by-product of an ARC-conversion and testing process.
If I convert to ARC, I offer to contribute the conversion back to the original author (e.g. via a GitHub "pull request" or whatever mechanism the author is open to) so it can be integrated into the code base.
At first glance, there are no performance issues with using or disusing ARC. ARC is basically normal reference counting, it's just not the programmer who inserts the release calls, but the compiler.
Related
I am trying to search to prevent the Method Swizzle in my current library but more or less every documentation or blog post that i found are about how to implement Swizzling.
There are couple of question that i have regarding Method swizzling that i could not find all across.
How to detect the Method Swizzling at runtime?
In case there is a Method Swizzle how to prevent it ?
I know the dangers of method swizzling and have already gone through the related posts here but could not find the related information to prevent it.
If there is any documentation or blog post that available on the above topics, I would really appreciate the assistance.
Avoiding method swizzling is simple; use functions rather than methods (i.e. do things the old-fashioned way without objects, in C++, or at least in Core Foundation). But if you're using the ObjC runtime, you can be swizzled.
You can in principle detect swizzling by caching all your IMP pointers, for example using class_getMethodImplementation in something like +load or maybe a C++ constructor on a global variable (which get run before main()), and then re-checking all your IMP pointers at various times to make sure they haven't changed.
That probably wouldn't be too hard, but it's difficult to imagine what all of this would achieve. If someone has your framework binary, it wouldn't be a major effort to to patch it to remove your check. Somewhere in the source code, there's got to be a if (swizzled) { ... }, and that's going to translate into a branch-if conditional instruction in the assembly. You stick a debugger on the system, wait for the branch to "ah! we're swizzled" to occur, note the point where it happens, and patch that byte to be "branch-if-not" or just add an unconditional jump.
Slowing that attack down, even a little, requires substantial obfuscation. There are techniques (that mostly don't work that well), but they only work by being kept secret. That's the difference between obfuscation and security.
Short answer is you really can't achieve this in any stable way. That means you either need a team devoted to constantly coming up with new, more advanced obfuscations and updating them regularly as new attacks emerge (i.e. how a company like Blizzard or Apple prevent hacking), or you'll need to find a way not to need this.
Simplest answer? Work mostly in C++ and use ObjC classes as little as possible (which will prevent swizzling, but not reverse engineering or patching). Or accept that swizzling is not avoidable.
(BTW, if there were even a "I'm willing to do whatever it takes" answer to this question, then Apple would just use that technique to make jailbreaking impossible. The fact that iPhones get jailbroken regularly suggests the difficulty of the problem.)
Retain counts are the way in which memory is managed in Objective-C. When you create an object, it has a retain count of 1. When you send an object a retain message, its retain count is incremented by 1, which we know that ARC does it automatically but how it does what is the technique it use??
And I still wonder if memory management is done automatically then why sometimes we get bad access error for objects allocations or retrieval.
I have already gone through this link:- https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/MemoryMgmt/Articles/MemoryMgmt.html
I think ARC (done by the compiler at compilation time, by inserting retain/release command where 'necessary') relies on the scope of variable, the block of code where they are defined (i.e. initialized) and if its value is stored in another variable whose scope is broader than the initial variable's scope.
That's why you have to declare more precisely the type of variable access and storage: to inform the compiler your intentions with a variable.
But I think too that ARC can't see further than the current file. ARC is more tricky with global variables and inter-files dependencies.
So, Apple a more complex variable's declaration grammar to replace a very simple (IMO) retain/release pattern. So developers don't have to worry about memory management.
That enable Apple ecosystem to be accessible to a lot more developers used to managed languages (like web developers) to develop for iOS.
I think it is a mistake to make developers believe you can develop efficiently without having to understand such a fundamental concept in IT as memory management.
But more developers for iOS means more programs developed and a more stable ecosystem in term of activity, so more revenues for Apple :-)
You would be better off reading the ARC docs: https://developer.apple.com/library/ios/releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html
ARC will manage the memory for you, but it cannot stop you from writing programming errors such as only holding weak references to an object.
Edited: Some of you think ASDealloc2MainObject from AsyncDisplayKit doesn't really override retain/release. I modified the source code behind ASDealloc2MainObject (line 405-428 of _AS-objc-internal.h), added a printf() inside the overridden release method and did a few test runs on my iPhone. The log was printed as expected. My test code (including a new class that inherits from ASDealloc2MainObject) was compiled with ARC enabled.
I used to believe that overriding retain/release methods cannot be done under ARC. Turns out I was wrong. Such a technique involves a base class compiled under MRC and its subclasses compiled under ARC.
One good example is the Facebook AsyncDisplayKit. Lots of classes from the Facebook AsyncDisplayKit framework inherit from a base class called ASDealloc2MainObject. ASDealloc2MainObject is a class that compiles under MRC and overrides NSObject's retain/release methods. In the meantime, subclasses of ASDealloc2MainObject compiles and runs under ARC.
I have two questions:
Quite a few blog posts on the internet say that when ARC is inserting memory management code during compile time, it will insert low level C functions such as objc_retain() and objc_release() rather than their Obj-C equivalents [NSOject retain] and [NSObject release]. ARC does this because low level C functions could provide extra optimization, such as eliminating costly Obj-C message sending and canceling adjacent autorelease and retain calls. My question here is, if we use the MRC/ARC overriding technique, do we lose such optimization?
My second question is in some way related to my first question. What's the runtime behavior of objc_retain()/objc_release() if the target object's base class has overridden its retain/release methods? My guess is that these C functions are able to figure out the situation here. Instead of performing their regular optimizations (such as eliminating sending retain/release messages), they would in fact revert to the old way and actually sends out retain/release messages.
Quoting the documentation:
You would implement [the retain] method only if you were defining your own reference-counting scheme. Such implementations must return self and should not invoke the inherited method by sending a retain message to super.
Are you implementing your own memory management system? No? Then do not override retain or release.
Apple also advises against using reference counting for all Objective-C code. You are supposed to be using ARC.
ASDealloc2MainObject does not override retain or release. Old versions did but FaceBook realised that was a terrible idea and have updated their code to use ARC.
As for how exactly ARC behaves, the answer is "it depends". There are many different ways it can behave. Go read the compiler source code if you really want to know how it works.
That blog post you linked to is ancient and should not be trusted at all. Apple makes breaking changes to the compiler every 12 months and that means they've done so 3 times since the blog post was written. Since memory management is a performance bottleneck, that's where they make the most changes each year.
Sending a "retain" or "release" message to an object is outrageously slow. ARC and the Objective-C runtime both try to avoid sending messages as much as possible. One of the reasons the Swift language was created was to eliminate sending messages altogether. objc_retain() and objc_release() exist to avoid sending retain and release to an object. There might be situations where they do so but you can't rely on it.
I'd suggest that you write some code and try it. I'd expect that retain/release are not actually called from ARC code, because it uses (faster) function calls. So your overrides won't work when called from ARC. They probably work when called from non-ARC code.
That's to find out what happens. In practice, overriding retain/release in mixed ARC/non-ARC code will probably just get you into trouble.
I have seen many samples of NSXMLParser and understand how it works. For example, this one is very good:
http://wiki.cs.unh.edu/wiki/index.php/Parsing_XML_data_with_NSXMLParser
All samples I saw use Release to release temporary objects at some point during parsing which is OK. But if I switch on ARC, I don't have access to release at all. How does the sample code change then?
For example, please look at the above code (link) and explain how would you change it with ARC ON?
Thanks.
For a discussion of how one goes about making non-ARC code enabled with ARC, I'd refer you to the Transitioning to ARC Release Notes. As Midhun alludes, you will be replacing retain references with strong references and eliminating release and autorelease. You'll also be removing calls to [super dealloc]. So the conversion isn't hard, but there are a number of items to be conscious of.
Having said that, I disagree with your assessment that this example code is "pretty good." With no insult to the original author, it's a little outdated, and as such, is applying historical conventions rather than the modern contemporary practice (e.g. explicitly declared ivars for properties, not using underscore for ivar names, etc.). I also noticed a few bugs in the code (minor things like a missing property, more significant things like a bug in the foundCharacters routine, etc.).
I've cleaned up the code (both converting it to ARC and addressing a number of these issues) and have uploaded it to a repository on GitHub. Note, I've done two things:
I've modified the code to be a little more contemporary in its practices (this is the UsersParser class) and fixing a few of these little bugs;
I've also made a rendition of this code which is a little more flexible, the XmlArrayParser, where the parser class isn't hard-coded for the Users XML file that the example uses. The method that calls this has to understand what elements we're looking for, but the parser itself doesn't care.
I hope this help.
When you convert it to ARC there will not be any
retain
release
autorelease
keywords.
For better understanding you should convert that sample code using Xcode ARC conversion Tool.
You'll get a better understanding when you complete that.
Please refer this tutorial for assistance.
In what circumstances should I be using this feature?
How exactly mature is it?
What are the pros and cons?
What problem does it solve?
Is it specific to MonoTouch, Mono GC, or reference counting in ObjC?
Here are some quick, high-level (and out or order) answers to your questions...
Is it specific to MonoTouch, Mono GC, or reference counting in ObjC?
It allows sgen, the mono garbage collector, to work more closely with Objective-C reference counting. That awareness is not needed for Mono (or Mono for Android) so it's specific to MonoTouch.
How exactly mature is it?
As the UI says: Experimental preview. So while we know it works it has not yet seen a wide usage inside applications (compared to the default GC). It's more a direction than a destination (i.e. it will likely evolve).
You're more than welcome to test it, use it (if it proves useful in your situation) and report your findings/experiences with it. However it's not fully supported, e.g. you might hit a bug that we can't immediately fix or workaround (beside asking you to go back to the default settings).
What problem does it solve?
The coexistence of a garbage collector and the reference counting of Objective-C is very complex subject. MonoTouch tries it best to hide (most of) complexity of this to the developers.
Most of this is done inside the runtime (e.g. by using the backing fields). This extension to sgen is meant to have the GC itself (not only the runtime) aware of the needs for reference counting.
What are the pros and cons?
PRO: It saves memory as the linker can remove many of the backing fields that would be otherwise required to ensure we keep a reference to the managed objects. Without those (references to) backing fields the GC would normally collect the instances (while they are still needed by unmanaged code).
CON: We need more feedback, more comparison data (e.g. performance).