In John Oliver’s voice : “Fuck you Apple, fuck you.”
The tangible benefits of ARC are at best marginal, and there are downsides, which some can reasonably find more significant, and thus ARC not worthwhile.
First off, "manual" reference counting is misnamed. It is at the very least "semi-automatic" and highly automatable.
So how does a property declaration look with "MRC" vs. ARC?
@property (nonatomic,strong) NSString *str;
vs. @property (nonatomic,strong) NSString *str;
Can you tell which is which?So how about use?
someObject.str = @"Hello World!";
vs. someObject.str = @"Hello World!";
Can you tell which is which? In use, ARC and MRC are mostly indistinguishable, as long as you use accessors/properties for all instance variable access. You do that, right? Right?OK, so there is automatic dealloc. That's a nice convenience, but actually not intrinsically tied to ARC. How do I know? I implemented automatic dealloc for a project once. Didn't use it much after because the small effort spent on dealloc just didn't seem worth it, especially as you also had other boilerplate to implement, the coders, isEqual and hash.
The one biggie was weak, which was previously handled via non-retained references, so no automatic nilling. This could actually be a pain from time to time, but really not that huge a deal and it was also never really intrinsic to ARC, as shown by Apple recently adding weak for non-ARC code.
So those are/were the upsides. Not really that much.
Among the downsides is a performance penalty that could be both significant and somewhat unpredictable, on the order of 50%-100% slower in realistic scenarios (in extreme cases it can be an order of magnitude or more). You could also get unexpected crashes because of retain/releases added in unexpected places. We had a crash in a method that did nothing but return 0;
http://blog.metaobject.com/2014/06/compiler-writers-gone-wil...
However, for me the biggest pain point was the semantic changes in ARCed-C: what used to be warnings about an unknown message are now hard compile errors, and that seriously cramps Objective-C's style as a quick-turnaround exploratory language.
And yes, I have worked with/built both significant ARC and non-ARC codebases.
What's really troubling about these things (GC, ARC, Swift) is the rabid fanboyism. When GC came out, you were complete idiot and a luddite if you didn't embrace it and all its numerous warts (which were beautiful) wholeheartedly, and buy into all the BS.
Then when GC was dropped and replaced by ARC: same thing. Did anyone say GC? We meant beautiful shiny ARC, you ignorant luddite. And it quickly became an incontrovertible truth that ARC was faster than "MRC", despite the fact that this wasn't so. And when people asked about it, mentioning they had measured significant slowdowns, they were quickly attacked and everything questioned, because everybody "knew" the "truth". Until a nice gentleman from Apple chimed in an confirmed. Oops.
So please ratchet down the fanboy setting. Technologies have upsides and downsides. Reasonable people can differ on how they weigh the upsides and the downsides.
And of course we are seeing the same, just magnified by an extraordinary amount, with Swift.
I don’t know how to check this, but that isn’t how I remember it at all.
There was a brief flurry of interest when Apple added GC, but it never caught on. If it had been popular, Apple would have kept it.
Then when ARC arrived, it was genuinely popular, and that’s why it was a lasting success. By automating the exact same retain/release/autorelease protocol that people were already doing by hand, it fit much more neatly into existing Obj-C best practices.
I do partly agree with you, that Swift seems to have some problems that haven’t yet been fully resolved, but Apple are still going full steam ahead with it. It feels more like GC, but Apple are treating it like ARC.
Well, that's the beauty of upgrading to ARC: your declaration syntax doesn't need to change; usually it just means that you can drop a bunch of autoreleases in your codebase.
I read your blog post, where you mention this snippet of code being optimized in an odd way, printing "1 2" in Clang:
int main() {
int *p = (int*)malloc(sizeof(int));
int *q = (int*)realloc(p, sizeof(int));
*p = 1;
*q = 2;
if (p == q)
printf("%d %d\n", *p, *q);
}
Of course, when you have odd things like this happen you're reaching down into undefined behavior, and then all bets are off.Really, I you're just focusing on performance too much and neglecting the fact that ARC isn't there for increasing the performance of your code: it's there so that you can program in a manner that's more safe. Sure, it's easy to manage memory manually, until that one time you double free and SIGSEGV.