Setting default segment in UISegmentedControl - ios5

I have an app that has two viewcontrollers Viewcontroller and OptionsViewController. Viewcontroller is the initial viewcontroller then if I click a button I have a modal segue to optionsviewcontroller.
There in optionsviewcontroller I have I UISegmented viewcontroller created from the storyboard which is linked to an outlet (UnitsSegmentedControl) and I want to be able to tell the segmented control which segment should be selected by default when OptionsViewController loads.
In my Viewcontroller I wrote a method:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
OptionsViewController *ovc=[segue destinationViewController];
ovc.delegate=self;
[ovc.UnitsSegmentedControl setSelectedSegmentIndex:1];
}
the thing is when OptionsViewController loads the view the selected index is 0 as by default. I don't get any error message or something.
I'm using Xcode 4.2. I think It might be some option I can change in storyboard to make the UISegmentedControl to be able to set default selected index. I don't know what else could be causing that.
EDIT:
I figured out that if I write :
[ovc.UnitsSegmentedControl setSelectedSegmentIndex:1];
inside OptionsViewController method viewdidload everything works fine. Why am I not able to do it from the prepare for segue method?

The segmented control does not exist until the OptionsViewController is loaded which is why you cannot set the selected segment in the prepareForSegue method of you ViewController. Review the UISegmentedControl Class Reference reveals that there is no way to set a default state:
"The default value is UISegmentedControlNoSegment (no segment selected) until the user touches a segment. Set this property to -1 to turn off the current selection. UISegmentedControl ignores this property when the control is in momentary mode. When the user touches a segment to change the selection, the control event UIControlEventValueChanged is generated; if the segmented control is set up to respond to this control event, it sends a action message to its target."
Setting the selectedSegmentIndex in the viewDidLoad method of your OptionsViewController is the correct way to set a default value the view controller.

Just use this code if you want to do it programmatically
segmentControl.selectedSegmentIndex=-1;
If you want to set it from nib then in interface builder just uncheck selected property of index

Related

Storyboard: Condition segue transition for navigation (push)

I am new to storyboard and xcode (using 4.6)
I m using Navigation Storyboard with push segue.
I would like to implement a select snap view, that if have minimum 1 snap selected - the segue would work. Otherwise, the user should stay on the same view.
I created 2 UIView: SelectSnapsViewController and ShippingDetailViewController.
In SelectSnapsViewController.m I added the following:
- (IBAction)nextButtonPressed:(id)sender
{
looseDataAlert = NO;
[okkkBtn setFrame:CGRectMake(116, 272, 72, 37)];
if ([appDelegate.selImageDetails count] == 0)
{
label1.text = #"To proceed you need to add snaps.";
[self openAlertView];
}
else{
[self performSegueWithIdentifier:#"MySegue" sender:self];
}
}
When I debug the code - I see that the it always fall in else case of condition, however the segue (transition to the new view) still happens.
How can I prevent the user to be transferred to the new view?
There are two ways to implement conditional segues.
1) Configure the Segues as 'manual' from the ViewController and invoke performSegueWithIdentifier conditionally within your IBAction method that you wire up to event handling for your button.
OR 2) Configure the Segue as a 'Triggered Segue' from your button and implement - (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender in your view controller to perform the conditional logic.
Are you saying that you only want to perform the segue if a condition is true?
If so, instead of creating the segue directly from a control or table cell, create a triggerless segue. A triggerless segue has the view controller as its source, and it won't ever fire automatically. Instead you can fire it programmatically any time you like, including from an IBAction.
To create a triggerless segue, start control+dragging the segue from the containing view controller icon in the scene dock at the bottom of the scene. Drag to the destination scene like normal, and pick the segue type. Select the segue, and in the inspector, choose a segue identifier.
At runtime, when you want to perform the segue, invoke -[UIViewController performSegueWithIdentifier:sender:]. You can pass any object you'd like for the sender, including nil. If the sender has no use to you, pass nil.
So, in summary:
Create a triggerless segue from the view controller to the destination scene
Set an identifier for the segue in the inspector
At runtime, and form code, call -[UIViewController performSegueWithIdentifier:sender:] when you want to trigger the segue.

Controlling a button text from another view

I have two views and i used two view controllers. From the main view i want to initialize the button in the second view with a certain text.
If I press the button in the second view, then i can store that button reference to a global UIButton, and change the text then onwards.
But the very first time, how can I initialize the button text in the second view from my main view with a particular text ?
You should not do that: every controller should be responsible for its own view. Full stop.
You can always set some poperty on the second controller and use it when the second view appears on the screen to change whatever you like.
you use delegates & #protocol to access other class example,
refer ex, ex1, link
Not sure how you did this. But if you post some code, it will be helpful. If you already have the above code working, then you need to have the following in order for what you are expecting to work.
Say you have ViewControllerA, ViewControllerB as the two view controllers. You can definitely initialize the text in the button when you create the XIB file.
But I am assuming that you want to do this programatically. If you want to access a button in another view controller, you need
a. Access to the other view controller.
b. Once you have access to the other view controller, access to the UIButton variable in that view controller.
So you can do the following in the ViewControllerA code,
-(void)changeButtonTextOfVCB{
viewControllerB.button setTitle:#"MyTitle" forControlState...
}
and you can have a button in viewControllerA, which will trigger the above method.
Having said this, I am not sure whether you have the whole thing working, where you can even switch between the view controllers
If you make a button in FirstViewController and want to change button properties like title..etc from the second view, then you should make properties in SecondViewController
#property (nonatomic,assign) UIButton *button;
when you navigate firstViewController to secondViewController just pass the button Object like
obj = [SecondViewController alloc]...]
obj.button = button;//(FirstViewController button object)

