Clear memory of previous ViewControllers when using modal segues? - xcode

I've been working a photo editing app that takes pictures and passes it on to the
next view controller.
Of course I use AVSession to have the camera preview shown.
When the picture is taken the current view controller passes the image on to the view controller that has all the editing features.
I use modal segues to control transition between views.
The Problem is that when the segue happens there is a increase in memory by 4mb that never gets released.
Viewcontoller-->EditorViewcontoller
EdiorViewcontroller-->Viewcontroller
I also have a segue from the editor to camera,again there is a accumulation of memory.
A few times back and forth and the app crashes.
I can't post picture due to lack of reputation.
How can I clean the memory of the previous Viewcontroller and just have the current view controller running.
Things I've tried
*setting all the instances to nil.
*dismissing the view controller.
*setting the entire view controller to nil.
*profiled it.
*using #autorealease.
*spent hours on the internet searching for a solution.
I use this line of code to perform the segue.
[self performSegueWithIdentifier:#"effectsegue" sender:self];
I even tried using a weak self hoping it might help.
__weak ViewController *weakself=self;
[weakself performSegueWithIdentifier:#"effectsegue" sender:self];
When I profile it,it tells me these lines of code
NSData *jpegData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];
and
[self performSegueWithIdentifier:#"effectsegue" sender:self];
are taking memory.
I would like some suggestions and idea as to what can be done to clear memory of previous view controller and free memory,any other alternates other than segues.
I've been working on this for weeks and this is really not allowing me to proceed forward.
Thanks in advance.

If you're using storyboards and ARC you can create a button inside EditorViewcontroller (that you'll use to go back to Viewcontroller) and link it to the following action on your EditorViewcontroller.m file:
- (IBAction)goBack:(UIButton *)sender
{
[self dismissViewControllerAnimated:YES completion:nil];
}
This should release the memory used by EditorViewcontroller

Related

What is the best way to develop applications using the auto layout in Xcode?

So I guess this is going to be closed for being too subjective and too opinion based but if anyone can help me I would appreciate it.
I got a question. If I have a few controllers that all have almost the same thing For example they have the same background, have a menu going around the edge but the actual content is different. I had a couple of ideas. 1) Just have one view controller and just kill the objects for that current view if the user chooses a different option on the menu and spawn the new objects for that menu. My issue with this way was that I could't find a way to use the auto layout with this.
Second way would to be have a function in a .swift file that I can call and it creates an image view and sets up the menu an everything like that. I have the opposite issue here though, now the auto layout won't work.
App devs must have a way of doing this, I'm just probably thinking of this completely the wrong way.
Is there a better way to be doing this - I am sure there is? I would appreciate it if someone could point me in the correct direction.
Thanks
EDIT:
I should make it clear that the language I am using is swift.
You can create custom container view controller and swap the view controllers for the part that change according to the user selection.
--Adding Example--
e.g iPad's Settings app. The left side is a table view and right side is detail view which changes on user selection. So Tableview can be wrapped in a view controller let's say ListViewController. This will not change. The right side will be DetailViewController which would be swapped according to user selection. Your ContainerViewController will have 2 view controllers at all times.
Here is how to add view controllers as child and set their views in objective-c.
- (void) setupContentViewControllerWith: (DetailViewController*) detailViewController andListViewController:(ListViewController*)listViewController {
[self addChildViewController:listViewController];
[self addChildViewController:detailViewController];
listViewController.view.frame = CGRectMake(kListView_X, kListView_Y, kListView_Width, kListView_Height);
detailViewController.view.frame = CGRectMake(kListView_Width, kDetailView_Y, self.view.bounds.size.width, self.view.bounds.size.height-kDetailView_Y);
[self.scrollContainer addSubview:listViewController.view];
[self.scrollContainer addSubview:detailViewController.view];
[self.scrollContainer setContentSize:CGSizeMake(kListView_Width+self.view.bounds.size.width, self.view.bounds.size.height)];
}
When user selects new item from the list, you can swap DetailViewControllers as below
- (void) replaceEpisodeControllerWith:(DetailViewController *)detailViewController {
detailViewController.view.frame = CGRectMake(kListView_Width, kDetailView_Y, self.view.bounds.size.width, self.view.bounds.size.height-kDetailView_Y);
[UIView transitionFromView:currentDetailViewController.view
toView:detailViewController.view
duration:0.0
options:UIViewAnimationOptionTransitionNone
completion:^(BOOL finished)
{
[currentDetailViewController.view removeFromSuperview];
[currentDetailViewController removeFromParentViewController];
[currentDetailViewController release];
currentDetailViewController = detailViewController;
}];
}
I don't have swift version of this.

