ios scratch card effect crash - iphone

I need to use a scratch effect for my game. here is an example code years ago.
https://github.com/oyiptong/CGScratch
It works just fine, but when i use it together with navigation controller, it crashes.
My project uses ARC, i flag the file as -fno-objc-arc. Here is the source code:
https://github.com/lifesaglitch/ScratchWithError
it crashes when i push the view controller, then pop, then reenter.
Edit:
When you convert all to arc, and flag the view controller that uses the scratch view as -fno-objc-arc, it works. But when you flag the scratch view as -fno-objc-arc instead, it crashes again. My project uses arc and i dont think i can convert my own view controller to be -fno-objc-arc.
Edit 2:
I modify the initialization code to:
scratchable = CGImageRetain([UIImage imageNamed:#"scratchable.jpg"].CGImage);
it does not crash anymore, but there's a memory leak. and CGImageRelease did get called once in dealloc method.

Use CGImageCreateCopy.
The reason for this is that you send a release to your CGImageRef at your dealloc, but if you inspect the actual CGImage object you'll see that it points to the same memory address each time (I guess it's part of Apple's optimizations, so it's just like you would have a static UIImage object and reference its CGImage).
So in your initWithFrame: you should get your scratchable like this:
UIImage *sci = [UIImage imageNamed:#"scratchable.jpg"]; // This guy is always the same
scratchable = CGImageCreateCopy(sci.CGImage);
PS: You had an actual leak with pixels, so you also need a CFRelease(pixels);
I tested, analyzed and measured the code and it seems to be OK now.
Here is also a link to the fixed project (I've also put a navigation controller and a button to push/pop) - and uses ARC of course.

This one works great for me https://github.com/moqod/iOS-Scratch-n-See !

In AppDelegate.m
[window addSubview:viewController.view];
You should instead replace it with:
[window setRootViewController:viewController];

Related

Do the viewcontrollers in a UIPageViewController set-up need releasing?

I am using the Apple UIPageViewController template from Xcode to create interactive photobooks. Everything works fine except that whenever I turn a page (create a new viewcontroller) the memory allocation goes up and up and up until the app crashes. It looks to me that the viewcontrollers never get 'released' (am I still allowed to use that word in an ARC environment?). It does not seem to be anything to do with the content of the pages because when I comment out all the content creation stuff in the ...DataViewController the memory still keeps going up and up every time I turn a page, not as spectacular as when a large image has been included but it still keeps creeping up.
There's been exactly the same question here: PageViewController: How to release ViewControllers added to it? but this one deals with a pre arc & storyboard situation. Adding autorelease is not permitted and it certainly seems that the compiler is NOT taking care of it. :-(
Any suggestions?
The problem turned out to be the never enough damned "UIImage imagedNamed" construct. It probably is all my own fault for not checking after I read somewhere that this had been fixed in a recent xcode release. So I assumed images were no longer being cached whereas the opposite was true. Once I changed all to the "UIImage imageWithContentsOfFile" the app started working smooth as a babies bottom.
I had the same problem building a picture book with very large images. I went to other question you provided a link for and that solved it for me. Adding "autorelease" frees up the memory.
In the UIPageviewcontroller delegate method "viewControllerAtIndex". I changed from:
// Create a new view controller and pass suitable data.
ContentViewController *contentViewController = [[ContentViewController alloc] initWithNibName:#"ContentViewController" bundle:nil];
and added autorelease
// Create a new view controller and pass suitable data.
ContentViewController *contentViewController = [[[ContentViewController alloc] initWithNibName:#"ContentViewController" bundle:nil] autorelease] ;
This wasn't included in the apple example but I'm also using xib for each page. I've been debugging this using instruments and saw memory reclaimed right away and dealloc being called when it wasn't previously.
found answer here....
https://stackoverflow.com/a/7934392/1212585

How to release a view when it's not visible in a tabbar controller?

I have a simple app with a tabbar navigation interface.
It has three view (A, B and C) and a modal view. Each view has its own view controller and nib . They are all designed and connected in the interface builder.
I'd like to release views which are not visible.
Tried release and nil them when another view appears such as
[[[self.navigationController.viewControllers objectAtIndex:0] view] release];
[[self.navigationController.viewControllers objectAtIndex:0] view] = nil;
etc.
It doesn't cause any issues but when I run instruments it does not make any difference. I don't see any drop in memory usage
I would appreciate your help
as #Daryl Teo wrote you should release and recreate in viewWillDis/Appear and (thats why I write this answer) you have a method called didReceiveMemoryWarning, use it!
You can simply log out whenever it gets called and test it with the Simulator included memory warning test function.
Simply open a tab, open another tab and call that test function. Your debug console should print out the log. If not you should double check if you have released all objects maybe someone is over-retained (which again should be released in viewWillDisappear).
The drop in memory usage might not be significant, depending on what the released viewController holds on to. I sugest you out a NSLog into the 'dealloc' of the viewController to see if it really gets dealloced or if there is some other object still holding on to it. Remember that release won't free the memory, it will only do so (by calling dealloc) if the objects retain count reached 0.
You don't want to do this. Let the TabBarController handle your view controllers for you. (It will already retain your viewController internally so whatever you do will only make retain count go out of sync)
You may be able to make it more memory efficient if you release objects in viewWillDisappear. Then rebuild the data again in viewWillAppear.

showInView: method for custom UIView

I have created a custom UIView called CustomMessage that I am using throughout my program. The appearance of the CustomMessage is animated so I have written a method in the CustomMessage class called showInView: to show the view. For example, say that I wish to show the CustomMessage view in a particular view controller - I would use the following code:
CustomMessage *myCustomMessage = [[CustomMessage alloc] initWithMessage:#"Hello"];
[myCustomMessage showInView:self.view];
As you can see, this is quite similar to how a UIActionSheet is created and presented.
However, I am having problems with the memory management. If I put the following line of code directly following the two lines above:
[myCustomMessage release];
then (as expected) the program will crash with the message sent to deallocated instance error.
I am unsure what I need to do in my CustomMessage class so that I can release the object directly after calling the showInView: method so that I don't get a memory leak. Obviously this can be done, since that's how a UIActionSheet works (but I just can't get my head around how I can implement something similar - I can't figure out how the CustomMessage object can be retained by some other object, presumably the self.view (in the example above) which is displaying the CustomMessage, to avoid it releasing the object entirely while it is still in use).
Everything else works perfectly except for this little aspect, so any help would be greatly appreciated :)
I'd need to see your code for showInView: in CustomMessage.m. I would expect it to look something like the following.
- (void)showInView:(UIView *)view
{
// pre-animation configuration
[view addSubview:self];
// do the animation
}
This means that the CustomMessage instance is retained by view. Also, if your implementation of showInView uses concurrency at all it is possible it is returning immediately allowing MyCustomMessage to be released and then background operations are trying to access the release object. I'm just guessing w/o seeing your code.
What is the crash log? What message is sent to what object in what context? This info will localize the problem.
If none of the above helps you solve the problem, post your code for showInView as well as details from the crash log and I'll take another look.

three20 - TTTableViewController Memory warning gives blank screen, how to fix?

This is driving me nuts. I am using three20's TTTableViewController and when I get a memory warning, the screen goes white. Now, after reading on the three20 google group is seems that the tableView got released. But, I cannot for the life of me figure out a check to see if that is the case, then create it again.
I was using the following because I thought it would fix the issue, but it seems that it doesn't satisfy the if statement:
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
// If we don't have a datasource we need to reset it
if (!self.dataSource) {
// Create datasource again
}
}//end
Does anyone know what to do when this happens? The google group has been no help.
Are you subclassing TTTableViewController? I haven't used it before, but assuming it's just like UITableViewController...
How does your "viewDidUnload" look like? Are you releasing the tableview here? If so, you need to create tableview in viewDidLoad to match it.
No need to check if dataSource is available in viewDidAppear, because if you read View programming guide, it explains that memory warning will call "viewDidUnload" to give you a chance to clean up data that are created in "viewDidLoad".
i had the same issue and it drove me crazy as well.
Nobody mentions it in the three20 docs, but you shouldn't use UIViewController's initWithNibName function to add subviews. If you do, a memory warning will release these subviews.
Try to move your code from initWithNibName function to viewDidLoad function. I have noticed that some code need to be kept in the initWithNibName, such as navigation styles. However, any subviews added to the controller's view should be in the viewDidLoad function.
In general you should be careful to set up views in viewDidLoad rather than the class constructor. For instance, you should set up your launcher view in viewDidLoad rather than the constructor of your launcher view controller, otherwise your launcher will become empty after a memory warning.
In the case of TTTableViewController however this does not (usually) apply because you don't set up the table view manually. I had the same problem you had, and eventually tracked it down: I had redefined viewWillDisappear: and forgot to call [super viewWillDisappear:animated]. This meant that some of the flags that the Three20 controller maintains about the state of the view were not updated correctly.
I also found that it was beneficial to redefine didReceiveMemoryWarning to call [self setEditing:NO] before calling super; I found that the state of the table view got confused otherwise (this is not relevant if you don't use edit mode for your table).
Finally, there is a bug in Three20 which means that tables in loading/empty/error mode will not be restored properly; see a discussion in the blog post by TwoCentStudios and a proposed fix on github.

cocoa - quickly release all IBOUtlets

I have a view with many retained IBOutlets, loaded from a XIB.
I have read that they have to be released when the controller's dealloc method is called.
May I use a cycle to do this(also to avoid releasing each outlet separately)?
something like
for(UIView *v in self.view.subviews){
[v release];
v=nil;
}
?
also, after that, should I release the view as well?
That would only make sense if you've actually retained every single subview, and even then it seems like asking for trouble -- if you ever wanted to change your .xib, you'd have to remember to update you code as well. And there may also be non-view objects in a nib that can be connected to outlets, like view controllers.
There are only so many views you can fit on an iPhone- or iPad-sized screen, so it's hard to imagine that you have more than a few dozen outlets. I think the prudent thing to do here is to simply release each one separately. This is what and iOS developer would expect to see, and it won't be any slower than using a loop. It'll be more code, yes, but the code will be easy to understand.
self.view is automatically released on UIViewController deallocation, and subviews also, if not retained by your code.
You should re-read the chapter on memory management in Apple Documentation... ;)
I wrote like a releaseVars function, which takes address of variables, release them and set to nil. This save some lines of code, but still you have to manually take care of them.