Add button in UITabBarController in Storyboard

I have the following storyboard:
In the tab bar controller I have a add button with a segue to a view controller. I need to use the method "prepareForSegue:" because I need to transfer an object but in the Repositories Table View doesn't fire the method.
How can I detect the method "prepareForSegue:" in the Repositories Table View? Is it possible?
I suppose for "detect the method prepareForSegue" you mean "identify the right segue in the prepareForSegue method".
You do this by using [segue identifier] and the string comparison method isEqualToString: to compare it to what you set the Identifier to be in storyboard.
Also, make sure that the button, table view cell, button or other element is attached to the right segue. You can of course do that in storyboard as well. If you need to do it in code e.g. because the button is created programmatically, you will have to call the segue yourself. In the button handler you just use
[self performSegueWithIdentifier:"SegueIdentifier" sender:self];

UIPopoverController on UITableViewCell

I have a UITableView cell with several UITextFields in it. When a user clicks into one of the textFields, a popover appears with some information. At first, they then had to click outside of either the textField or the popover to clear the popover before then clicking into the next textField. I therefore then added the cell's contentView to the popover controller's passThroughViews property so they can click through the different textFields in that cell at will without having to dismiss the popover controller first. However, it keeps the original popover open (which) is fine, and then opens another identical popover as well.
Is there a way I can tell if a popover is already open before sending the command to open another? I can't think of how to detect this?
If each cell controls the logic of the popover, you need to say to your custom cell to implement UIPopoverControllerDelegate protocol, set the delegate for the popover as self (the cell) and override popoverControllerDidDismissPopover like the following:
- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController
{
[self.pop dismissPopoverAnimated:YES]; // hide the popover
self.pop = nil; // release the popover, this forces to create a fresh popover each time
}
If you want you can also remove the line self.pop = nil; but remember to release it in dealloc (I suppose you are not using ARC code since you are using retainCount). As bbum suggested you should't use retainCount to check objects existence.
In addition, each UIPopoverController instance has a property called popoverVisible if you want to see if a popover is already visible or not.
OK, I did it. For others who find this question. In addition to the other answers, this is how I did it.
I made my view controller a UIPopoverControllerDelegate.
I then created an BOOL called myPopoverControllerOpen.
When I created my popover I set the BOOL to yes. Using the delegate method popoverDidDismissPopover I then set the BOOL back to NO.
I then check on the state of this BOOL before presenting the popover.

Drag-n-Drop from UIPopoverController to other UIView

How would I go about implementing dragging and dropping a UIView from UIPopoverController into the back UIView.
This is the functionality that Pages provide in their insert media popover, where you can drag a shape out from the UIPopoverController and drop it into the main document.
I am actually confused with the pan UIGestureRecognizers and where they will be implemented.
Thanks,
Umer
According to the documentation on UIPopoverController, when the popover is presented, it is presented on a special "window". Because of this, simply adding a subview to the popover view controller's content view controller is not sufficient to be able to drag a view outside of the popover view controller's view.
The easiest solution here is to create your own window, add your drag-able view to the window when dragging occurs. Make the window visible for the duration of the drag/drop, and then release your window when complete.
As mentioned above, gesture recognizers (GR) are best suited for Drag/Drop functionality. Once the GR's state has changed to "Began" the GR will control all touches until the "Ended" or "Cancelled" state is achieved which makes it ideal for dragging views between view controllers as well as windows :)
Example:
#interface MySplitViewController : UISplitViewController {
UIView *dragView;
UIWindow *dragWindow;
}
Implementation:
NOTE we do not need to call "makeKeyAndVisible" on our window. We just need to set its "Hidden" property
From Apple in regards to the makeKeyAndVisible method:
// convenience. most apps call this to show the main window and also make it key. otherwise use view hidden property
-(void)dragBegan{
self.dragWindow = [[UIWindow alloc] initWithFrame:self.view.window.frame];
[self.dragWindow addSubview:self.dragView];
[self.dragWindow setHidden:NO];
}
Here we handle the Gesture Recognizer's "Ended" or "Cancelled" state.
NOTE: It is important to remove the window when the Drag/Drop is complete or you will lose user interactiveness with the views below.
-(void)dragEnded{
[self.dragView removeFromSuperview];
[self.dragWindow setHidden:YES];
[self.dragWindow release];
[self.view addSubview:self.dragView];
}
You have to deal with two view controllers one that's in the background called mainController one that presented using a UIPopoverViewController called popoverController. Your popoverController could add a UIPanGestureRecognizer to the views, that the user can drag. The action target of the gestureRecognizer could be a method on the popoverController.
Once the user starts a dragging operation your action method is called with the gestureRecognizer as an argument, were the state of the gestureRecognizer is UIGestureRecognizerStateBegan. You could than save the current frame of the view somewere to be able to animate it back, when the dropping fails. It might be necessary to move the view to an other superview (the window for example), because I'm not sure if UIPopoverViewController clipsToBounds its view.
As the user draggs, your action method is called over and over with the gestureRecognizer in the state UIGestureRecognizerStateChanged. Use the translationInView: method on UIPanGestureRecognizer to determine how much the user dragged and update the dragged views center/frame/transform accordingly.
Once the user lifts his finger the action method is called for a last time with the gestureRecoginzers state set to UIGestureRecognizerStateEnded. Now it's time to find out if the drag was successful. For example the popoverController could ask the mainController via delegation if there's a drop target under the views current position, if so the mainController can take action, else the popoverController would animate the dragged view back to were it came from, and add it back as a subview to it's view.
I hope this is somehow comprehensible and helpful.