Using buttons on different views and classes to trigger view switch from the main view controller - cocoa-touch

I am using storyboard to create my page.. each with it's own class... from the mainViewController, I manage the view change with a swipe gesture recognizer... So far so good... But I have certain pages that will appear as "popup" when swiping up and to get rid of them, the user clicks on the X to remove the view... the thing is that doing this and releasing the view from superview is giving me a white screen as the switch is not done by the mainViewController, since the view is release by the popup class... I think I need to use some sort of delegation to do this.. but my brain just doesn't want to sink in how to use the delegate thing, even after reading about it...
Since the view switching is done on index 1, i'd figure that if I put those popup on index 2 and release them, the view at index 1 would still be there, but.. no..
... so at the beginning of my swipe gesture function, I start declaring the animation process... then I have a switch...case that check for the gesture being done.. left will set the animation to curlUP and right to Curl down... this is what happens after the switch... I also put myView into a myViewTemp, and add the new view to myView in the switch..case statement..
if (myView.title == #"popup1") {
[myView viewWillAppear:YES];
[myViewTemp viewWillDisappear:NO];
// [myViewTemp.view removeFromSuperview];
[self.view insertSubview:myView.view atIndex:2];
[myViewTemp viewDidDisappear:NO];
[myView viewDidAppear:YES];
} else {
[myView viewWillAppear:YES];
[myViewTemp viewWillDisappear:YES];
[myViewTemp.view removeFromSuperview];
[self.view insertSubview:myView.view atIndex:1];
[myView viewDidDisappear:YES];
[myViewTemp viewDidAppear:YES];
}
[UIView commitAnimations];
}

Related

Displaying NSPopOver