dismiss multipleViewControllers in iOS 5 and above?

I've an app which consists of a UITabBar with three views one of which is a UITableVIew. The first view that loads when the app boots is a UIView held within the UITabBar view. This view is a form for the user to fill in which takes them through five different screens. Previously I've been loading these as modal views one on top of the other and at the end dismissing them all when the user hits the final button like so:
[self.parentViewController.parentViewController.parentViewController.parentViewController dismissModalViewControllerAnimated:YES];
However since [self.parentViewController dismissModalViewControllerAnimated:YES] no longer works and has been replaced with [self dismissViewControllerAnimated:YES completion:nil]; I'm not really sure how to achieve this multiple dismissal of view controllers. I've tried adding the calls to parent view controller but that doesn't work. I've also tried:
[self.presentingViewController.presentingViewController.presentingViewController.presentingViewController.presentingViewController dismissViewControllerAnimated:YES completion:nil];
But that doesn't seem to work either. Any advice would be much appreciated. I'm also getting the message in the console: Application windows are expected to have a root view controller at the end of application launch. Is this what's causing the problem?
Please note, this is the first time in ages I've been programming for iOS, I've been devoting most of my time recently to Arduino and interfacting electornics with coding so this is a bit of a steep refresher course I'm on.
Help would be much appreciated.
If your five view controllers are pushed onto a UINavigationController, then they can all be dismissed/popped with one command:
- (NSArray *) popToViewController: (UIViewController *) viewController
animated: (BOOL) animated
[It doesn't appear that you are using a UINavigationController... but it wasn't entirely clear from your description.]

Return for the first view after I'm on the fifth view of an iOS application in Xcode

