Delegate does not get called - objective-c

I have a UIPageViewController which I setup in the viewDidLoad method of the RootViewController as follows:
[self addChildViewController:self.pageViewController];
[self.view addSubview:self.pageViewController.view];
The delegate pageViewControllerspineLocationForInterfaceOrientation is called successfully and I can set the spine accordingly.
However, I want to setup the PageViewController on a button click so I moved the code to the event handler of the button pressed event. Now the delegate is not called.
Any ideas how I can fix it?

It is some what complicated but can be achieved through the code below :
Step 1: Add below code to .h file of rootViewController.
#property (strong, nonatomic) IBOutlet UIButton *previousClick;
#property (strong, nonatomic) IBOutlet UIButton *nextClick;
Step 2: Connect them to the xib or storyboard which ever you use.
Step 3: Add two IBAction methods to .m file.
#pragma mark - IBAction Methods
- (IBAction)previousClick:(id)sender
{
[_modelController pageViewController:self.pageViewController viewControllerBeforeViewController:_dataViewController];
}
- (IBAction)nextClick:(id)sender
{
[_modelController pageViewController:self.pageViewController viewControllerAfterViewController:_dataViewController];
}
Step 4: You also need to put below lines too to .m file
#interface RootViewController ()
#property (readonly, strong, nonatomic) ModelController *modelController;
#property (readonly, strong, nonatomic) DataViewController *dataViewController;
#end
And synthesize them as below
#synthesize modelController = _modelController;
#synthesize dataViewController = _dataViewController;
Step 5: Last and final add below line to - (UIPageViewControllerSpineLocation)pageViewController:(UIPageViewController *)pageViewController spineLocationForInterfaceOrientation:(UIInterfaceOrientation)orientation method.
_dataViewController = currentViewController;
after the currentViewController's alloc init call.
If you find that the added buttons are hidden by the pageViewController just bring them to the front using the code below in side the -viewDidLoad method
[self.view bringSubviewToFront:self.previousClick];
[self.view bringSubviewToFront:self.nextClick];

Related

Double click on row in NSTableView doesn't display the new view

