Add, remove subview and communicate between subview and main uiviewcontroller - objective-c

I have created two uiviewcontrollers in storyboard. I am adding second UIview as a subview to 1st view when a button is pressed.
Now, my subview has a done and cancel button, which upon been touched, the subview has to be removed from the main view and needs to send some data back to main view. Is using delegates the only way to solve this? Please explain if there is any other simpler or better option.
Thank you :)

It sounds like the question is just about subviews of the 1st view controller's view. In that case, the 1st view controller can directly inspect all of them. i.e. Say the data that you'd like "passed" between views is the text of a UITextField contained on the subview.
You have an outlet to the subview, probably painted in IB?
// MyViewController.m
#property(weak, nonatomic) IBOutlet UIView *subview; // self.view is it's parent
Create an outlet that connects to whatever subviews you want data from:
#property(weak, nonatomic) IBOutlet UITextField *textField; // probably, subview is it's parent
Hide and show the "dialog":
self.subview.alpha = 0.0; // to hide (alpha is better than 'hidden' because it's animatable
self.subview.alpha = 1.0; // to show
When the button is pressed:
- (IBAction)pressedDoneButton:(id)sender {
self.subview.alpha = 0.0;
// or, prettier:
[UIView animateWithDuration:0.3 animations:^{ self.subview.alpha = 0.0; }];
// the text field still exists, it's just invisible because it's parent is invisible
NSLog(#"user pressed done and the text that she entered is %#", self.textField.text);
}
The point is that data is not being passed between views. The view controller has pointers to views. Some, like buttons generate events for the view controller to react to. Others carry data that the view controller can see.

Related

Can't change UILabel's text from another View Controller

I have two view controllers, one with a text field and a 'Next' button and another one with just a label. The idea is that you fill in your name in the text field and click 'Next'. It should then switch to the other view and the label should show your name.
When I switch views however, the label is just empty. I am rather new to Objective-C and I'm hoping someone knows why this is happening :).
ViewController.m:
#interface ViewController () {
IBOutlet UILabel *label;
IBOutlet UITextField *textField;
}
-(IBAction)go:(id)sender
{
label.text = textField.text;
}
-(IBAction)remove:(id)sender {
[sender resignFirstResponder];
}
You said that you have two View Controllers. The first View Controller has an instance of UITextField, and a UIButton. Your second View Controller just has an instance of UILabel.
However, I noticed in your code that ViewController.m, which I am assuming is your first View Controller, has two IBOutlets, one for a UILabel and one for a UITextField, which doesn't make sense because the UILabel is supposed to be part of your second View Controller.
What you need to do is properly delete the IBOutlet for the UILabel from your first View Controller. Then, in your second View Controller, add the IBOutlet for it's UILabel.
Then, you need to implement the prepareForSegue method in your first View Controller and add a code statement like this:
[[segue destinationViewController]label].text = textField.text;
This way, when the segue is performed, you will successfully pass your first View Controller's text field's text to your second View Controller's label.

UIView inside a UIViewController or better way to do it?

I have a problem on how to properly do a certain kind of action.
The image below shows a UIViewController, but the second part of the view is a custom UIView (the one with the profile pic, name and Show View button).
The subclassed UIView is allocated using this code:
profileView = [[GPProfileView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 70)];
profileView.myTripGradientColor = YES;
[self.view addSubview:profileView];
The problem is of course, that the button on the UIView can't show any view, since it's only the UIViewController that can push another ViewController to the window(correct?).
The UIView is used in several places in the app and needs to be added easily and have the same behavior across the application.
This worked great until I added the button, and I'm starting to think I've made this wrong, and there has to be a better way to do it (maybe change the UIView to something else?).
I was thinking I should be able to call:
self.superview
And then somehow get the ViewController so I can push another ViewController into the view hierarchy, but nope.
Any suggestions and a tips on how to do this correctly?
UPDATE:
I have no idea on how to push another UIViewController from the button.
What should I do in this method when pressing the button in the UIView:
- (void) showViewButtonTouched:(UIButton*)sender {
GPProfileSocialFriendsViewController *friendsSettings = [[GPProfileSocialFriendsViewController alloc] init];
}
How do I push GPProfileSocialFriendsViewController?
Your - (void) showViewButtonTouched:(UIButton*)sender method should be in your controller and would probably be better named - (void) showView:(UIButton*)sender or - (void) showProfile:(UIButton*)sender so it clearly denotes what it does (not how you got there).
It's not the view's responsibility to manage transitions from a state to another. If you move your method to your controller, your problem is no more (you can easily access self.navigationController or push directly if you don't have an navigation controller like this:
[self presentViewController:vcThatNeedsToBePushed animated:YES completion:nil];
I think you can create weak reference in GPProfileView on UIViewController. Like this:
#property (weak, nonatomic) UIViewController *rootController;
when you create GPProfileView, assign rootController-property:
profileView = [[GPProfileView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 70)];
profileView.myTripGradientColor = YES;
profileView.rootController = self; // if view created in view controller
[self.view addSubview:profileView];
and in implementation of button selector:
self.rootController push... // or pop
May be this not correct, but you can try
You could let the view controller push the next view controller when the button is pushed. The view controller can add a target/action on the button, so that the action method in the view controller is called on the touch up inside event.

Resize UIView and change subview position simultaneously

I have placed out a UIView with a UIButton as a subview in a ViewController in Interface Builder. I also have a UITextField where I have a action witch is triggered every time I type something in it. When I type something my view is supposed to get higher and the button should move to the bottom of the view. But when I type the first letter in the textfield the view resizes but the button doesn't move. When I type a second letter the button moves. Probably because the view is already resized. My question is how to get this to work simultaneously when typing the first letter in the textfield.
My code:
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(keyPressed:) name:UITextFieldTextDidChangeNotification object:textField];
- (void)keyPressed:(NSNotification*)notification{
view.frame = CGRectMake(view.frame.origin.x, view.frame.origin.y, view.frame.size.width, 200.0);
button.frame = CGRectMake(button.frame.origin.x, (view.frame.size.height-button.frame.size.height), button.frame.size.width, button.frame.size.height);
}
try to implement this method:
-(void)textFieldDidBeginEditing:(UITextField *)textField
{
// put your action here
}
Solved it by putting the button at the bottom of the view. Then when I resized the view the button followed along by staying at the bottom. I didn't need to programmatically move the button.

