I have a parentViewController and a subView, in viewWillAppear in the parentViewController I added the subview to self.view and I set the delegate of subview to self. When I'm trying to use the delegate in the subview to push another view controller it does't work, I checked the value of delegate and it got "null".
My Main idea: when the user clicks on a button in the subview, I need to push another viewController using the navigationController of the parentViewController.
Here is my code
//parentViewController.h
#import "mysubView.h"
#interface parentViewController : UIViewController <mysubViewDelegate>
.
.//Some properties here
.
#end
In the implementation file:
//parentViewController.m
-(void) viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
mysubView *myView;
//GlobalObjects is to load the file in a certain language
myView = [[GlobalObjects loadNibNamed:#"mysubView" owner:self options:nil] objectAtIndex:0];
//Print myView.delegate gets the correct value here
myView.delegate = self;
[self.view addSubview:myView];
}
.
.
.
-(void)pushViewControllerUsingDelegate:(UIViewController *)viewController
{
[self.navigationController pushViewController:viewController animated:YES];
}
In mysubView.h:
//mysubView.h
#protocol mysubViewDelegate <NSObject>
-(void)pushViewControllerUsingDelegate:(UIViewController *)viewController;
#end
#interface mysubView : UIView< UITableViewDataSource, UITableViewDelegate>
{
}
#property (nonatomic , retain) id <mysubViewDelegate> delegate;
-(IBAction)ButtonClicked:(UIButton *)sender;
#end
In mysubView.m
#implementation mysubView
#synthesize delegate;
.
.
.
-(IBAction)ButtonClicked:(UIButton *)sender
{
newViewController *newController = [[newViewController alloc] initWithNibName:#"newViewController" bundle:nil];
//Here is my problem in this line .. self.delegate is null here
[self.delegate pushViewControllerUsingDelegate:newViewController];
}
-(void)pushViewControllerUsingDelegate:(UIViewController *)viewController
{
[self.delegate pushViewControllerUsingDelegate:viewController];
}
#end
myView = [[GlobalObjects loadNibNamed:#"mysubView" owner:self options:nil] objectAtIndex:0];
Use mysubView instead of GlobalObjects like as below
myView = [[mysubView loadNibNamed:#"mysubView" owner:self options:nil] objectAtIndex:0];
Please use Capital letter when you create new class.this is only convention but you should follow it.
Related
I have two UIViewController class with names : (RootViewController & SecondViewController).
I have one UIButton Outlet in my SecondViewController.now I want give action method to my UIButton in RootViewController.but I don't know about it.
please guide me and tell me how to get my UIButton in another View and give action method on it in another View....
I'm not sure why you are doing this, it doesn't look good.
Anyway, here's the way.
SecondViewController.h
#interface SecondViewcontroller:UIViewController
#property (nonatomic, weak) IBOutlet UIButton *theButton;
#end
RootViewController.m
SecondViewContoller * sv = [[SecondViewController alloc] init];
[sv.theButton addTarget:self action:#selector(buttonHandler:) forControlEvents:UIControlEventTouchUpInside];
You have to removeTarget when you've done with the button.
Why don't you use delegate or block callback?
ADDED
delegate
SecondViewController.h
#protocol SecondViewControllerDelegate <NSObject>
- (void)theButtonPressed;
#end
#interface SecondViewController : UIViewController
#property (nonatomic, strong) id<SecondViewControllerDelegate>delegate;
#end
SecondViewController.m
#interface SecondViewController ()
{
UIButton *theButton;
}
#end
#implementation SecondViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[theButton addTarget:self.delegate action:#selector(theButtonPressed) forControlEvents:UIControlEventTouchUpInside];
}
#end
RootViewcontroller.h
#interface RootViewController : UIViewController <SecondViewControllerDelegate>
#end
RootViewController.m
SecondViewController *sv = [[SecondViewController alloc] init];
[sv setDelegate:self];
and
- (void)theButtonPressed
{
}
block
SecondViewController.h
typedef void(^TheButtonTouched)(void);
#interface SecondViewController : UIViewController
- (void)addButtonEvent:(TheButtonTouched)event;
#end
SecondViewController.m
#interface SecondViewController ()
{
UIButton *theButton;
TheButtonTouched buttonBlock;
}
#end
#implementation SecondViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// button alloc init here and..
[theButton addTarget:self action:#selector(buttonEvent:) forControlEvents:UIControlEventTouchUpInside];
}
- (void)buttonEvent:(UIButton *)sender
{
if(buttonBlock)
{
buttonBlock();
}
}
- (void)addButtonEvent:(TheButtonTouched)event
{
buttonBlock = event;
}
#end
RootViewController.m
SecondViewController *sv = [[SecondViewController alloc] init];
[sv addButtonEvent:^{
// ADD SOMTHING HERE
}];
You need to create the button's iboutlet property.
Than using object of secondclass.button name you can assign selector.
[classobjectname..btnname addTarget:objectname.class action:#selector(objectname.methodname:);
Just Create RootViewController 's Object and passed into target parameter.
e.g.
[btnShow addTarget:self.rootCtrlObj action:#selector(viewPhoto_click:)
forControlEvents:UIControlEventTouchUpInside];
where rootCtrlObj is #property inside SecondViewController.h file
and when you push this controller in RootViewController you have to pass reference of RootViewController .
For Example,
secVCObj.rootCtrlObj = self;
[self.navigationController pushViewController:secVCObj animated:YES];
as i said custom delegate methods will work perfect for these cases,
in SecondViewController.h file define a custom delegate method like below
#import <UIKit/UIKit.h>
#import "ViewController.h"
#protocol SecondControllerDelegate<NSObject>
- (void)someActionToPerformInRootController;
#end
#interface SecondViewController : UIViewController
#property (nonatomic, assign) id<SecondControllerDelegate>delegate; //declare a custom delegate
#end
in SecondViewController.m file lets take an action of some button
- (IBAction)myButtonActionMethod:(id)sender
{
if([self.delegate respondsToSelector:#selector(someActionToPerformInRootController)])
{
[self.delegate someActionToPerformInRootController]; //this will call the delegate method in first view conroller( root view controller) //do what ever u want t do in the action method of rootviewcontroller
}
}
in RootViewController.h file
#import "SecondViewController.h"
#interface RootViewController : UIViewController < SecondControllerDelegate> //confirmas to delegate
in RootViewController.m while presenting the SecondViewController set the delegate to self
- (IBAction)showAction:(id)sender
{
SecondViewController *secondController = [[SecondViewController alloc]initWithNibName:#"SecondViewController" bundle:nil];
secondController.delegate = self; //call back to this controller
[self presentViewController:secondController animated:YES completion:nil];
}
//this method called from the secondViewcontroller
- (void) someActionToPerformInRootController
{
NSLog(#"perform action in root view controller");
}
In my Storyboard, I am using a UINavigationController with a navigation bar to present a view controller. This view controller, ViewController2, is pushed to the stack by tapping a UIBarButtonItem that I placed in the navigation bar. I made this connection in Interface Builder by dragging from the bar button to the ViewController2 scene and selecting "push" for the segue. To return back to the first view controller, I have an IBAction that calls the popViewControllerAnimated method. I'm using the delegate method to send data back to the first view controller but the string from ViewController2 is not being sent back to ViewController.
How can I pass the text entered in ViewController2 back to the first ViewController using the delegate method?
ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
#end
ViewController.m
#import "ViewController.h"
#import "ViewController2.h"
#interface ViewController () <UITableViewDelegate,UITableViewDataSource,Vc2Delegate>
#property (strong,nonatomic) NSArray *tableArray;
#property (weak,nonatomic) IBOutlet UITableView *listTableView;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
[self.listTableView setDelegate:self];
[self.listTableView setDataSource:self];
self.tableArray = #[#"item 1",#"item 2",#"item 3"];
ViewController2 *vc2 = [[ViewController2 alloc] init];
[vc2 setDelegate:self];
}
# pragma mark - TableView
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.tableArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"ItemCell" forIndexPath:indexPath];
cell.textLabel.text = [self.tableArray objectAtIndex:indexPath.row];
return cell;
}
#pragma mark - Delegate Method
- (void)returnFromVc2:(NSString *)userString {
NSLog(#"delegate text is %#",userString);
}
#end
ViewController2.h
#import <UIKit/UIKit.h>
#protocol Vc2Delegate <NSObject>
- (void)returnFromVc2:(NSString *)userString;
#end
#interface ViewController2 : UIViewController
#property (weak,nonatomic) id <Vc2Delegate> delegate;
#end
ViewController2.m
#import "ViewController2.h"
#interface ViewController2 ()
#property (weak,nonatomic) IBOutlet UITextField *textField;
#end
#implementation ViewController2
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (IBAction)toPreviousVC:(id)sender {
NSLog(#"user text is: %#",self.textField.text);
[self.delegate returnFromVc2:self.textField.text];
[self.navigationController popViewControllerAnimated:YES];
}
#end
You set the delegate to a local variable that won't be the same instance as the one you push.
- (void)viewDidLoad {
....
ViewController2 *vc2 = [[ViewController2 alloc] init];
[vc2 setDelegate:self];
....
}
You should also make a habit of checking if your delegate can respond to the message sent.
- (IBAction)toPreviousVC:(id)sender {
NSLog(#"user text is: %#",self.textField.text);
if ( [self.delegate respondsToSelector(#selector(returnFromVc2:))] ) {
[self.delegate returnFromVc2:self.textField.text];
}
[self.navigationController popViewControllerAnimated:YES];
}
Working over storyboard.
I've created View Controller (storyboard) and then in middle of content added subview from xib file.
I want to add xib (UIView) like as subview into ViewController and send object with data and print that data into label but I don't know how.
Here is my code.
ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController {
UIView *subView;
}
#property (strong, nonatomic) IBOutlet UIView *subView; //connected over IB
#end
ViewController.m
#import "OfferViewController.h"
#import "OfferLocation.h"
#interface OfferViewController ()
#end
#implementation OfferViewController
#synthesize subView;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
OfferLocation *location = [[OfferLocation alloc] initWithFrame:CGRectZero];
[self.subView addSubview:location];
}
...
#end
and here is subview:
OfferLocation.h
#import <UIKit/UIKit.h>
#interface OfferLocation : UIView{
UIView *view;
UILabel *locationLabel;// here is that label taht I want to print into
}
#property (nonatomic, retain) IBOutlet UIView *view;// connected over IB
#property (nonatomic, retain) IBOutlet UILabel *locationLabel;
#end
OfferLocation.m
#import "OfferLocation.h"
#implementation OfferLocation
#synthesize view, locationLabel;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self)
{
locationLabel.text = #"some text"; //this is not working
NSArray *subviewArray = [[NSBundle mainBundle] loadNibNamed:#"OfferLocation" owner:self options:nil];
UIView *tempView = [subviewArray objectAtIndex:0];
[self addSubview:tempView];
}
return self;
}
subView never seems to be initialized and loaded to the view or presented. Therefore you cannot see it.
Try calling:
self.view = self.subView // or subView; // or [self.view addSubview:self.subView // or subview];
or something similiar
Then declare a UILabel and initialize it with whatever text you want and add it to subview:
UILabel *label = [[UILabel alloc] initWithString:#"StackOverflow rocks!"];
[self.subView addSubview:label];
// or [self.view addSubview:label];
Differing on how you set subView.
What is this data you want to set on label's text? If it is a data type use the specifiers in the string.
%i // for int
%# // for string or object adress
%c // for char
%f // for float
etc...
I have a UIPopover that I want to use either
-(BOOL)popoverControllerShouldDismissPopover:(UIPopoverController *)popoverController{
return NO;
}
or
-(void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController{}
on. Neither of them seem to work (and I'm sure once one is fixed, the other will be too since it's probably a problem with delegates). For delegates, here is what I have:
In optionsViewController.h, the view which is inside the popover:
#import <UIKit/UIKit.h>
#protocol OptionsViewControllerDelegate <NSObject>
-(void)didPick:(NSString *)string;
#end
id delegate;
#interface OptionsViewController : UIViewController <OptionsViewControllerDelegate>{
IBOutlet UIPickerView *picker;
NSMutableArray *list;
}
#property (nonatomic, copy) NSArray *passthroughViews;
#property(nonatomic,retain) NSMutableArray *list;
#property(nonatomic,assign) id<OptionsViewControllerDelegate> delegate;
#end
and in the .m:
#synthesize delegate;
and in the .h of the view where the popover appears:
#interface exampleViewController : UIViewController <OptionsViewControllerDelegate,UIPopoverControllerDelegate>{
UIPopoverController *popoverController;
OptionsViewController *optionsViewController;
}
and in the .m:
#synthesize popoverController;
#synthesize optionsViewController;
-(BOOL)popoverControllerShouldDismissPopover:(UIPopoverController *)popoverController{
return NO;
}
[popoverController release];
[optionsViewController release];
In the ViewDidLoad, I have:
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
optionsViewController =[[OptionsViewController alloc]init];
optionsViewController.delegate = self;
popoverController = [[UIPopoverController alloc] initWithContentViewController:optionsViewController];
popoverController.popoverContentSize = CGSizeMake(320, 216);
}
To present the popover, I use:
-(IBAction)showDecadePopover{
[popoverController presentPopoverFromRect:CGRectMake(150, 50, 150, 50) inView:self.view permittedArrowDirections:UIPopoverArrowDirectionLeft animated:YES];
}
I'm probably missing something really obvious (that's why I gave so much of my code). Thanks so much!
Luke
Yep, simple fix. After you init the popoverController you need to set the exampleViewController as the delegate of it.
[popoverController setDelegate:self];
PS: What is the id delegate; floating after your OptionsViewControllerDelegate protocol definition for? Synthesizing delegate, which you already do, is all you need to create storage for it.
I have programmatically created a second view controller (MySecondViewController) which was all done and hooked up without using the visual object editor.
My problem is that when I run the app, only the original view controller (HelloWorldViewController) comes up; the second view controller does not show up. When I click on the view for HelloWorldViewController, nothing comes up.
Can you tell me what's wrong?
windowBasedAppAppDelegate.h
#import <UIKit/UIKit.h>
//-- Add a forward reference to the HelloWorldViewController class --
#class HelloWorldViewController;
#interface windowBasedAppAppDelegate : NSObject <UIApplicationDelegate> {
//-- create an instance of the view controller--
HelloWorldViewController *viewController;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
//--Expose the view controller as a property--
#property (nonatomic, retain) IBOutlet HelloWorldViewController *viewController;
#end
windowBasedAppAppDelegate.m
#import "windowBasedAppAppDelegate.h"
#import "HelloWorldViewController.h"
#import "MySecondViewController.h"
#implementation windowBasedAppAppDelegate
#synthesize window;
#synthesize viewController;
//-- a second view controller object--
MySecondViewController *mySecondViewController;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
//-- add the new view to the current window--
//-- instantiate the second view controller --
mySecondViewController = [[MySecondViewController alloc]
initWithNibName:nil
bundle:nil];
// -- add the view from the second controller --
//[window addSubview:mySecondViewController.view];
[window addSubview:viewController.view];
[self.window makeKeyAndVisible];
return YES;
}
- (void)dealloc
{
[MySecondViewController release];
[viewController release];
[window release];
[super dealloc];
}
#end
MySecondViewController.h
#import <UIKit/UIKit.h>
#interface MySecondViewController : UIViewController {
//-- create two outlets, label and button --
UILabel *label;
UIButton *button;
}
//-- expose the outlets as properties --
#property (nonatomic, retain) UILabel *label;
#property (nonatomic, retain) UIButton *button;
// -- declaring the IBAction ---
- (IBAction) buttonClicked: (id)sender;
#end
MySecondViewController.h
#import "MySecondViewController.h"
#implementation MySecondViewController
#synthesize label, button;
- (IBAction) buttonClicked: (id)sender {
UIAlertView *alert =
[[UIAlertView alloc] initWithTitle:#"Action Invoked!" message:#"Button clicked" delegate:self cancelButtonTitle:#"OK" otherButtonTitles: nil];
[alert show];
[alert release];
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)dealloc
{
[super dealloc];
}
HelloWorldViewController.h
#import <UIKit/UIKit.h>
#interface HelloWorldViewController : UIViewController {
}
#end
HelloWorldViewController.m
import "HelloWorldViewController.h"
#implementation HelloWorldViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)dealloc
{
[super dealloc];
}
Added code from MySecondViewController.m
//-- add the views to the view window --
[self.view addSubview:label];
[self.view addSubview:button];
[view exchangeSubviewAtIndex:1 withSubviewAtIndex:0];
self.view = view;
[super viewDidLoad];
Since the view is being initialized and that it has a proper frame, the problem could be this sequence of code,
[window addSubview:mySecondViewController.view];
[window addSubview:viewController.view];
As the viewController's view will have the same frame, it will be added over mySecondViewController's view. So you will have to remove the second line for the view to show up.
You never actually push the new view controller onto the screen.
mySecondViewController = [[MySecondViewController alloc]
initWithNibName:nil
bundle:nil];
// -- add the view from the second controller --
//[window addSubview:mySecondViewController.view];
[window addSubview:viewController.view];
You add viewController.view, (which should be undefined...), but not mySecondViewController.view.
Also, programHasFinishedLaunching may not be the best possible place to push it. If I were you, I'd put a button on the front page that pushes the new view in, it's easier that way.