I have an os x app that uses core data.
I have 3 .xib files in my app, those are:
1. MainMenu.xib
2. MasterTableViewController.xib
3. DetailViewController.xib
When started , app displays a view that has NSTableView with couple of records in it.
I name that view MasterTableViewController
I want when user double click on the row, to hide the "master" view and to display my "detail" view. I named that view DetailViewController.
When double clicked on the row in the NSTableView in the "master" view,nothing happen, "master" view remains visible. What I want is "master" view to dissapear, and "detail" view to appear.
Here is the code that I have right now, and more explanations follows:
AppDelegate.h
#import <Cocoa/Cocoa.h>
#interface AppDelegate : NSObject <NSApplicationDelegate>
#property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;
#property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;
#property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;
#property (nonatomic,strong) NSViewController *mainAppViewController;
#property (weak) IBOutlet NSView *mainAppView;
- (void)changeViewController:(NSInteger)tag;
#property (weak) IBOutlet NSTableView *websitesTableView;
- (void)tableViewDoubleClick:(id)nid;
#end
AppDelegate.m
#import "AppDelegate.h"
#import "MasterTableViewController.h"
#import "DetailViewController.h"
#interface AppDelegate ()
#property (weak) IBOutlet NSWindow *window;
- (IBAction)saveAction:(id)sender;
#end
#implementation AppDelegate
NSString *const masterTable = #"MasterTableViewController";
NSString *const detail = #"DetailViewController";
-(void)awakeFromNib {
[_websitesTableView setTarget:self];
[_websitesTableView setDoubleAction:#selector(tableViewDoubleClick:)];
}
- (void)tableViewDoubleClick:(id)nid {
NSInteger rowNumber = [_websitesTableView clickedRow];
NSTableColumn *column = [_websitesTableView tableColumnWithIdentifier:#"websiteUrl"];
NSCell *cell = [column dataCellForRow:rowNumber];
NSInteger tag = 2;
[self changeViewController:tag];
}
- (void)changeViewController:(NSInteger)tag {
[[_mainAppViewController view]removeFromSuperview];
switch (tag) {
case 1:
self.mainAppViewController = [[MasterTableViewController alloc]initWithNibName:masterTable bundle:nil];
break;
case 2:
self.mainAppViewController = [[DetailViewController alloc]initWithNibName:detail bundle:nil];
break;
}
[_mainAppView addSubview:[_mainAppViewController view]];
[[_mainAppViewController view] setFrame:[_mainAppView bounds]];
[[_mainAppViewController view] setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
}
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
// automatically run the master table view controller
NSInteger tag = 1;
[self changeViewController:tag];
}
Now, some of you may wondering, where is the rest of the code. I have ommited the boiler plate code for the core data below in the AppDelegage.m, since it is unchanged. I used binding to make my NSTableView to work and to display my records, so MasterTableViewController.h and .m files are empty, and same is true for the DetailViewController.h and .m file.
Important note - What i can't understand here: If I change the tag in 2 in the applicationDidFinishLaunching method, detail view is displayed normally, but if i switch it back on 1, and then double click on the row, "master" view (with the NSTableView) remains visible, and nothing happen (views are not swapped)
Anyone can help me to find out what is wrong with my code?
Regards, John
You apparently had a second instance of your AppDelegate class instantiated in the MasterTableViewController.xib file. There should be only one AppDelegate instance and that's the one in MainMenu.xib. So, it shouldn't be in MasterTableViewController.xib.
One of the instances was receiving the double-click action method from the table, but the other one was the one with the outlet to the main window.
You need(ed) to get rid of the second instance and find another way to access the app delegate from the MasterTableViewController.

Root View Controller's child View Controllers are on top of root

I have what is a seemingly simple problem but I cannot find a solution! I have a subclass of UIViewController that is my root view controller, and ten different other UIViewcontrollers that I want to load in as child view controllers when called (one at a time, not all ten on screen at once.)
The root controller has a few buttons whose actions call the respective code to bring up a child view controller. The root view controller is loaded first by the nib and I want to instantiate it with page01ViewController as the first child. But whenever I call the following code, the child view controller is overlayed on top of my rootViewController, hiding all of the control buttons in my root controller!
// RDJrootPageViewController.m
#import "RDJrootPageViewController.h"
#import "RDJhomeScreenViewController.h"
#import "RDJpage01ViewController.h"
#import "RDJpage02ViewController.h"
#import "RDJpage03ViewController.h"
#import "RDJpage04ViewController.h"
#import "RDJpage05ViewController.h"
#import "RDJpage06ViewController.h"
#import "RDJpage07ViewController.h"
#import "RDJpage08ViewController.h"
#import "RDJpage09ViewController.h"
#import "RDJpage10ViewController.h"
#interface RDJrootPageViewController ()
#property (retain, nonatomic) RDJhomeScreenViewController *homeScreenViewController;
#property (retain, nonatomic) RDJpage01ViewController *page01ViewController;
#property (retain, nonatomic) RDJpage02ViewController *page02ViewController;
#property (retain, nonatomic) RDJpage03ViewController *page03ViewController;
#property (retain, nonatomic) RDJpage04ViewController *page04ViewController;
#property (retain, nonatomic) RDJpage05ViewController *page05ViewController;
#property (retain, nonatomic) RDJpage06ViewController *page06ViewController;
#property (retain, nonatomic) RDJpage07ViewController *page07ViewController;
#property (retain, nonatomic) RDJpage08ViewController *page08ViewController;
#property (retain, nonatomic) RDJpage09ViewController *page09ViewController;
#property (retain, nonatomic) RDJpage10ViewController *page10ViewController;
#end
#implementation RDJrootPageViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
currentPage = 1;
self.page01ViewController = [self.storyboard instantiateViewControllerWithIdentifier:#"page01"];
[_page01ViewController.view setFrame:CGRectMake(0, 0, 1024, 768)];
[self addChildViewController:_page01ViewController];
[self.view addSubview:_page01ViewController.view];
[_page01ViewController didMoveToParentViewController:self];
[self.view setUserInteractionEnabled:YES];
}
My problem is similar to the one asked here, but no solution was ever identified:
Return from Child View Controller to Container
Every tutorial I find has the same setup: make your new VC, add it as a childView to self, then add that as a subview to your root view, but it dosen't work.
Anyone know the right way to do this?
You may want to user insertSubview:atIndex:. Using an index of 0 will add the view under all the other views. Alternatively you could have a container view for the views of the page view controllers. This container view needs to be added at index 0 in the view of RDJrootPageViewController. The page view controllers views could be added to the afore mentioned container view.
Hope this helps.

passing data from parent to child

In my app I'm trying to pass data from the parent view to the child view. However, when I run the app the delegate method isn't being called.
Here is the code on how I implemented the custom delegate:
parent.h
#protocol SLBWallViewControllerDelegate <NSObject>
- (void) pictureToBeUploaded:(id)picture;
#end
#interface SLBWallViewController : UIViewController <UIActionSheetDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate>
- (IBAction)createPotButtonPressed:(id)sender;
#property (weak, nonatomic) id <SLBWallViewControllerDelegate> delegate;
#end
parent.m
[self.delegate pictureToBeUploaded:info[UIImagePickerControllerEditedImage]];//i'm taking the pic from a uiimagepicker
child.h
#interface SLBPostViewController : UIViewController <SLBWallViewControllerDelegate>
#property (weak, nonatomic) IBOutlet UIImageView *picture;
#end
child.m
#pragma mark - Wall View Controller Delegate
- (void)pictureToBeUploaded:(id)picture{
self.picture.image = picture;
}
Is there anything wrong or missing?
Well, the problem probably (edit: confirmed in the comments) is that self.delegate is nil at that point. So you send a message to nil and nothing happens of course. What you have to do is make sure that you assign a Child instance to delegate property before trying to send the message. Something like this for example:
//...
self.delegate = //.. a 'Child' instance
//...
[self.delegate pictureToBeUploaded:info[UIImagePickerControllerEditedImage]];
//(1) In Child in .h file create one property
#property (nonatomic,strong) UIImage * someImage;
//(2) In Child in .m file override the property
-(void)setSomeImage:(UIImage *)someImage{
_someImage=someImage;
self.picture.image = self.someImage;
}
//(3) In Parent in .m file set image to child's 'someImage' property
childsObject.someImage= UIImagePickerControllerEditedImage;

UIPopoverControllerDelegate delegate methods not being called

I have a screen with a button. Clicking the button will display a popover with two buttons. I want to be able to use the following method when the popover is dismissed:
#pragma mark - UIPopoverControllerDelegate
- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController {
NSLog(#"OrderViewController.m -popoverControllerDidDismissPopover start");
}
The popover view has its own class:
#import <UIKit/UIKit.h>
#import "MenuItemModel.h"
#interface SelectedItemsOptionsViewController : UIViewController
#property (weak) id <UIPopoverControllerDelegate> delegate;
#property (strong, nonatomic) MenuItemModel *item;
#end
The class which creates the popover has:
#interface OrderViewController : UIViewController <PageViewControllerDelegate,
UITableViewDataSource, UITableViewDelegate, ServiceConnectorDelegate,
UIPopoverControllerDelegate>
So the OrderViewController - wants to know when SelectedItemsOptionsViewController has been dismissed.
I have the method declared (first block of code) and I am setting the delegate as:
SelectedItemsOptionsViewController *destViewController = (SelectedItemsOptionsViewController *)segue.destinationViewController;
popSegue = (UIStoryboardPopoverSegue *)segue;
[destViewController setDelegate:self];
destViewController.item = toDisplay;
So I am setting the delegate OK as far as i'm aware... the delegate property is #syntheized in th SelectedItemsOptionsViewController.m and well, its driving me a bit crazy.
I could be misunderstanding something here but looks like you're assigning the delegate for a UIViewController class, but where are you assigning the popOver its delegate, in the storyboard?

Why is my delegate method being sent to its parent view after being sent to the delegate?

I apologise ahead of time for the question title. I'm not quite sure how to succinctly describe my issue.
I'm having trouble with this delegate method I set up. I'm trying present a simple login screen modally. My issue is my login view gets a method called to it after I dismiss it.
Specifically, Xcode logs this:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[LoginViewController login:]: unrecognized selector sent to instance [memory address]'
LoginViewController.h
#import <UIKit/UIKit.h>
#protocol LoginViewControllerProtocol;
#interface LoginViewController : UIViewController
#property (weak, nonatomic) IBOutlet UITextField *userNameTextField;
#property (weak, nonatomic) IBOutlet UITextField *userPasswordTextField;
#property (weak, nonatomic) IBOutlet UIButton *loginButton;
#property (nonatomic, weak) NSObject<LoginViewControllerProtocol> *loginViewControllerDelegate;
#end
#protocol LoginViewControllerProtocol <NSObject>
- (void)loginViewController:(LoginViewController *)controller didLogin:(NSString *)userName;
#end
LoginViewController.m
- (IBAction)login
{
if ([self.loginViewControllerDelegate respondsToSelector:#selector(loginViewController:didLogin:)]) {
[self.loginViewControllerDelegate loginViewController:self didLogin:self.userNameTextField.text];
}
}
The delegate: (TestViewController.m)
- (void)loginViewController:(LoginViewController *)controller didLogin:(NSString *)userName
{
[self dismissModalViewControllerAnimated: YES];
didLogIn = YES;
}
I can't see why the delegate method is being sent back to the dismissed view.
Any help would be greatly appreciated!
Edit:
I apologise for leaving this out. This occurs in the view controller that calls LoginViewController. The delegate method also exists here.
TestViewController.m
if (!didLogIn) {
//launch login view modally
LoginViewController* loginController = [[LoginViewController alloc] initWithNibName: #"LoginViewController" bundle: nil];
loginController.loginViewControllerDelegate = self;
loginController.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
loginController.modalPresentationStyle = UIModalPresentationFormSheet;
NSLog(#"LoginViewControllerDelegate: %#", self.description);
NSLog(#"LoginViewController: %#", loginController.description);
[self presentModalViewController:loginController animated: YES];
TestViewController.h
#import <UIKit/UIKit.h>
#import "LoginViewController.h"
#class NuanceGuidHandler;
#interface TestViewController : UIViewController <LoginViewControllerProtocol>
#property (weak, nonatomic) IBOutlet UILabel *partnerGuidLabel;
#property (weak, nonatomic) IBOutlet UILabel *userGuidLabel;
#property (strong, nonatomic) NuanceGuidHandler *nuanceGuidHandler;
#property (nonatomic) BOOL didLogIn;
#end
The delegate thing is a red herring.
* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[LoginViewController login:]: unrecognized selector sent to instance [memory address]'
Means a object of class LoginViewController has been sent the message login:, which it doesn't know how to handle.
You've connected the action to a method called login:, and in your controller your action is defined as login. The colon is all-important, as any doctor will tell you. Either disconnect and reconnect the action in interface builder, or change the login method signature from
- (IBAction)login
To
- (IBAction)login:(id)sender
You seem to be doing one of two things:
You don't seem to be declaring your delegate anywhere when you mush your modal view controller.
modalviewcontroller.delegate = self
I'm not sure if this is causing an issue or not but you have a double protocol declaration in LoginViewController.h. This has messed with my delegate stuff in the past, and it may or may not be causing your problem.