I'm fairly new to xcode, and am creating a single view application with five views (xib files). I am not using navigation controller or storyboard for two reasons.
If I use Storyboard, I am forced to have my other views be UIView files. These dont have
-(void)viewDidLoad
Which prevents me from loading a few timers I have in my application.
I am able to navigate from the first page to the second and so on, all the way to the fifth page/view with the following code.
-(IBAction)pagethree {
countdown=[[Countdown alloc] initWithNibName:#"Countdown" bundle:nil];
[self.view addSubview:countdown.view];
}
However when I want to go back from the fifth view to the first page I run into a problem.
My first view is called ViewController. If I try the code from above, my app is full of errors.
I also tried using
-(IBAction)back {
[self.view removeFromSuperview];
}
but that only took me back one view.
My fifth view controller is called Statistics and the first one is called ViewController.
What can I code to get from back from the last view to the first?
Thanks
First, to answer your question, you need to do a removeFromSuperview (or similar) for each addSubview: you did. Each time you do addSubview, you're placing your new screen "on top" of the last one, like a stack. When you reach your 5th view, you have 4 other views "behind" it. (Actually, that's not exactly what addSubview does, but I'm just describing the effect in your particular situation).
But I think you're doing it wrong... You should read more about storyboards and navigation controllers. Both are used with UIViewController and support out of the box what you're trying to do by hand. For example, using a navigation controller, to push a new view controller you can do:
[navigationController pushViewController:viewController animated:YES];
You can do that as many times as you want. Then, to go back once, you do:
[navigationController popViewControllerAnimated:YES];
And to go back directly to the first one:
[navigationController popToRootViewControllerAnimated:YES];
Hope this helps.

Different views depending on orientation on iOS

I know this question has been asked before, but how can I support a different view depending on my interface orientation in iOS 5?
An example by Apple shows a PortraitViewController and a LandscapeViewController. The PortraitViewController creates the LandscapeViewController and registers itself for rotation notifications. When it receives a rotation notification it either pushes or pops the LandscapeViewController depending on current interface orientation.
So far so good.
But how can I keep data both controllers have synchronized? (They display the same data obviously, since they are technically the same controller to the user, just with different views in landscape and portrait). Both have a "reload data button" which reloads their data. How can I tell the PortraitViewController to show the same data when the LandscapeViewController reloads it and vice versa?
Another problem is with memory warnings. When the interface is in landscape mode and I receive a memory warning my PortraitViewController gets unloaded. Now if I reload the data for my LandscapeViewController the PortraitViewController cannot do the same, because it is unloaded and has its Outlets still set to nil.
How do I adress all of these issues?
you actually first have to make new xib...
go to file - new - file
select user interface
select view
and so on to make new XIB
now select new view
go to identity inspector in right panel
add class name to connect the xib to old .h and .m files
important step...
connect new xib view with file's owner
now new xib is connected with the oldviewcontroller .h and .m
last step
in appdelegate use if statement to change the nibname based on IOS
for this you can use this..
[[UIDevice currentDevice] systemVersion]
in if statement you have to change initwithname with new view..
self.viewController = [[[ViewController alloc] initWithNibName:#"View" bundle:nil] autorelease
So what I ended up doing is using one ViewController with 2 views which shows a different view depending on interface orientation. The downside of this is that I have to connect all outlets twice and manipulate them twice.
But this way I can easily share my data and avoid one view being unloaded while the other isn't.
You should have a new class which will store your data. Both viewController will have a reference to this dataController (or whatever name you want).
You can also add a bit of logic on viewWillAppear and viewWillDisappear of your viewControllers.
Finally, for the memory warning issue, you can check on the viewWillAppear is the view is loaded and act accordingly.

NSView added as subview doesn't show

I have a puzzling problem. Working on a cocoa app in mac os x 10.7.
My app main window contains a split view. In a certain use context in one of the subviews of the split view is loaded a custom view with some labels (nstextfield) and a split view (instantiating a view controller that loads a nib and getting view from that controller). Frame of the custom view is set to split view subview bounds and everything works fine.
Problem is that one of the subviews of the second split view should be loaded (same method: view controller-nib-view-frame/bounds) with a custom view containing a table view and a button, but in this case nothing shows. Everything is done the same way but last custom view is not visible. Any idea?
Thanks
(edit)
this is the code I use to instantiate controller for the view to be added, get the view, and add it as subview to a subview of the split view
- (void)loadSubview {
self.subviewToAddController = [[viewController alloc] initWithNibName:nil bundle:nil];
//nib name is coded in the controller class definition
[[self.subviewToAddController view] setFrame:[self.splitViewContainerSubView bounds]];
//container subView is an outlet
[self.splitViewContainerSubView addSubview:[self.subviewToAddController view]];
}
However I don't think the problem is in this code because if I ask the container subview for its own subviews I can see the new subview is present in the list. It just doesn't show. If I add it as a subview of the split view (a test a just made) or as subview of the subview of the most external split view it is correctly showed too (sorry for the confused explanation, I would need a diagram but in this moment I can't make it)
To elaborate more my doubt (I didn't want to misled so I didn't mention before) can't it be a problem of coordinates, so view is correctly loaded and added as subview but is not visible because hidden by something or showed out of visible area?
(update)
Sorry it took so long to post an update.
After more testing I found out the problem is related to autolayout. No idea what the exact problem is and how to solve it. I ended up turning it off for the nibs the were in troubles and use the old way to set interface objects position and size/resize. Not the best way but for now I can go on.
My best guess is that you didn't set the autoresizing masks of the view properly.

Resources