Note: I apologize if there are similar questions, but they are more specific like "UIMapView Kit Memory Leak issues", I am more concerned and really want to know in General Swift and ARC and the memory Management Issues with it.
I have done a couple of apps now in Xcode, however it was all done in Objective-C.
The memory management of UIKit objects(including UIViews and UIViewControllers) and any other object for that matter was easy to handle in Objective-C, and by easy I mean getting used to it after battling with it at some point in the Learning curve.
Now I am working with Swift trying to keep up with the "Cutting-Edge" technology. however I have noticed a slight issue with what I was able to pin down and control in Objective-C, Memory Management.
Swift comes in saying how easy is going to be for us to focus more on Code Development and not on memory management like its predecessor or soon-to-be predecessor.
However I have not yet found this benefit. I have been having a horrible time with memory management of my new app. Just creating a simple UIViewController with a few views can stack up memory that I don't longer need, few Mb's at a time.
keep in mind, I have been using deconstructor(Deinit in Swift), been assigning nil to values I no longer need to use, removing SubViews from Super Views manually thinking this was the problem, even using AutoReleasePool code segment.
autoreleasepool{
//Code looping through Swift Native Objects that potentially might lead to leaking
//But AutoReleasePool helps with this, supposedly.
}
Now the Question: Anyone here would know exactly what is the problem? Is it me doing something terrible with my code? or is there really a bug in Xcode and swift memory management? Have anyone else had this issue, have you solved it?
Here is a link explaining a bit this situation.
Problems of ARC in Swift?
ARC in Swift Apple Docs
Update:
You are right, I should post more about my situation: so here it goes.
I have memory starting at ~5mb as as soon as the app starts.
Once I start navigating around the app. I notice how memory starts to pile up little by little.
but the biggest spike of memory start to pile up when I use UIMapView of about 25+ Mbs.
when using just a regular UITableViewController it just piles up ~2mbs every time I push(to NavController) the same UITableViewController. When I tab that TableViewCell it opens another ViewController with a UIMapView, this is where the memory starts to pile up really good.
Rememeber I am just going back and forth navigating through the app. Just a total of 4 UIViewControllers including My Menu.
But here is the thing... All these memory SnapShots you see are after I stop navigating and go back to the main menu, the Root ViewController of my Navigation Controller.
Swift uses ARC in exactly the same way that ObjC does. If you're seeing a leak, you're probably creating a retain loop somewhere, and you would avoid those in almost exactly the same way as in ObjC (with the additional option of using unowned, but those are very similar to unsafe_unretained, so even that isn't a major change). If you're familiar with memory management in Cocoa, then you understand memory management in Swift. But we can't help based on the information you've given here (which mostly seems just commentary on Cocoa).
autoreleasepool{
//Code looping through Swift Native Objects that potentially might lead to leaking
//But AutoReleasePool helps with this, supposedly.
}
All that said, this comment hints at your mistake. The autorelease pool needs to go inside a loop where you are rapdly creating and destroying objects, not around it. Autoreleased objects are not released until the end of the pool block, or the end of the event loop. The latter is generally sufficient, but if you're generating and releasing lots of objects, then you sometimes have to drain the pool sooner. Autorelease pools are explained in the Advanced Memory Management Programming Guide. That said, they are not commonly needed for UIKit objects.
As a side note, the "Problems of ARC in Swift?" link you give seems to be unaware of the history of Garbage Collection in Cocoa. GC was tried by Apple on Mac and rejected by Cocoa devs. Apple deprecated GC and has subsequently removed it (I was at WWDC when they announced it was being deprecated; we applauded). It is even less applicable to iOS. An excellent discussion of this issue is in Why mobile web apps are slow. I'm not saying that GC is a bad thing. I'm saying that Apple is well aware of it, and actively chose not to incorporate it. They didn't just miss an opportunity.
EDIT: Your updated info looks like a pretty standard retain loop. I'd start with heap shot analysis to figure out what kinds of objects are involved. Make sure you're following the rules. And go from there, mostly with Instruments (especially the Allocations and Leaks instruments). One key is that view controllers should generally not retain other view controllers at all. They should talk to each other through the model. You must be careful using self in blocks. The normal rules. They're the same in ObjC and in Swift. But heap shot is definitely the place to start. Find out what is leaking; then figure out why.
Related
How can I search for specific static memory address in iOS games some thing like amount of damege and other Thing that don't have vaule in Gameing
I use Ida put its not helpful cause it not show you the statice memory address
Assuming you're trying to hack existing games by twiddling bytes similar to what Game Genie did on old video game systems, good luck with that. Besides the fact that iOS apps use dynamic memory allocation for pretty much everything, iOS also incorporates address space layout randomization, which means even ostensibly static storage probably won't be in the same location in consecutive launches.
The only approach that would even stand a chance of working would involve injecting code that performs introspection of the classes using Objective-c runtime calls. And even if you do that, there's no guarantee that such hacks will be possible or practical in iOS.
I know about iOS Automatic Reference Counting, which is compiler based feature. But, i have been going through many sites and confused with whether Garbage collection is also there or not on iOS program development? I know, ARC and GC is different each other. Some links says, GC is available for iOS and some links says GC is available only for Mac OS X development. But, i couldn't conclude saying whether the GC is there or not on iOS development? Please direct me the right path or link so that i can understand about it and try programming.
Thanks!
iOS has no method of Garbage Collection. Even so, Garbage Collection is entirely unnecessary (for all practical purposes) when ARC is used. ARC works its magic at compile time to do the reference counting for you thereby making it unnecessary (and actually non-allowed) to use any other sort of memory management.
Edit:
To clarify, OS X does currently support garbage collection, but it is deprecated (unbeknown to me until a few minutes ago) as of OS X Mountain Lion. iOS never has and never will support garbage collection. Any advantages of garbage collection are moot when compared to those of ARC, and Apple has made the move to (forcefully) nudge us in the right direction.
iOS does not have garbage collection
We've just released an app using the Crittercism framework. After some time, we've had about 125K app loads, and 95 crashes - a rate of less than 0.08%.
One crash happened 19 times, another 10, but the other 41 all occurred 3 or less. If there were any major problems with the app, I would expect to see significantly more failures in particular areas, so I'm happy with the level of figures I'm seeing.
A quick look shows many of them to be low level failures, not obviously caused but programmer error.
Examples
The largest group are all to do with CFNetworking on a background thread while static HTML is being being rendered in a web view on the main thread.
There are some KVO failures in free_list_checksum_botch
But my question is, in a sufficiently complex OS (iOS in this case), with a sufficiently complex app (which I think it is), should I, as a developer, expect to see this level of "background noise"?
Should I expect to see one app crash per 1-2000 loads, just because the OS isn't perfect? Has anyone else had a similar experience?
(I'm not looking for solutions to the errors themselves.. thanks!)
Crittercism conducted an analysis on app crashes. Their report was based on Android vs iOS crashes.
They concluded that the most popular apps on iOS crash 0.51% of app launches. So #Ashley Mills, if you're getting 0.08%... you're doing well. (i think I have my figures correct, anyway).
Not sure where the original report is, but I read it here:
Forbes app crash rates, conducted by Crittercism
Actually another shot in the dark non-technical answer could be. What added value will it bring you (the developer) to keep digging into that particular issue, when you could be spending more time and effort either developing more capability within your tool, or another tool completely.
If your app is simply for fun and learning, then I could see digging into this issue as a fun adventure. From a business perspective, what is your time worth and is figuring out this 0.08% problem going to sell enough (more) copies to make your efforts worth it.
An analogous would be, what requirements are essential, and what requirements are desirements?
Just food for thought. I know many of the companies I have worked for don't see the value in stressing about that low of a yielding bug.
I am an iOS developer, employed professionally. I take it personally when my apps crash, because that is not the user experience I was aiming for. A crash is a bad user experience. One crash, per user, is too many. A crash is a bug.
That being said, I have definitely seen crash logs that appear to be unsolvable because they seem to be indicating a problem way down deep in the SDK. What I have learned, however, is that more than likely there is something about my own code that is ultimately the cause.
There are any number of bizarre crashes that can be caused by timing issues between threads or blocks or just because I did something wrong. Just recently I discovered I was doing something entirely wrong with respect to a complex table I was updating. The crash logs for this problem provided almost no clues except for the general area of code I might look at. As I dug into the code and started experimenting, I realized my mistake, which ultimately was a timing issue caused by what I thought was a clever separation of main-thread vs. non-main-thread activity. I was too clever for my own good, in this case. :-)
So, to sum up:
One crash is too many crashes and ultimately a bad user experience.
Often, bizarre low-level crashes are the result of your own code's complexity and possibly timing issues there in.
Finally, I offer this question to consider:
Are you willing to piss off or dismiss some of your users simply because they fall into the 0.08% of users experiencing crashes?
Food for thought. :-)
I'm a professional iPhone developer, and what I've seen is the crash frequency isn't what upsets users, it's the funnel for how the crashes happen.
If they are intermittent you are usually okay, the problem starts to occur when one user experiences a specific crash multiple times. This is unacceptable.
Striving to remove every crash is always a good thing, but in many cases it's simply not realistic, you have to decide where your time is best spent. If you have the opportunity to rework a portion of the UX flow or fix an intermittent crash, you need to decide which one benefits more users.
The important thing to remember is, if you choose not to fix a crash that happens 0.08% of the time, you aren't writing off the users experiencing it unless they are experiencing it multiple times.
Although not a technical answer, on my iPhone I'd personally expect to have an app I use a lot crash at least once or twice over a year. I'd say that level is perfectly acceptable, and since generally I find they crash a lot more on the first time you start it I believe it's something to be expected.
We are developing an app that we want to run on iOS 4.3 and above.
Our senior developer believes using ARC is a bad thing and causes crashes and problems in anything below iOS 5. Is this true? What problems could there be when using ARC on iOS 4.3?
I know you have to use unsafe_unretained instead of weak references. What issues could this cause?
Should we not use ARC at all if we are also developing for iOS 4.3 or is it possible to develop a solid app for both iOS 5 and above and iOS 4.3 using ARC?
There's no reason not to use ARC when deploying to 4.x. It's totally incorrect to say that ARC causes crashes and problems on anything below iOS 5. That totally missing the point and not understanding what ARC is probably.
ARC is a compile time "funkiness". That's what I like to call it anyway! It simply adds in the right number of retains and releases or autoreleases to make your objects stay around for as long as they should. I like to think of it as almost like turning objects into stack variables. So consider this code:
- (void)methodA {
NSNumber *number = [[NSNumber alloc] initWithInt:5];
[someObject doSomethingWithANumber:number];
}
ARC will add in a release of number when the number variable goes out of scope. In this case it goes out of scope when methodA returns. So consider this more elaborate bit of code:
- (void)methodB {
NSNumber *number = [[NSNumber alloc] initWithInt:5];
if (<some_expression>) {
return;
}
[someObject doSomethingWithANumber:number];
}
In this case, without ARC we would have had to put in 2 [number release] calls. Once before the premature return and once at the end of the method. Obviously this is a contrived example by the way - it's just to show the idea. With ARC, we don't have to put in these 2 calls it does it for us. I think you can see the power of ARC here because in this scenario if your method got a bit bigger and more complex, you could very easily forget to release things before a premature return from a method.
Back to the point in hand about 4.x... You're right that you can't use weak references. This is because this is the only part of ARC that requires help from the runtime, and this isn't part of the runtime shipped with 4.x. The runtime will automatically nil out weak references when the object it's pointing to goes away. So if you have ObjectA having a weak reference to ObjectB (e.g. delegate pattern) then if ObjectB goes away because it's no longer in use, then ObjectA's reference will be nilled out. This only serves as a safety net in my opinion. You should be coding so that that scenario never occurs anyway. It's been the way ever since weak references came in and you just have to code in such a way as to not let it be an issue - something we've all been doing for many years already.
In my opinion, you should be using ARC. It will help you. You'll get much smaller code and more readable code because you don't have retains, releases and autoreleases all over you code. You'll get less crashes & leaks from incorrect memory management, something which we all have had problems with.
In short: USE ARC.
I strongly agree, they're identical to using assign in iOS4, however to suggest they are no more likely to cause crashes in this case is not thinking this through. Who writes code so it crashes? No-one. Do applications still crash despite this intention? Of course. Looming large across the spectrum of culprits is memory management and the raison d'ĂȘtre for ARC. Interestingly though the least caution iOS developers exercise is with assignment - and it's here the danger lies. How often have you seen code where delegates and datasources have not been zeroed in the dealloc? There's scarce hope the level of caution in dealing with these in ARC is going to increase as we delight at our cleaner code, nary a thought for the dangers of dangling pointers. This risk in iOS4 is not obvious and can be very difficult to trace. ARC is the way forward however there are compelling reasons for those supporting applications in iOS4 to take a considered approach.
This is incorrect. In iOS4 the runtime will not automatically nil weak references, you can only use __unsafe_unretained (non-zeroing) rather than __weak (zeroing) which can lead to crashes. Some useful background reading here:
http://mikeash.com/pyblog/friday-qa-2010-07-16-zeroing-weak-references-in-objective-c.html
http://www.mikeash.com/pyblog/friday-qa-2011-09-30-automatic-reference-counting.html
I'm working on a custom PDF library for iOS and noticed that there are explicit functions for retaining and releasing CGPDFDocumentRefs andPageRefs. Does ARC handle the retain/release of such opaque types?
No. ARC does not currently handle the memory management for anything except Obj-C objects (which CGPDF things aren't).
I had the same problem when I recently converted to ARC in PSPDFKit 1.8. After considering a lot of tricks, like bringing ARC to autorelease an item, or using associated values, I finally use a container class that manages the references on the CoreFoundation-Level.
It's tricky, as if you have a CGPDFPage and you release the CGPDFDocument, further calls to the CGPDFPage will crash, even if that one's retained. So be careful with the references.
Related, it's not a good idea to keep many CGPDFDocumentRefs open - they may need A LOT of memory, malloc's of 15MB are not unusual. So in my library I took great care that things get released fast when there's a memory warning.