My project is using ARC and objective c. And i'm having troubles with the
ViewControllers that is created inside my scrollview. They dont get removed
completely.
What i did was that i have created a UIScrollView inside the main
ViewController. Then i have created 2 other ViewControllers.
I'm placing the 2 viewControllers inside the UIScrollView like that:
ViewController1 * test1 = [[ViewController1 alloc] init];
ViewController2 * test1 = [[ViewController2 alloc] init];
[scrollview addSubview:test1.view];
[scrollview addSubview:test2.view];
it works and i can see both of my design from the viewControllers. But when i try to remove both viewControllers from the main viewController and add them back later it create new views, but the same old views still exist underneath. I want to completely remove them from the main viewController and create new ones instead.
i'm removing them like that:
[test1 removeFromParentViewController];
[test2 removeFromParentViewController];
[test1.view removeFromSuperview];
[test2.view removeFromSuperview];
The code where i'm adding new views for the second time is like the first one, but here it is:
ViewController1 * test1 = [[ViewController1 alloc] init];
ViewController2 * test1 = [[ViewController2 alloc] init];
[scrollview addSubview:test1.view];
[scrollview addSubview:test2.view];
but i'm only doing this when the remove is done.
FIXED IT:
The problem was that i was using block-based notification handlers which sometimes stops the app from calling dealloc to release my viewcontrollers. I tested that anything that use block-based stuff will kind block the app from calling dealloc the fix is to stop/free the block-based notification and then make a remove call of the views.
FIXED IT:
The problem was that i was using block-based notification handlers which sometimes stops the app from calling dealloc to release my viewcontrollers. I tested that anything that use block-based stuff will kind block the app from calling dealloc the fix is to stop/free the block-based notification and then make a remove call of the views.
Related
I am little confuse because my dealloc is not called in ARC. I have using storyboard in my application.
Case 1: Mydealloc called when i use all IBOutlet from storyboard
Case 2: My dealloc is not called when i try to use alloc and init methods in UIViewController. such as below.
UIViewController *vc = [[UIViewController alloc] initWithNibName:#"ProfileDetailView" bundle:nil];
__weak ProfileDetailView *detailview = (ProfileDetailView *)vc.view;
detailview.backgroundColor = [UIColor clearColor];
vc = nil;
....Set value in object.....
[self.view addSubview:detailview];;
detailview = nil;
Can you explain why dealloc is not called? and How can i able to achieve to call dealloc?
Thanks
The concept of ARC is that an object's retain count should theoretically be 1 in order for it to be deallocated. When you execute:
[self.view addSubview:detailview];;
Your self.view increments detailview's retain count by 1 when it adds it to view.subviews. Logically, when self.view removes detailview, the retain count is decremented by 1.
Again, this is a theoretical perspective. The reality is usually:
INSANE.
No one really knows how the mysterious Objective-C runtime works! (just kidding the whole source code is available online.)
Thanks for your reply. I am able to called my dealloc function when view controller pop. For achieving that, we need to remove my added subviews from my view when user tapped on back button.
I am implementing MDSpreadView, a third party controller, in one of my projects. I have simply included every file related to it including xib. Calling it as subview.
The hierarchy of calling views is like this: there is a uiviewcontroller in which I am adding UIView as subview, and from that subview I am calling uiviewcontroller as subview.
MDViewController *MDvc = [[MDViewController alloc]initWithNibName:#"MDViewController_iPhone" bundle:nil ];
[self addSubview:MDvc.view];
It Appears fine but when I touch to scroll or select or for anything, Thread 1:EXC_BAD_ACCESS error occurs at selection delegate. Whereas delegates are implemented as it is in demo proj.
here is the image
I know there is some issue in calling subviews. How do I solve this?
The idea of taking a view out of one controller and inserting it as a subview in a different controller is a common cause of crashes. If you have to do it, make sure that the original controller (MDViewController in this case) is not released. You can do that by making it a strong property of the object that is hijacking its view or, better, look at the documentation for how to implement a container controller.
Finally get to know how to handle multiple views, especially when you have subviews and viewcontroller. Solution is very simple , in such situations you need to have delegates or there is a great thing which apple gives itself is NSNotification. I did solve my problem through NSNotification. On the button press(from where i have to call other view) i post a notification like this:
[[NSNotificationCenter defaultCenter] postNotificationName:#"WhatEverYouWantTocallIt" object:nil];
and i added observer in the class which i needed to call, like this:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(bringSpreadViewToFront) name:#"WhatEverYouWantTocallIt" object:nil];
AND added a selector, in selector u should handle it according to scenario you have i did this:
-(void)bringSpreadViewToFront{
NSArray *viewsToRemove = [self.view subviews];
for (UIView *v in viewsToRemove) {
[v removeFromSuperview];
}
MDViewController *md = [[MDViewController alloc] initWithNibName:#"MDViewController_iPhone" bundle:nil];
[self presentViewController:md animated:YES completion:nil];
}
i first removed the subviews one by one and then present my view controller, presenting pushing its your choice. it works perfect.. Cheers :)
Thank you Phillip for pushing me in a direction close to the solution.
I'm facing a strange problem..
I want to add a UIViewcontroller (called iView) to my current View.
I do it by calling
iView = [[KFKaraokeInfosView alloc] initWithKaraoke:karaoke NibName:#"InfosView" commingFromPlayer:NO];
iView.songTitle.text = karaoke.title;
[self.view addSubview:iView.view];
In the viewDidLoad of iView, I add it as an observer to the NotificationCenter for a certain notification, like this
- (void)viewDidLoad
{
[super viewDidLoad];
self.title = #"About";
if ([karaoke.styles count] == 0)
{
[[NSNotificationCenter defaultCenter] postNotificationName:#"GetInfosOfSong" object:self.karaoke];
}
else
{
shouldSetup = YES;
}
[self.navigationController setNavigationBarHidden:NO animated:YES];
[self.navigationController.navigationBar setBarStyle:UIBarStyleBlack];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(setup) name:GetSongInfos object:nil];
[optionsTableView setBackgroundView:nil];
}
The problem is when I call autorelease method on iView at the initialisation, the notification is never catched (so setup method is never called), but if I don't call autorelease for iView, it works.
I don't understand the memory management in this situation, can someone help me to understand ?
The container view controller methods are found in Implementing a Container View Controller of the UIViewController Class Reference, and sample code can be found in Creating Custom Container View Controllers of the View Controller Programming Guide.
Thus, in iOS 5 and later, you should probably have:
iView = [[[KFKaraokeInfosView alloc] initWithKaraoke:karaoke NibName:#"InfosView" commingFromPlayer:NO] autorelease];
[self addChildViewController:iView];
iView.songTitle.text = karaoke.title;
[self.view addSubview:iView.view];
[iView didMoveToParentViewController:self];
If this is iOS 4 or earlier, it doesn't support proper containment. You can manually kludge it, by adding the view like you are, with no autorelease:
iView = [[KFKaraokeInfosView alloc] initWithKaraoke:karaoke NibName:#"InfosView" commingFromPlayer:NO];
iView.songTitle.text = karaoke.title;
[self.view addSubview:iView.view];
You'd obviously keep a copy of the child view controller in some ivar of the parent view controller, not autorelease it, but rather explicitly release the child's controller when the child's view is dismissed. Note, since you're operating in a pre-containment iOS4 world, your child controller is not guaranteed of receiving various events (notoriously rotation events). But you should receive your notification center events.
An alternative to this ugliness of trying to fake containment in iOS 4 is to not use a child view controller at all, but just add the child view to the parent view. You can actually add it to the parent controller's NIB, but just hide it. Then, when you want to present it, unhide it. But keep everything in the parent view controller and it's NIB. The method that I described above, faking containment, might work (I've seen people do it), but it gives me the heebie jeebies. This is simpler.
I am inside a root view controller. and then allocate the secondviewcontroller
SecondViewControl *second=[[SecondViewControl alloc] init];
[self presentModalViewController:second animated:NO];
The second viewcontroller 's view not showing up
AddSubView method works though.
[self.view addSubView:second.view];
why presetModalViewController is not working?
Usually you'll allocate the SecondViewControl with a .xib file that actually defines the user interface. Consider using a line like this (broken for readability):
SecondViewControl *second = [[SecondViewControl alloc]
initWithNibName:#"SecondView"
bundle:nil];
Without the accompanying .xib to define the view, you may be left with a view controller that doesn't have the necessary properties set to actually support user interaction, and so presentModalViewController: may have trouble there.
I'm attempting to embed an editable UITextView inside a UIPopoverController, with... strange results. The steps I've taken are:
Create a custom UIViewController class, and create a .xib file with that controller with a UITextView inside it.
When the UI action that should bring up the controller occurs (touch up inside), I instantiate the controller and its view from the .xib file.
I create a new UIPopoverController, with the view controller I just instantiated as the content view.
I present it with presentPopoverFromRect:inView:permittedArrowDirections:animated:
Here's some example code:
- (void)noteButtonPressed:(id)sender {
self.noteview = [[MyTextPopupViewController alloc] initWithNibName:#"MyTextPopupViewController" bundle:nil ];
UIPopoverController *popoverController = [[UIPopoverController alloc] initWithContentViewController:self.noteview];
self.popover = popoverController;
self.popover.delegate = self;
[self.popover presentPopoverFromRect:((UIView*)sender).frame
inView:self.view
permittedArrowDirections:UIPopoverArrowDirectionAny
animated:YES];
}
Then, inside MyTextPopupViewController, I make sure the the text view is the first responder to bring up the keyboard:
- (void)viewDidAppear:(BOOL)animated {
[self.view becomeFirstResponder];
[super viewDidAppear:animated];
}
And that all works... right until it doesn't. Sometimes, it works perfectly; other times, either immediately or after a few keystrokes, the application crashes by exiting the main event loop (!). No exception is thrown (at least not that the lldb catches), but the application simply stops, both on the simulator and on hardware.
Any thoughts? Has anyone gotten this working successfully, or knows for sure that it does not?
I think the UIPopoverController instance needs to be a property in your code.