I have a class which is derived from window controller with xib which has all the functionalities. In this xib i have a tableview which displays the list of halls. If i double click on a hall name, i ll get a popover, which displays the features of that hall. I have a view controller class, in which i would ilk to create the pop over programatically,
NSPopover *popover;
NSViewController *popoverViewController;
-(void)displayPopover{
popover = [[NSPopover alloc] init];
[popover setBehavior: NSPopoverBehaviorApplicationDefined];
[popover setDelegate: self];
popoverViewController = [[CHBPopover alloc] initWithNibName: #"MYViewController" bundle: nil];
[popover setContentViewController: popoverViewController];
[popover setContentSize: popoverViewController.view.frame.size];
[popover showRelativeToRect: NSMakeRect(700, 400, 5, 5)
ofView: [[NSApp keyWindow] contentView]
preferredEdge: NSMaxXEdge];
}
In my window controller class, i have a method like,
-(IBAction)featuresDisplay:(id)sender{
if([_hallNamesList selectedRow] == -1){
[self setFeaturesList:nil];
}
else {
//[self.hallFeaturesPopOver showRelativeToRect:[_hallNamesList frameOfCellAtColumn:0 row:[_hallNamesList selectedRow]] ofView:_hallNamesList preferredEdge:NSMaxXEdge];
// [pop.displayPopover ];
NSDictionary *hallFeaturesDictionary;
hallFeaturesDictionary = [_hallNames objectAtIndex:[_hallNamesList selectedRow]];
_hallId=[hallFeaturesDictionary valueForKey:#"hallId"];
[officeDetails setHallName:[hallFeaturesDictionary valueForKey:#"hallName"]];
_featuresList=[conferenceHall getConferenceHallFeaturesWithDetails:officeDetails];
NSLog(#"features list=%#",_featuresList);
[self setFeaturesList:[conferenceHall getConferenceHallFeaturesWithDetails:officeDetails]];
}
}
How would i call that popover method in this IBAction? I need to double click on a row and display the pop over.. How would i do this? Thanks.
The display coordinates seem to be quite off. The rectangle for the popover is relative to the ofView parameter. Start with (0, 0) here, which should display the popover in the upper left corner of your keywindow.contentView. Then fine tune the position. You probably have to pass in the actual rectangle from your IBAction (probably the table cell bounds). The size part in the view rect for the popover is important because the popover moves relative to that. I'd also pass in the view to attach the popover to, as sometimes a view does not become key when you click it.
Note that the delegate for the popover is only necessary if you plan to implement detaching it into a floating window. Experiment also with the behavior. Start with NSPopoverBehaviorTransient. I'm not sure what you actually have to do with the application defined behavior but at least with the transient behavior it works fine for me.
Finally, you don't need to recreate the popover every time you show it. Just set it up in awakeFromNib and then just call showRelativeToRect... every time you need it. With the transient behavior it will automatically disappear.

Superview is Nil after Second Launch of View Controller

I've spent hours and I cant figure this out. I have a detail view controller (UITableView) which is launched here:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
EventLocationDetailController *newDetailViewController = [[EventLocationDetailController alloc] initWithNibName:#"EventLocationDetailController" bundle:nil];
self.eventDetailController = newDetailViewController;
[self.navigationController pushViewController:self.eventDetailController animated:YES];
[newDetailViewController release];
}
In the detail view controller there is a button method which calls the below method to display a slide-in-slide-out animation confirming the users choice:
-(void)confirmLastActionWithMessage:(NSString *)message {
ConfirmActionViewController *newConfirmActionViewController = [[ConfirmActionViewController alloc] initWithNibName:#"ConfirmActionViewController" bundle:nil];
self.confirmActionViewController = newConfirmActionViewController;
[newConfirmActionViewController release];
[[self.view superview] addSubview:self.confirmActionViewController.view];
}
Protocol method called by the ConfirmActionViewController indicating that the animation is finished.
-(void)didFinishConfirmDisplay:(UIView *)viewToRemoveFromSuperview {
[viewToRemoveFromSuperview removeFromSuperview];
}
This works perfect the first time I press the button. If I pop the detail controller and push it back on to the stack and press the button again, nothing happens and the detail controller's superview is nil every time I invoke the method after that. Superview is not nil in the viewWillAppear method for the detail view, only when It gets to the confirmLastActionWithMessage method. No other user interaction happens in between. How do I get the superview back? I have a similar code that works without animation.
I've also noticed that the detail view controller hasn't called dealloc when popped off the stack. Not sure where the problem is.
Thanks.
EDIT 1
OK. I replaced the addSubview line with this one:
[self.view insertSubview:self.confirmActionViewController.view atIndex:0];
and the animation view appeared underneath one of the table cells. Could one of the table cells steal the superview?
Well I don't really understand why you should add the subview to the superview. Why not add it just to self.view
I may not be able to explain why there is no superview but try either adding the controller view to self.view or
[[[[UIApplication sharedApplication] delegate] window] addSubview:yourview];
This will render the view on top of everything.

Trouble with gesture recognizers in subviews

I'm having a rather basic problem, I've looked around (here, google, etc) and haven't found a solution for this:
In my View Controller's viewDidLoad, I have this:
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(myfunc:)];
//I have a UIScrollView named "containerView"
//here's some code that creates an UIView in a variable named "myView"
//this works fine, I can see "myView" when I run it
[containerView addSubview:myView];
[myView addGestureRecognizer:longPress];
and then I have this function in the same class:
- (void)myfunc:(UIRotationGestureRecognizer *)recognizer
{
NSLog(#"hola!"); //never runs
}
The call to NSLog never runs. What am I doing wrong?
EDIT
Some extra info: it seems no touch events are ever sent to the subview. However, I tried adding an UIView with a button inside, all in the UIScrollView, and the button receives the touch event just fine, so the problem is only with programmatically added subviews.
Strangely enough, adding a "container" UIView inside the UIScrollView, and then the other subviews inside this container, made it work. Now touch events are sent to the subviews.
How can a superview interecept a touch sequence before any of its subviews?
TLDR:
[containerView setCanCancelContentTouches:NO];
do it just as you add the gesture recogniser to the scroll view.
also look into
[containerView setDelaysContentTouches:NO];
If the above behaviour isn't quite right.
for more info:
http://developer.apple.com/library/ios/#documentation/UIKit/Reference/UIScrollView_Class/Reference/UIScrollView.html
I think on myFunc you must do somethings like that:
switch (reconiger.state)
{
case UIGestureRecognizerBegin:
//Do something when start recognizer
break;
case UIGestureRecognizerEnd:
//Do something when end recognizer
break;
}

Use UISegmentedControl to switch to a MKMapView and UITableView

I'm making an app and i have a view controller with a UISegmentedControl, and a want to switch between a MKMapView and a UITableView.
In the MKMapView i want to display a map with the users current location, and in the TableView i want to list some data. Thats it.
Sounds simple but i'm don't know how to proceed, i tried to make my view controller a tableview controller and then add the MKMapview, also tried to just add both views and a simple view controller. Anyway, there is a right or better way to do that?
Thanks guys!
You can use target-action to have the segmented control hide one view and unhide the other when it's value is changed:
- (void)segmentChanged:(id)sender
{
switch ([sender selectedSegmentIndex]) {
case 0:
{
self.tableView.hidden = NO;
self.mapView.hidden = YES;
break;
}
case 1:
{
self.tableView.hidden = YES;
self.mapView.hidden = NO;
break;
}
default:
break;
}
}
add both as subview
then whenever you want to switch just do
[self.view bringSubviewToFront:YOURVIEW];
The clean way would be to switch the subview, as soon as the button is pressed.
[view1 removeFromSuperView];
[self.view addSubview: view2];
For better performance you could save both views as a member variable, so they don't get instanciated every time.
You could even add a Viewtransition, when doing it in that way. (Eg flipping or fading)
Also in iOS5 you could write your own ViewControllerContainer. But thats way too complicated for that task.
I would use 2 navigationControllers.
Declare your first navigationController as usual, then when user tap the segmentedControl, create your tableController with another navigationController, and display it as modalViewController.
UINavigationController* modalController = [[UINavigationController alloc] initWithRootViewController:tableViewController];
[modalController setToolbarHidden:NO];
[self.navigationController presentModalViewController:modalController animated:YES];
[modalController release];
Then, when user tap the tableViewController's segmented control, just dismiss the viewController.

Trying to dismiss subview and UIView

I'm still very new to iOS developing. In fact, if there is a super noob, I would be one :p. Currently I am working on creating an IBAction button that accesses a subview. I have 2 ViewControllers, AddClientVC and NewClientVC, both with .nib files. So basically, inside my AddClientVC I implement an IBAction button with the following code:
- (IBAction)buttonPressed:(id)sender
{
UIView *transparentBG = [[UIView alloc] initWithFrame:CGRectMake(-5, -5, 1500, 2500)];
transparentBG.backgroundColor = [UIColor blackColor];
transparentBG.opaque = NO;
transparentBG.alpha = 0.5;
[self.view addSubview:transparentBG];
transparentBG.center = transparentBG.center;
vc = [[NewClientVC alloc] initWithNibName:#"NewClientVC" bundle:nil];
[self.view addSubview:vc.view];
vc.view.center = self.view.center;
}
As you can see I implemented a UIView as a transparent background. Basically AddClientVC --> Transparent Background --> NewClientVC. Now I have created another IBAction button but this time inside NewClientVC as a function to dismiss the accessed subview which looks like this:
- (IBAction)saveDismiss:(id)sender
{
[self.view removeFromSuperview];
}
The problem I'm having right now is when I click the saveDismiss button it only removes the subview that I called previously on AddClientVC but it didn't remove the transparent background I have created as a UIView. So the problem is how do I implement an action which simultaneously removes my subview and the UIView transparent background I created.
I need all the help I can get :)
I'm not too sure I fully understand what you want to happen, but maybe you could try something like this?
- (IBAction)saveDismiss:(id)sender
{
[vc removeFromSuperView];
[self.view removeFromSuperview];
}
I recommend not to manage your screens by adding subviews manually but instead use
- (void)presentModalViewController: (UIViewController *)modalViewController
animated: (BOOL)animated
method on your root viewController.
Or better instantiate a UINavigationController and use push and pop methods to drill down/up your views.
See apple reference here
Do not worry about code execution speed and stay confident in apple's SDK. UIKit is optimized for best user experience. Trying to boost your code by doing inappropriate SDK use is, in my opinion, a risky strategy. ;) – Vincent Zgueb
Sorry Vincent but I don't agree with you. I reached here because I want to implement an gesture that adds a sub-view for my view, which will be the navigation of my app.
[self.view addSubview:ctrl.view];
is faster presenting the view than
[self.navigationController presentModalViewController:ctrl animated:NO]
and by the way, the solution to the topic in my case was:
[self.view sendSubviewToBack:ctrl.view];