Using delegation to talk to view controllers in TabBarController - objective-c

I'm trying to use protocols and delegation to send messages to different views in a tab bar controller. I've set it up like below but I don't seem to be receiving the message;
#class RaprTabBarViewController;
#protocol RaprTabBarViewControllerDelegate <NSObject>
#optional
- (void)initActivites:(NSArray *)activities;
#end
#interface RaprTabBarViewController : UITabBarController <RKObjectLoaderDelegate>
#property (nonatomic, weak) id <RaprTabBarViewControllerDelegate> delegated;
#end
Then in the implementation
- (void)someMethodThatIsCalled:(NSArray *)objects {
NSLog(#"Delegating..");
[self.delegated initActivites:objects];
}
Now I get the NSLog so the method is definitely called. And now here is a view controller which is embedded in a navigation controller;
#interface ActivitesViewController : UITableViewController <RaprTabBarViewControllerDelegate>
#property (nonatomic, strong) NSArray *activites;
#end
And the implementation
- (void)initActivites:(NSArray *)activities {
NSLog(#"Called initActivities");
self.activites = activities;
}
I do not get the NSLog in the view controller so the initActivites method is never called. What am I doing wrong?
Thanks for your help.

Related

Objective-c - control outlet from other class

I just like to play with coding for a hobby, so probably a noob question;
I have a simple storyboard for MacOS with 2 views. Both have there own classes (main class and subclass). How can I control a outlet in the subclass from the main class?
for example
I have a button (IBAction) in the mainclass and a textfield (IBOutlet) in the subclass. I want to set the stringvalue for the textfield with a click on the button in main.
I have searched a lot last days but just don't get it. (or just need a push in the right direction)
EDIT after JingJingTao's answer:
I used the control-drag function to open the second window.
I tried the code JingJingTao gives, but the textfield doesn't respond to the action.
My classes look like this now:
ViewController.h
#import <Cocoa/Cocoa.h>
#interface ViewController : NSViewController
- (IBAction)newText:(id)sender;
#end
ViewController.m
#import "ViewController.h"
#import "ViewController2.h"
#interface ViewController ()
#property (nonatomic) ViewController2 *subclass;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)setRepresentedObject:(id)representedObject {
[super setRepresentedObject:representedObject];
}
- (void)newText:(id)sender {
self.subclass.textField.stringValue = #"button pressed";
}
#end
ViewController2.h
#import "ViewController.h"
#interface ViewController2 : ViewController
#property (nonatomic) IBOutlet NSTextField *textField;
#end
ViewController2.m
#import "ViewController2.h"
#interface ViewController2 ()
#end
#implementation ViewController2
- (void)viewDidLoad {
[super viewDidLoad];
}
#end
Update:
I've attached two screenshots of what it looks like in the storyboard for the first suggestion,
1) Add a view to your ViewController, set the class at the top right to 'YourView', 'YourView' is a just an NSView, add a textfield to it and hook it up.
2) Add YourView as a property to your ViewController, i.e. #property (nonatomic) IBOutlet NSView *yourView; and hook it up.
Let me know if there are any issues.
You just need to put the textfield in the public interface of your subclass, so you can access it in your main class, although it does sound like you're using inheritance and I don't think you need to but that's another topic :D.
Example:
In MainClassViewController.m
#interface MainClassViewController ()
#propert (nonatomic) Subclass *subclass;
#end
#implementation MainClassViewController
// I guess you already add your subclass to the main viewcontroller because they display on the same screen.
- (void)yourButtonTapMethod {
self.subclass.textfield.text = #"Your value";
}
In Subclass.h
#interface Subclass : NSObject
#property (nonatomic) IBOutlet UITextfield *textfield;
I use Cocoa Touch instead of Cocoa, so maybe it's NSTextfield for you. Please let me know if this does not answer your question, good luck.

delegate don't work between 2 viewcontrollers

