When I start my iPad app, I want to display a screen that slides in on top of the main view that is there at the start up. I want this screen to take up the entire screen and display a web page, and the only way that the user can get out of it is click on a UIButton at the bottom of the screen.
Right now, I am setting the view of my main view controller as the view that I want to display, but the next step in execution is showing a UIAlert, and this alert is appearing.
What can I use to have this pop up wait for the user to click Agree before continuing?
Thanks.
You will want to use a delegate.
So to do what you want do something like this (I don't know your actual class names, so I'm guessing):
In your AlertScreenViewController.h file add this code:
#protocol AlertScreenViewControllerDelegate;
#interface AlertScreenViewController : UIViewController {
...
id<AlertScreenViewControllerDelegate> delegate;
...
}
...
#property (assign) id<AlertScreenViewControllerDelegate> delegate;
...
#end
#protocol AlertScreenViewControllerDelegate <NSObject>
- (void)alertScreenViewControllerWillClose;
#end
Then in your AlertScreenViewController.m file:
add this:
#implementation AlertScreenViewController
...
#synthesize delegate;
...
#end
add this code wherever your button is pressed:
[self.delegate alertScreenViewControllerWillClose];
In your MainViewController.h file add this:
#import "AlertScreenViewController.h"
#interface MainViewController : UIViewController <AlertScreenViewControllerDelegate> {
...
}
...
#end
In your MainViewController.m file add this:
Wherever you've loaded up the AlertScreenViewController add this after the init call:
alertscreenviewcontroller.delegate = self;
Then move all code after the display of the alertscreenviewcontroller code to this method:
- (void) alertScreenViewControllerWillClose {
//UIAlert logic here
}
You can find another example here: http://www.dosomethinghere.com/2009/07/18/setting-up-a-delegate-in-the-iphone-sdk/
Or just google iphone sdk delegate
Related
I am working on an iOS project and wanted to include a UIView that is reused on multiple screens in the application (appearing at the bottom of different UIViews). I am using a storyboard for the UI work so far but created an .xib file to be used by the reusable view (playerView in code below).
The view gets added but the button I have added to the View is unresponsive, also my background color cannot be changed on the view. I have tried to set background color programmatically and in the .xib with no luck. Very weird symptoms and I tried to instantiate the view from #5 of this article and probably did something wrong. I dont fully understand everything in the article which makes me nervous - for instance my showSubclassedView method returns IBAction but I just call the function name in code and dont use a button (I did hook up the buttons in the view as the article described though).
Here is the code:
EventViewController.m (where I trry and add PlayerView)
#import "EventViewController.h"
#import "PlayerView.h"
#interface EventViewController ()
-(IBAction)showSubclassedView;
#end
#implementation EventViewController
-(IBAction)showSubclassedView
{
[PlayerView presentInViewController:self];
}
PlayerView.h (.h for reusable view)
#import <UIKit/UIKit.h>
#import "Utils.h"
#class PlayerView;
#protocol PlayerViewDelegate
-(void)playerViewTouchedUp:(PlayerView*) playerView;
-(void)playerViewDidDismiss:(PlayerView*) playerView;
#end
#interface PlayerView : UIView
+(void)presentInViewController:(UIViewController<PlayerViewDelegate>*) playerView;
-(IBAction)viewTouchedUp;
-(IBAction)dismiss;
#end
PlayerView.m (.m for reusable view)
#import "PlayerView.h"
#interface PlayerViewOwner : NSObject
#property(nonatomic,weak) IBOutlet PlayerView *playerView;
#end
#implementation PlayerViewOwner
#end
#interface PlayerView ()
#property (nonatomic, weak) UIViewController <PlayerViewDelegate> *delegateViewController;
#end
#implementation PlayerView
+(void)presentInViewController:(UIViewController<PlayerViewDelegate> *)viewController
{
PlayerViewOwner *owner = [PlayerViewOwner new];
[[NSBundle mainBundle] loadNibNamed:NSStringFromClass(self) owner:owner options:nil];
owner.playerView.delegateViewController = viewController;
[viewController.view addSubview:owner.playerView];
}
-(IBAction)viewTouchedUp
{
//forward to delegate
NSLog(#"you clicked a button");
[self.delegateViewController playerViewTouchedUp:self];
}
-(IBAction)dismiss
{
[self removeFromSuperview];
// Forward to delegate
[self.delegateViewController playerViewDidDismiss:self];
}
#end
PlayerView.xib has a UIbutton on it that connects it to viewTouchedUp method in PLayerView.m
Is there anything I did wrong in the code above? Is this the best way to do a reusable view to display on other views?
Thank you!
Here's a workaround I found after not being able to solve this.
New implementation is from this article
I reverted my changes from my initial question and implemented this. It lacks the nice protocol separation for talking back and forth and I might need something like this later but I think now I can still implement a protocol to solve this.
At least with this solution I have usable items in my view and a background that changes!
Here's a trivial VC called Club
Club has a function:
#implementation Club
-(IBAction)clickMe
{
NSLog(#"Whoa!");
}
#end
Now regarding ButtonA. Obviously in Storyboard you can drag from ButtonA to the function "clickMe" in "Club".
Now. Regarding ButtonB.
Is there any way, in Storyboard, to drag from ButtonB, to "clickMe" in "Club"?
Perhaps using the mysterious "object" objects, or ... ??
Note that, obviously, you can make a class for the small view, and have a function:
#implementation SmallViewOnRight
-(IBAction)sameAsClickMe
{
[(Club*)self.parentViewController clickMe];
}
#end
Then, you can drag from ButtonB to sameAsClickMe. But that's a complete nuisance.
Note that it's very normal to use container views like this, to handle different "areas" of your main view (particularly if you have stuff sliding around and so on, and when you have many things "on top of each other"). It's hugely convenient to move "sections" outside the main view, using container views. But it's a complete nuisance "passing up" the clicks.
Is there an obscure way to do this in Storyboard? Cheers!
Just FTR, iOS7+ only, nothing older
Note - going in the "other direction" is well-explored and easy enough to do.
No, you can't do that but you can use delegates for this behavior.
In SecondViewController.h:
#protocol SecondViewControllerDelegate <NSObject>
-(void)clickMe;
#end
#interface SecondViewController.h: UIViewController
#property (weak, nonatomic) id <SecondViewControllerDelegate> delegate;
#end
In SecondViewController.m:
#implementation SecondViewController
- (IBAction) buttonBClicked:(id)sender {
if ([self.delegate respondsToSelector:#selector(clickMe)] {
[self.delegate performSelector:#selector(clickMe)];
}
}
#end
In ClubViewController.m:
#import "SecondViewController.h"
#interface ClubViewController () <SecondViewControllerDelegate>
#end
#implementation ClubViewController.m
// make yourself a delegate of SecondViewController somewhere in your code. For example, in prepareForSegue.
-(void)clickMe {
NSLog (#"Clicked");
}
#end
EDIT:
Try with Unwind Segues!
I've posted an answer here on how to use them. But skip step 4.
I've created a view with a logout button and I'm trying to make that a subview of another view. The logout button view has a xib and a controller associated with the xib.
How do I make it so that this view/controller is a part of my other view?
The way I've done this before is by having a view that draws itself programmatically, drawing that view in the interface builder as part of another view and changing the class for that view. As I want that view to respond to methods, I made it have a protocol and then made the controller it was a subview of implement that.
Is that the only way to do it? Or is there a way such that I have an independent controller for my logout view that I can just 'drop in' into other views, because the drawback of the other method is that every view that wants to use this subview has to implement the protocol, even if that method is going to be the same in every view.
Create a superclass to abstract the logout behavior. Then, each UIViewController that supports the logout should subclass that superclass. In the superclass, provide the method for logout.
This approach will enable you to either simply hook up UIControls in Interface Builder to the common IBAction in the superclass, or alternatively, even add specific customization in the subclass before invoking the superclass method.
Here's one possible example:
LogoutViewController.h
#import <UIKit/UIKit.h>
#interface LogoutViewController : UIViewController
-(void)performLogout;
#end
LogoutViewController.m
#import "LogoutViewController.h"
#interface LogoutViewController ()
#end
#implementation LogoutViewController
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)performLogout
{
//do logout code
}
- (IBAction)logout:(id)sender
{
[self performLogout];
}
#end
SomeOtherViewController.h
#import <UIKit/UIKit.h>
#import "LogoutViewController.h"
#interface SomeOtherViewController : LogoutViewController
#end
SomeOtherViewController.m
#import "SomeOtherViewController.h"
#implementation SomeOtherViewController
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (IBAction)mySpecificLogoutButtonPressed:(id)sender
{
self.title = #"Good bye";
// do other code specific to logging out from this UIVC
[super performLogout];
}
#end
You can use NSNotificationCenter for this. So you can post the notification on logout button action. You can check the documentation.
Hope this helps.
I'm calling a modal viewcontoller from a number of locations and when i close it i'd like to find out what view it is on top of so i can call a update function if it is this custom list i've made.
I'm wondering how i might call a method in the ViewController under the modal view.
Right now i've set up a delegate, but it doesnt seem to call the method that i've set up.
Please see code.
ViewController.h
#interface PICTSharePictViewController : PICTBaseShareViewController <PICTConnModalViewControllerDelegate>
.m
-(void)viewDidLoad{
PICTConnModalViewController *cmodal = [self.storyboard instantiateViewControllerWithIdentifier:#"connModal"];
cmodal.pictDelegate = self;
}
-(void)checkSwitches:(PICTConnModalViewController*)sender{
NSLog(#"-----Check-----");
}
And ModalView
.h
#class PICTConnModalViewController;
#protocol PICTConnModalViewControllerDelegate
-(void)checkSwitches:(PICTConnModalViewController*)sender;
#end
#interface PICTConnModalViewController : PICTBaseViewController {
__weak id <PICTConnModalViewControllerDelegate> sliderDelegate;
}
#property (nonatomic, weak) id <PICTConnModalViewControllerDelegate> pictDelegate;
.m
-(void)viewDidLoad{
[pictDelegate checkSwitches:self];
}
I get no errors or any warnings. Can anyone tell me what I'm doing wrong?
You can access the View Controller that presented the modal View Controller by using the -[UIViewController presentingViewController] method on the modal/presented VC.
I am struggling to make a simple thing (at least I think it's simple) but I just can't do it!
I will try to explain a little bit.
It's an app which displays information. When the user is inside a view, he can click on a button, which displays a popoverview, where he can choose which information he wants to know.
Actually, I can't create an action that changes the UILabel text I created in the main view when the user clicks on the popoverview's buttons.
Anyone has any idea?
Just for you to know: the main view I created a class for it, and also for the popoverview. Although, the popover view I created its design in a XIB file (I don't know if this is important, that's why I am putting this).
Well, I hope you guys were able to understand my question.
Thanks in advance.
Fernando.
Just create a property from the viewcontroller and access it from the consumer (other viewcontroller )
You will have to use delegation in order to see changes in the main view when you are making different actions inside the popover. First, you need to create a protocol inside your popover controller header file:
#import <Foundation/Foundation.h>
#class MyPopoverController;
#protocol MyPopoverDelegate
- (void)valueChanged:(NSString*) newVal;
#end
#interface MyPopoverController: UIPopoverController
#property (weak) id<MyPopoverDelegate> delegate;
#end
Then in .m you implement it like this:
- (void) someActionOccured
{
if([self.delegate respondsToSelector:#selector(valueChanged:)]){
[self.delegate valueChanged:valueYouWantToSendBack];
}
}
Remember that in your main class you have to implement MyPopoverDelegate protocol:
#interface MainViewController: UIViewController <MyPopoverDelegate>
And when you instantiate your popover controller:
/*
** inside MainViewController.m
*/
// remember to assign it's delegate
MyPopoverController *popoverController = [MyPopoverController alloc] init];
popoverController.delegate = self;
Also, you'll have to implement the protocol's method:
/*
** inside MainViewController.m
*/
- (void)valueChanged:(NSString*) newVal
{
// process the string and display it where you need it
}