How to show a UIView OVER a UIPopoverController

In my app, I have my main view and when i click a button, a UIPopoverController is shown over my main view (not fullscreen so i still see the view behind) containing a UITableView. When I click one of the tableview cells, I want to show a custom view centered on screen (simple view informing the user that the app is processing) that will fade in and fade out during a specific amount of time.
The problem is that my custom view always appears UNDER the UIPopover...I tried all I can think of, bringSubviewToFront etc...Nothing works... I also tried to wrap my custom view in a UIViewController and use [mainView presentViewController:myCustomView ...] but when I do that the main view disappear
Someone can help?
Thx
Thx Ole Begemann, this question was indeed a duplicate.
Although, the solution to my problem is not to subclass UIWindow but to add my UIView to the key UIWindow :
NSArray * windows = [[UIApplication sharedApplication] windows];
UIWindow* win0 = [windows objectAtIndex:0];
[win0 addSubview:loadingView];
[win0 bringSubviewToFront:loadingWindow];

Putting a custom view into a UITableView

I have a regular-style UITableView—the one that has a white background and gray horizontal lines to separate the rows.
I have another custom UIView that is just a 100x100 rectangle filled with redColor.
How can I put the latter into the former, such that it appears over the horizontal lines, but is still a “part” of the table view in the sense that when I scroll the table view around, the red view scrolls with it? In fact, I should also be able to put my finger on the red area and scroll the table view.
Once again, if the red view is placed to overlap some horizontal lines, it should appear over the lines. Sadly, when I just add the red view as a subview to the table view, the horizontal lines go over the red view; see this screenshot.
How can this be accomplished?
The correct place to handle the stacking order of your red square is in the layoutSubviews method. The table view sends itself layoutSubviews any time it adds or removes subviews (and at other times).
You need to make a subclass of UITableView that has a reference to the red square:
#interface MyTableView : UITableView
#property (weak, readonly) IBOutlet UIView *redSquare;
#end
You can initialize redSquare in whatever way you want. I just put it in my nib along with the table view, and moved it to be a subview of the table view in awakeFromNib:
#implementation MyTableView
#synthesize redSquare = _redSquare;
- (void)awakeFromNib {
[self addSubview:self.redSquare];
}
Anyway, to actually make sure the red square is always on top of the table cells and grid lines, override layoutSubviews like this:
- (void)layoutSubviews {
[super layoutSubviews];
[self bringSubviewToFront:self.redSquare];
}
EDIT
If you are trying to add the view a above the lines (hide the lines) try to use – bringSubviewToFront: to take it to the front of the table view.
[self.tableView bringSubviewToFront:redView];
ELSE
Add the view to the self.tableView.tableHeaderView this will place it above the table view and will scroll with the table view.
UIView *redView = [[UIView alloc]init];
redView.frame = //set the frame
redView.backgroundColor = [UIColor redColor];
self.tableView.tableHeaderView = redView;
Good Luck
Just add this view to UITableView as subview:
[tableView addSubview:myRedView];
See userInteractionEnabled property in order to handle interaction and scrolling.
Make your view a subview of any normal subview of the UITableView: a header, a footer or any UITableViewCell.
I think what you've described can best be achieved using a UITableViewCell or even a subview of the header. A cell has the inherent ability to scroll the table and can be customized any way you like it. It's essentially a view.
In your situation, for example, you may want the red box to appear by default at the top of the table. You would make the first cell a 'red box' cell, where you would insert your red box into the cell's content view.
So, your problem is basically, that the UITableViewCells of a UITableView are added as Subviews dynamically, and you cannot control wether they are added in front of or behind your view.
So to keep your view at the front, you need to get it back there every time cells may be added, which occurs when the UITableView scrolls.
I would suggest you try adding your custom view as a subview and then override -scrollViewDidScroll like so:
- (void)scrollViewDidScroll {
[super scrollViewDidScroll];
// myCustomView is your custom view referenced in an IVar
[self.tableView bringSubviewToFront:myCustomView];
}
Edit your viewWillAppear delegate with these lines
UIView *redView=[[UIView alloc]initWithFrame:CGRectMake(30,30, 100, 100)];
redView.backgroundColor=[UIColor redColor];
[self.tableView addSubview:redView];