I am invoking "HelpviewController" from UIViewController using following code, which is working fine.
self.pageViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"InnerHelpPageViewController"];
self.pageViewController.dataSource = self;
InnerHelpViewController *startingViewController = [self viewControllerAtIndex:0];
NSArray *viewControllers = #[startingViewController];
[self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil];
// Change the size of page view controller
self.pageViewController.view.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height - 30);
[self addChildViewController:_pageViewController];
[self.view addSubview:_pageViewController.view];
[self.pageViewController didMoveToParentViewController:self];
Inside my new controller InnerHelpViewController I have done button which should remove this newly added view and send control back to initiated page.
- (IBAction)unwindToMenuFromInnerHelp:(id)sender {
[self.view removeFromSuperview];
}
This call removing the newly added view, but the problem is "MenuController" is frozen. I couldn't do any clicks on it. Any help?
To explain flow--> I have menu screen where one button with name "help" --> When user clicks on this help button first snippet of code in this question executes and shows HelpViewController-->Once done with help, user clicks "Done" button--> Which should close the HelpViewController and move to "menu" screen.
Implement protocol method in InnerHelpViewController.h file class
#protocol InnerHelpViewControllerDelegate
-(void)removeCustomView;
#end
#interface InnerHelpViewController : UIViewController{
}
#property(nonatomic, weak) id<InnerHelpViewControllerDelegate> delegate.
In InnerHelpViewController.m file
#synthesize delegate;
- (IBAction)unwindToMenuFromInnerHelp:(id)sender {
[delegate removeCustomView];
}
in MenuController .h file Adopt InnerHelpViewControllerDelegate.
#interface MenuController : UIViewController<InnerHelpViewControllerDelegate>{
}
Now Confirm your delegate in MenuController.m file while helpviewcontroller object creation.
self.pageViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"InnerHelpPageViewController"];
self.pageViewController.dataSource = self;
InnerHelpViewController *startingViewController = [self viewControllerAtIndex:0];
startingViewController.delegate = self;
NSArray *viewControllers = #[startingViewController];
[self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil];
// Change the size of page view controller
self.pageViewController.view.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height - 30);
[self addChildViewController:_pageViewController];
[self.view addSubview:_pageViewController.view];
[self.pageViewController didMoveToParentViewController:self];
//Implement here delegate method
-(void)removeCustomView{
[self.pageViewController removeFromSuperview]
}
Related
I'm new to ObjC and I'm trying to create Button outside ViewController file (following MVC paradigm).
What I did:
.h
#interface MainMenu : UIButton
-(UIButton *)addButton;
#end
.m
#implementation MainMenu
-(UIButton *)addButton {
UIButton* button = [[UIButton alloc] initWithFrame:CGRectMake(50.0, 50.0, 200.0, 75.0)];
[button setBackgroundColor:[UIColor colorWithRed:1.0
green:1.0
blue:0.0
alpha:1.0]];
[button setTitle:#"TITLE"
forState:UIControlStateNormal];
return button;
}
#end
In ViewController I want to create button on the screen and make it respond to touch event. So
.m
#implementation ViewController
-(void)viewDidLoad {
[super viewDidLoad];
MainMenu *menuButton = [[MainMenu alloc] init];
[menuButton addTarget:self
action:#selector(ButtonClick)
forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:menuButton];
}
-(void)ButtonClick {
NSLog(#"You clicked on button!!!");
}
#end
I can make it work by implementing all in ViewController.m file, but wish I could have then separated. This code above doesnt show me a button
Second thing: I tried to add addTarget:action:forControlEvents: method to MainMenu.m instead of ViewController.m and I couldnt make it work properly because I need to pass ViewController as a target and method ButtonClick from ViewController.m as a selector (I guess)
So I'm interesting how to make it right according to MVC?
Thanks!
They way you are doing is bit wrong, as you subclassing UIButton and then you have instance method addButton which returns a button, don't make sense. Either you can add Class level method or just subclass and add another init method to fulfill your requirements.
Better would be if you want to create a custom button and want to add target action also do something like this
#interface CustomButton : UIButton
- (instancetype)initWithTarget:(id)target andAction:(SEL)action;
#end
in .m file
#implementation CustomButton
- (instancetype)initWithTarget:(id)target andAction:(SEL)action {
self = [super initWithFrame::CGRectMake(50.0, 50.0, 200.0, 75.0)];
if (self) {
[self setBackgroundColor:[UIColor colorWithRed:1.0
green:1.0
blue:0.0
alpha:1.0]];
[self setTitle:#"TITLE"
forState:UIControlStateNormal];
[self addTarget:target
action:action
forControlEvents:UIControlEventTouchUpInside];
}
return self;
}
#end
and you can just use it like this anywhere
[self.view addSubView:[CustomButton alloc] initWithTarget:self andAction:#selector(name)]];
You are almost there. Here is what you have done right:
1) Subclassed UIButton to MainMenu class. (I would typically call this MainMenuButton or something more specific)
2) Set up, created, and configured an instance of MainMenu in ViewController.
Here is what you did wrong:
1) Did not implement a custom init method
2) Tried to setFrame from within the subclass, this should be done from ViewController
3) You need to make modifications to self, which is the current instance of the subclass, not a new variable called button
The addButton method will never be called, since there is nothing to call it. When customizing a UIButton subclass you will want to do all of this in a custom init method. Try replacing your addButton method with this code:
#implementation MainMenu
-(id)init {
self = [super init];
if(self) {
[self setBackgroundColor:[UIColor colorWithRed:1.0
green:1.0
blue:0.0
alpha:1.0]];
[self setTitle:#"TITLE"
forState:UIControlStateNormal];
}
return self;
}
#end
Then in ViewController create an instance of your MainMenu subclass, set the frame, and configure as you did previously. This init method will be called when you call [[MainMenu alloc] init]; and will configure the subclass before returning it to ViewController.
#implementation ViewController
-(void)viewDidLoad {
[super viewDidLoad];
MainMenu *menuButton = [[MainMenu alloc] init];
[menuButton setFrame:CGRectMake(50.0, 50.0, 200.0, 75.0)];
[menuButton addTarget:self
action:#selector(ButtonClick)
forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:menuButton];
}
-(void)ButtonClick {
NSLog(#"You clicked on button!!!");
}
#end
I want to make the bottom button seen in the storyboard on the right to take the user to the signupstoryboard.storyboard/signupController seen on the left when the user taps on the button. How can that be done?
{ - (IBAction)signupbutton:(id)sender; SignupController *signUpView = [self.storyboard instantiateViewControllerWithIdentifier:#"signup"]; [self presentViewController:signUpView animated:YES completion:nil]; }
You'll have to do it by code.
- (IBAction)buttonTapped
{
NSString *storyboardName = #"signupstoryboard";
UIViewController *nextViewController = [[UIStoryboard storyboardWithName:storyboardName bundle:nil] instantiateInitialViewController];
// if you are using a navigation controller to push it:
[self.navigationController pushViewController:nextViewController animated:YES];
// otherwise if you are presenting it modally:
[self presentViewController:nextViewController animated:YES completion:nil]
}
In your .m (at the top)
#import "signupController.h"
In your button action method (Don't forget to set the storyboard id for your signupController as signup
- (IBAction)signupbutton:(id)sender
{
SignupController *signUpView = [self.storyboard instantiateViewControllerWithIdentifier:#"signup"]; [self presentViewController:signUpView animated:YES completion:nil];
}
Thats it
I wanted to add a UISearchBar to my view controller without storyboard so I added it programmatically as a subview. I have set the delegate and yet I can't seem to dismiss the keyboard by clicking on the search button.
here's my code:
#interface ViewController : UIViewController <UISearchBarDelegate>
{
IBOutlet UISearchBar* mySearchBar;
}
----
- (void)viewDidLoad
{
[mySearchBar setDelegate: self];
mySearchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, self.navigationController.navigationBar.frame.origin.y, 320, 44)];
[self.view addSubview:mySearchBar];
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)mySearchBar
{
[mySearchBar resignFirstResponder];
}
- (void)searchBarTextDidEndEditing:(UISearchBar *)mySearchBar
{
[mySearchBar resignFirstResponder];
}
You are setting the delegate before allocating the search bar. Try to set delegate afterwards.
mySearchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, self.navigationController.navigationBar.frame.origin.y, 320, 44)];
[mySearchBar setDelegate: self];
It is always helpful to check whether the delegate methods are called in the first place. Set a break point and see :)
I have a view controller named ViewController.
ViewController displays a UIView that has a button on it, which allows me to advance to a second view controller - SecondViewController.
SecondViewController also has a button on it, which allows me to advance to a third view controller.
However, I am having trouble displaying ThirdViewController. When I tap the button in SecondViewController it throws an error:
Warning: Attempt to present ... on ... whose view is not in the window hierarchy!
I have been to a bunch of other sites and posts that address this issue, but cannot seem to find a working solution. I have implemented quite a few solutions, but none seem to work.
Here is my code:
- (void)secondaryView:(UIView *)secondaryView
{
UIView *theView = secondaryView;
UIViewController *viewController = [[UIViewController alloc] init];
viewController.view.frame = [UIScreen mainScreen].bounds;
[viewController.view addSubview:theView];
viewController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentViewController:viewController animated:YES completion:nil];
}
secondaryView is a UIView that I am constructing elsewhere in the application. I add it to the viewController then present the viewController.
Is there any way to dynamically create UIViewControllers, add a UIView to each one, and add them to the window hierarchy?
If you can use navigation in your ViewControllers, you can try the below code
In the place where you call the firstViewController,
-(void)callFirst
{
FirstViewController *first = [FirstViewController alloc] init];
UINavigationController *navigationController = [UINavigationController alloc] initWithRootViewController:first];
navigationController.modalPresentaionStyle = UIModalPresenationFormSheet;
[self presentModalViewController:navigationController animated:YES];
}
And in the FirstViewController button action ,you can write
-(void)callSec
{
SecondViewController *sec = [SecondViewController alloc] init];
[self.NavigationController pushViewController:sec animated:YES];
}
And in SecondViewController you can do the same
-(void)callThird
{
ThirdViewController *third = [ThirdViewController alloc] init];
[self.NavigationController pushViewController:third animated:YES];
}
Try this...And in these ViewControllers you can do whatever coding you want to meet the requirement like
-(void)viewDidLoad
{
UIView *newView = [[UIView alloc] initWithFrame:CGRectMake(20,20,400,400)];
newView.backGroundColor = [UIColor redColor];
[self.view addSubView:newView];
}
I have a view which includes two subviews. I had it working so that only one subview was shown at a time and each subview had a button and when the button was clicked the subview would flip over and the next subview would appear. The problem was that it appeared as though the entire view was flipping. After reading on this site about how to solve the problem I attempted to add the subviews to a container and flip that instead. However now, although my first subview is showing up when I press the button it no longer flip. It doesn't do anything. I put a log statement in the method which flips the subviews, as well as a breakpoint and as far as I can tell it no longer gets called. I'm very new to xcode and objective c and delegates and I have no idea how to proceed. Any help would be appreciated. Thanks.
I have included the relevant code here:
The header for the ViewController
#interface ExerciseViewController : UIViewController<ExerciseSubViewDelegate>
//stuff for subviews
#property (nonatomic, strong) ExerciseSubViewImage *subViewImage;
#property (nonatomic, strong) ExerciseSubViewText *subViewText;
#property UIView *panel;
#end
This is the code for the ViewController:
#interface ExerciseViewController ()
#end
#implementation ExerciseViewController
#synthesize subViewImage, subViewText;
- (void)viewDidLoad
{
self.subViewImage.delegate = self;
_panel = [[UIView alloc] initWithFrame:CGRectMake(0,0, self.view.bounds.size.width, self.view.bounds.size.height/2)];
_panel.backgroundColor = [UIColor whiteColor];
[self.view addSubview:_panel];
[_panel addSubview:subViewImage];
}
-(ExerciseSubViewImage *)subViewImage
{
if (!subViewImage)
{
CGRect subViewImageFrame = CGRectMake(0,0, _panel.bounds.size.width, _panel.bounds.size.height);
self.subViewImage = [[ExerciseSubViewImage alloc] initWithFrame:subViewImageFrame];
[_panel addSubview:subViewImage];
}
return subViewImage;
}
-(ExerciseSubViewText *)subViewText
{
if (!subViewText)
{
CGRect subViewTextFrame = CGRectMake(0,0, _panel.bounds.size.width, _panel.bounds.size.height);
self.subViewText = [[ExerciseSubViewText alloc] initWithFrame:subViewTextFrame];
self.subViewText.backgroundColor = [UIColor blueColor];
[_panel addSubview:subViewText];
}
return subViewText;
}
-(void)exerciseSubViewImagePressed
{
[UIView transitionWithView:_panel
duration:0.2
options:UIViewAnimationOptionTransitionFlipFromRight
animations:^{
[subViewImage removeFromSuperview];
[_panel addSubview:subViewText];
}
completion: nil];
//This is how I did it before I added the container
/*[UIView transitionFromView:subViewImage
toView:subViewText
duration:0.2
options:UIViewAnimationOptionTransitionFlipFromRight
completion:nil];
self.subViewText.delegate = self;*/
NSLog(#"Ipushedtheimage");
}
-(void)exerciseSubViewTextPressed
{//I haven't updated this yet
[UIView transitionFromView:subViewText
toView:subViewImage
duration:0.2
options:UIViewAnimationOptionTransitionFlipFromRight
completion:nil];
self.subViewImage.delegate = self;
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
subViewImage = nil;
subViewText = nil;
}
#end
This is the code for the delegate
#import
#protocol ExerciseSubViewDelegate <NSObject>
-(void) exerciseSubViewImagePressed;
-(void) exerciseSubViewTextPressed;
#end
I am also added the code for the first subview:
#import
#import "ExerciseSubViewDelegate.h"
#interface ExerciseSubViewImage : UIView
#property (nonatomic, strong) UIButton *button;
#property (nonatomic, assign) id<ExerciseSubViewDelegate>delegate;
#property (strong, nonatomic) UIImageView *exerciseImageView;
#end
#import "ExerciseSubViewImage.h"
#import "UIImage+animatedGIF.h"
#implementation ExerciseSubViewImage
#synthesize button;
#synthesize delegate;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
//Initialization code
self.button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
CGRect buttonFrame = CGRectMake(50,200,100,35);
self.button.frame = buttonFrame;
[self.button setTitle:#"Image"forState:UIControlStateNormal];
[self.button addTarget:self
action:#selector(buttonTouched)
forControlEvents:UIControlEventTouchUpInside];
[self addSubview:self.button];
_exerciseImageView = [[UIImageView alloc] initWithFrame:CGRectMake(50,20,160,158)];
NSURL *url = [[NSBundle mainBundle] URLForResource:#"AppleLogo" withExtension:#"gif"];
_exerciseImageView.image = [UIImage animatedImageWithAnimatedGIFURL:url];
[self addSubview:self.exerciseImageView];
}
return self;
}
-(void)buttonTouched
{
NSLog(#"imagebuttonpressed");
[self.delegate exerciseSubViewImagePressed];
}
Again, any help would be appreciate. I know I'm probably just not understanding something simple.
Ok. This took me all weekend but I finally figured it out on my own. I thought I would shere the answer here in case anyone else ever has a similar problem. After trying several other approaches I finally went back to the approach I used here and started inserting a whole bunch of NSLogs to determine the order that every thing was executing in. What I finally ended up doing was changing this: (all in the top ViewController)
self.subViewImage.delegate = self;
_panel = [[UIView alloc] initWithFrame:CGRectMake(0,0, self.view.bounds.size.width, self.view.bounds.size.height/2)];
_panel.backgroundColor = [UIColor whiteColor];
[self.view addSubview:_panel];
[_panel addSubview:subViewImage];
to this:
//create panel
_panel = [[UIView alloc] initWithFrame:CGRectMake(0,0, self.view.bounds.size.width, s self.view.bounds.size.height/2)];
_panel.backgroundColor = [UIColor whiteColor];
[self.view addSubview:_panel];
[_panel addSubview:subViewImage];
//Set the subview delegates
self.subViewImage.delegate = self;
self.subViewText.delegate = self;