I get stuck on using the delegate method.
I have 2 views. In view A, I use a delegate to say I pressed a button to view B.
View B receives the message well.
I would like to sent a message to say that the view B has received the message.
So the view from A to B for my delegate works but the B to A is not working.
.h:
#import <UIKit/UIKit.h>
#protocol ButtonProtocolName <NSObject>
- (void)toucheEnter:(id)sender;
#end
#interface ClavierKsViewController : UIViewController
#property (nonatomic, assign) id <ButtonProtocolName> delegate;
#end
.m
#import "ClavierKsViewController.h"
#interface ClavierKsViewController ()
#end
#implementation ClavierKsViewController
-(IBAction)toucheEntreeClavier:(id)sender{
[self.delegate toucheEnter:sender];
}
#end
Now on view B.h:
#import "ClavierKsViewController.h"
#interface CaisseViewController : UIViewController<ButtonProtocolName>
#property (nonatomic,retain) ClavierKsViewController *clavierKsView;
b.m
- (void)viewDidLoad
{
[super viewDidLoad];
clavierKsView = [self.storyboard instantiateViewControllerWithIdentifier:#"clavierKsView"];
clavierKsView.delegate=self;
}
-(void)toucheEnter:(id)sender{
NSLog(#"valider");
}
in that sense it works
When I created a delegate from view B to view A in based on the same way, I still get the same message: can not find protocol declaration for delegate
The protocol cannot work is likely caused by circular dependency. The solution is to extract your protocol to another .h like "ButtonProtocolName.h" and import the protocol in both a.h and b.h

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;

Objective-C: Delegate is nil in modal in navigation controller

I've got a ViewController inside a navigation controller that needs to present a modal.
The ViewController has this as its header:
#interface ViewController : BaseViewController<AuthenticateDelegate>
and in the IBAction that presents the modal:
AuthenticationController *authVC = [self.storyboard instantiateViewControllerWithIdentifier:#"AuthControllerView"];
authVC.delegate = self;
[self presentModalViewController:authVC animated:YES];
The AuthenticationController has this in its .h file:
#interface AuthenticationController: BaseViewController<UITextFieldDelegate>
#property (nonatomic, assign) id <AuthenticateDelegate> delegate;
#end
As you can see, I have assigned "self" (the ViewController) as the delegate to the AuthenticationController, but for some reason, the delegate is in:
- (IBAction)SubmitAuthentication:(id)sender;
{
[self.delegate validateUser:lblUsername.text :lblPassword.text];
[self dismissModalViewControllerAnimated:YES];
}
Any help will be appreciated.
you must create delegate property as below.
#property (nonatomic, strong) id <AuthenticateDelegate> delegate;

Delegate to 'Parent' ViewController best practice

The setup:
PickerView (spinSelector) and label (chosenItem) added to ViewController.
Created separate delegate class files (SpinDelegate m&h) for the PickerView delegate.
Created instance of the delegate (SpinDelegate *mySpinDelegate)
Assigned delegate property to delegate instance
ViewController.h
#interface ViewController : UIViewController
{
SpinDelegate *mySpinDelegate;
}
#property (nonatomic, weak) IBOutlet UILabel *chosenItem;
#property (nonatomic, strong) IBOutlet UIPickerView *spinSelector;
ViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
mySpinDelegate=[[SpinDelegate alloc]init];
self.spinSelector.delegate=mySpinDelegate;
self.spinSelector.dataSource=mySpinDelegate;
}
SpinDelegate.h
#interface SpinDelegate : UIViewController <UIPickerViewDataSource, UIPickerViewDelegate>
{
ChoiceData *choiceItems;
}
#end
SpinDelegate.m
#pragma mark - PickerView Delegate
- (NSString *)pickerView:(UIPickerView *)pickerView
titleForRow:(NSInteger)row
forComponent:(NSInteger)component{
return [choiceItems.choiceList objectAtIndex:row];
}
Next is to use the method:
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component;
This is part of the UIPickerViewDelegate protocol. Using this, to simply change the UILabel (chosenItem) in the ViewController to value of row. Something like "The picked item is %i",row
I've read and searched through a ton of posts and questions on UIViewController to UIViewController messaging and looked at protocol/delegate, singleton, NSNotificationCenter... it just seems to me that there is a syntax I am missing to address the parent/super? The ViewController created the instance of the delegate, doesn't the delegate have scope?
Please educate me on this. : )
You can do something like this:
ViewController.h
#import "SpinViewController.h"
#interface ViewController : UIViewController<SpinViewControllerDelegate>
{
}
#property (nonatomic, weak) IBOutlet UILabel *chosenItem;
#property (nonatomic, strong) IBOutlet UIPickerView *spinSelector;
ViewController.m
- (void)someFunction
{
mySpinViewController=[[SpinViewController alloc]init];
mySpinViewController.delegate=self;
// show or present mySpinViewController
}
//implement the followed protocol's method
-(void) optionSelected:(NSString*)cellValue{
}
SpinViewController.h
#protocol SpinViewControllerDelegate <NSObject>
#optional
-(void) optionSelected:(NSString*)cellValue;
#end
#interface SpinViewController : UIViewController <UIPickerViewDataSource, UIPickerViewDelegate>
{
ChoiceData *choiceItems;
}
#property (nonatomic,retain)id <SpinViewControllerDelegate> delegate;
#end
SpinViewController.m
-(void) pickerValueSelectedOrSimilarFn:(NSString*)cellValue{
// this is how you give a callback to classes following the protocol
[self.delegate optionSelected:cellValue];
}