I've a main class where I want to define two protocols (1 used by a class A, the other by class B) (ios 6.1, xcode 4.6.3 , ARK mode, storyboard project).
According to official syntax, all my code seems to be correct.
But when I try to use the second delegate , nothing work correctly, my 2nd delegate does not respond
**HEADER myProtocols.h**
#import ...
#class myProtocols;
#protocol myProtocol1 <NSObject>
// list of methods and properties
doStuff:(float) myValue;
#end
#protocol myProtocol2 <NSObject>
// list of methods and properties
doOtherStuff:(float) myValue2 andText:(NSString *)myText andType:(NSString *)myType;
#end
#interface myProtocols:NSObject
{
__unsafe_unretained id <myProtocol1> _myDelegate1;
__unsafe_unretained id <myProtocol2> _myDelegate2;
}
#property (nonatomic, assign) id <myProtocol1> myDelegate1;
#property (nonatomic, assign) id <myProtocol2> myDelegate2;
#end
**MESSAGES myProtocols.m**
#import myProtocols.h
#implementation myProtocols
#synthesize myDelegate1 = _myDelegate1
#synthesize myDelegate2 = _myDelegate2
...
if ([_myDelegate1 respondsToSelector:#selector(doStuff:)])
[_myDelegate1 doStuff:3.5]; **// THIS DELEGATE WORK VERY WELL**
...
if ([_myDelegate2 respondsToSelector:#selector(doOtherStuff:andText:andType:)])
[_myDelegate2 doOtherStuff:4.5 andText:#"YES MAN" andType:#"YES BRO"];
**// THIS DELEGATE DONT WORK, IT'S LIKE IT DOESNT INIT**
...
#end
**HEADER classA.h**
#import "myProtocols.h"
#interface classA: UIViewController <myProtocol1>
#property(strong, nonatomic) myProtocols *myProtoVC;
//-(void) doStuff:(float) myValue; according to comments, nothing to do :(
#end
**MESSAGES classA.m**
#import "classA.h"
#interface classA ()
#end
#implementation classA
- (void)viewDidLoad
{
[super viewDidLoad];
_myProtoVC = [[myProtocols alloc] init];
_myProtoVC.myDelegate1 = self;
}
-(void) doStuff:(float) myValue
{
NSLog(#" YES VALUE IS %f",myValue);
}
**HEADER classB.h**
#import "myProtocols.h"
#interface classB: UIViewController <myProtocol2>
#property(strong, nonatomic) myProtocols *myProtoVC;
//-(void) doOtherStuff:(float) myValue2 andText:(NSString *)myText andType:(NSString *)myType; according to comments, nothing to do :(
#end
**MESSAGES classB.m**
#import "classB.h"
#interface classB ()
#end
#implementation classB
- (void)viewDidLoad
{
[super viewDidLoad];
_myProtoVC = [[myProtocols alloc] init];
_myProtoVC.myDelegate2 = self;
}
-(void) doOtherStuff:(float) myValue2 andText:(NSString *)myText andType:(NSString *)myType;
{
NSLog(#" YES VALUE IS %f and text %# and type %#",myValue2,myText,myType);
}
So, my mistake is to call [_myDelegate2 doOtherStuff..] directly inside a function in myProtocols called only by classA.
Then, if I want to call a function in myProtocols using both delegate I MUST init both these delegates in the class (A or B doesnt matter) I use to call this function:
**MESSAGES myProtocols.m**
#import myProtocols.h
#implementation myProtocols
#synthesize myDelegate1 = _myDelegate1
#synthesize myDelegate2 = _myDelegate2
-(void) pleaseDoIt
{
if ([_myDelegate1 respondsToSelector:#selector(doStuff:)])
[_myDelegate1 doStuff:3.5]; **// THIS DELEGATE WORK VERY WELL**
...
if ([_myDelegate2 respondsToSelector:#selector(doOtherStuff:andText:andType:)])
[_myDelegate2 doOtherStuff:4.5 andText:#"YES MAN" andType:#"YES BRO"];
**// THIS DELEGATE NOW WORK VERY WELL**
}
#end
**HEADER classA.h**
#import "myProtocols.h"
#import "classB.h"
#interface classA: UIViewController <myProtocol1>
#property(strong, nonatomic) myProtocols *myProtoVC;
#property(strong, nonatomic) classB *classBVC;
//-(void) doStuff:(float) myValue;
#end
**MESSAGES classA.m**
#import "classA.h"
#interface classA ()
#end
#implementation classA
- (void)viewDidLoad
{
[super viewDidLoad];
_myProtoVC = [[myProtocols alloc] init];
_classBVC = [[myProtocols alloc] init];
_myProtoVC.myDelegate1 = self;
_myProtoVC.myDelegate2 = _classBVC // THIS IS THE POINT!!!
[_myProtoVC pleaseDoIt];
}
-(void) doStuff:(float) myValue
{
NSLog(#" YES VALUE IS %f",myValue);
}
Related
I am writing a sample code in order to understand message forwarding in Objective C (iOS).
I have two classes (class A and class B). I want to create an instance of class B and set a class A instance variable to it. I am calling the Forward Invocation method (Message Forwarding) in the following code.
// ViewController.h
// TestInvocation
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
#end
// ViewController.m
// TestInvocation
#import "ViewController.h"
#import "TestInvocation.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[TestInvocation testRun];
[super viewDidLoad];
}
#end
// TestInvocation.h
// TestInvocation
#import <Foundation/Foundation.h>
#interface TestInvocation : NSObject
{}
+(void)testRun;
#end
// TestInvocation.m
// TestInvocation
#import "TestInvocation.h"
#import "ClassB.h"
#import "ClassA.h"
#implementation TestInvocation
+(void)testRun
{
ClassB* diplomat = [[ClassB alloc] init];
NSLog(#"value = %d",[diplomat value]);// Error shows up here on running:
//No visible #interface for 'ClassB' declares the selector 'value'
}
#end
// ClassA.h
// TestInvocation
#import <Foundation/Foundation.h>
#interface ClassA : NSObject
{
int value;
}
#property(readwrite,assign) int value;
#end
// ClassA.m
// TestInvocation
#import "ClassA.h"
#implementation ClassA
#synthesize value;
#end
// ClassB.h
// TestInvocation
#import <Foundation/Foundation.h>
#interface ClassB : NSObject
{}
#end
// ClassB.m
// TestInvocation
#import "ClassB.h"
#import "ClassA.h"
#implementation ClassB
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
return [ClassA instanceMethodSignatureForSelector:aSelector];
}
-(void)forwardInvocation:(NSInvocation *)anInvocation
{
ClassA* negotiate = [[ClassA alloc] init];
negotiate.value = 15;
[anInvocation invokeWithTarget:negotiate];
}
#end
I am expecting the above code to work. But instead I get the following build time error:
ARC Semantic Issue
TestInvocation.m:19:35: No visible #interface for 'ClassB' declares the selector 'value'
Class B should have the property in interface at least.
But you can make it #dynamic in implementation if you want to call forwardInvocation.
#interface ClassB : NSObject
#property (readwrite, assign) int value;
#end
#implementation ClassB
#dynamic value;
...
#end
I think it should work for you.
i have first display start_game screen than after when i click button that time display popupview using xib.in xib class i have create delegate method.when i close the popupview that time call delegate method but not calling
here is my delegate class
.h File
#import
#protocol digbuttonalertdelegate;
#interface digbuttonalert : UIViewController
#property (weak, nonatomic) IBOutlet UIImageView *bg_image;
#property (weak, nonatomic) IBOutlet UILabel *lbl_title;
#property (nonatomic, weak) id<digbuttonalertdelegate> delegate;
#end
#protocol digbuttonalertdelegate <NSObject>
#optional
-(void)digalertclose;
#end
.m File
#import "digbuttonalert.h"
#import "suggestion_alert.h"
#import "UIViewController+CWPopup.h"
#import "zoom_alert.h"
#interface digbuttonalert ()
{
bool status;
}
#end
#implementation digbuttonalert
- (void)viewDidLoad {
[super viewDidLoad];
status=0;
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tapDetected)];
singleTap.numberOfTapsRequired = 1;
[self.bg_image setUserInteractionEnabled:YES];
[self.bg_image addGestureRecognizer:singleTap];
// Do any additional setup after loading the view from its nib.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)close:(id)sender {
}
-(void)tapDetected{
NSLog(#"single Tap on imageview");
if(status==0)
{
self.lbl_title.text=#"As you walk you will discover the hidden map.This circle will show your progress.";
status=1;
}
else
{
[self dismissViewControllerAnimated:YES completion:nil];
if ([self.delegate respondsToSelector:#selector(digalertclose)]) {
[self.delegate digalertclose];
}
}
}
here this class i want to call method
#import "digbuttonalert.h"
#interface start_games () <MJSecondPopupDelegate,digbuttonalertdelegate>
{
- (void)viewDidLoad {
digbuttonalert *next=[[digbuttonalert alloc]init];
next.delegate=self;
next.modalTransitionStyle=UIWebPaginationModeRightToLeft;
next.modalPresentationStyle=17;
[self presentViewController:next animated:YES completion:nil];
}
- (void)digalertclose
{
[self StartTimer];
[[NSUserDefaults standardUserDefaults]setObject:#"false" forKey:#"alertstatus"];
}
Change .m file with below :
#protocol digbuttonalertdelegate <NSObject>
#optional
-(void)digalertclose;
#end
#interface digbuttonalert : UIViewController
#property (weak, nonatomic) IBOutlet UIImageView *bg_image;
#property (weak, nonatomic) IBOutlet UILabel *lbl_title;
#property (nonatomic, weak) id<digbuttonalertdelegate> delegate;
#end
And follow basic tutorial steps : enter link description here
Please implement digalertclose delegate in start_games controller like this
-(void)digalertclose {
}
You make digalertclose optional thats why crash does not occur if you remove optional keyword from digbuttonalertdelegate protocol you can see that there will be a crash because you try to fire a delegate but does not implement it.
In your digbuttonalert.h protocol is defined twice.
There is no #end for the interface.
Should be something like
ClassA.h
#protocol YourProtocol <NSObject>
#optional
-(void)yourProtocolOptionalMethod
#end
#interface ClassA.h
#property (weak, nonatomic) id <YourProtocol> delegate;
#end
ClassA.m
-(void) someClassAMethod {
[self.delegate yourProtocolOptionalMethod];
}
ClassB.h
#import "ClassA.h"
#interface ClassB <YourProtocol>
#end
ClassB.m
-(void) someClassBMethod {
ClassA *classA = [ClassA alloc] init];
classA.delegate = self;
}
After setting the delegate now when you will call the delegate from ClassA then it will trigger the protocol implemented method in ClassB
-(void)yourProtocolOptionalMethod {
NSlog(#"");
}
On your class , you need to declare the delegate like this:
#interface YourViewController () < digbuttonalertdelegate >
I need to pass a string from a NSObject class to a UIViewController, I understand that the best way is delegation but the delegate method isn't being called. I'm trying to set the UILabel an DieFacesViewController as the selectedOption from TemporarySelection.
A tableview shows the value of CustomOptionStore, once it's tapped passes its value to TemporarySelection and opens the modal view DieFacesViewCountroller which should, at least in my mind, take the label value from TemporarySelection. The reason I created TemporarySelection is because the DieFacesViewController will be used by other classes, not only by CustomOptionStore, and it will need to load the label from all those classes when different tableViews are selected.
I tried to set the delegate as self in both viewDidLoad and viewWillAppear with no luck, I don't understand if the view loads before being able to call the delegate method or if there's something wrong the way I set the method up.
I've been stuck here for two days, this is the first time I post a question so please forgive me if it's a bit confused.
my delegator class TemporarySelection.h is
#import <Foundation/Foundation.h>
#import "CustomOptionsStore.h"
#class DieFacesViewController;
#protocol TemporarySelectionDelegate <NSObject>
-(void)sendSelection;
#end
#interface TemporarySelection : NSObject
#property (nonatomic, weak) id <TemporarySelectionDelegate> delegate;
#property (nonatomic, strong) NSString *selectedOption;
-(void)addSelection: (CustomOptionsStore *) selection;
#end
and my TemporarySelection.m is
#import "TemporarySelection.h"
#implementation TemporarySelection
-(void)addSelection: (CustomOptionsStore *) selection{
self.selectedOption = selection.description;
[self.delegate sendSelection];
}
#end
the delegate class DiewFacesViewController.h is
#import <UIKit/UIKit.h>
#import "SelectedStore.h"
#import "TemporarySelection.h"
#interface DieFacesViewController : UIViewController <TemporarySelectionDelegate>
#property (strong, nonatomic) IBOutlet UILabel *SelectionName;
#end
and the DieFacesViewController.m is
#import "DieFacesViewController.h"
#interface DieFacesViewController ()
#end
#implementation DieFacesViewController
- (void)viewDidLoad {
TemporarySelection *ts = [[TemporarySelection alloc]init];
ts.delegate = self;
[super viewDidLoad];
}
-(void)sendSelection{
TemporarySelection *ts = [[TemporarySelection alloc]init];
self.SelectionName.text = ts.selectedOption;
}
-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:YES];
}
You are not setting the delegate object properly.Check the above code
#import "DieFacesViewController.h"
#interface DieFacesViewController ()<TemporarySelectionDelegate>
{
//global object
TemporarySelection *ts;
}
#end
#implementation DieFacesViewController
- (void)viewDidLoad {
ts = [[TemporarySelection alloc]init];
ts.delegate = self;
[super viewDidLoad];
}
-(void)sendSelection{
//Use the object to extract
self.SelectionName.text = ts.selectedOption;
}
-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:YES];
}
Starting point
I have a class, say A, used by an UI view.
A has a delegate that should notify UI view and this one should be write something on screen.
Question
What is the best approach to achieve this feature?
Seems something like observer-observable pattern
Code
---A.h
#interface A : NSObject
#end
---A.m
#implementation A
-(void)fooDelegate:(FooType *)sender {
/* Here I need to notify UI (that change notificationArea.text) */
}
---UIView.h
#interface UIView : UIViewController
#property(strong, nonatomic, retain) A* a;
#property(strong, nonatomic) IBOutlet UITextField *notificationArea;
#end
Based on the comments, I guess just code is what you're looking for...
Create your delegate protocol:
#protocol ADelegate;
#interface A : NSObject
#property (nonatomic, weak) id <ADelegate> delegate;
#end
#protocol ADelegate <NSObject>
#optional
-(void)fooDelegate:(A *)a;
#end
Notify your delegate:
#implementation A
-(void)fooDelegate:(FooType *)sender {
if ([[self delegate] respondsToSelector:#selector(fooDelegate:)]) {
[[self delegate] fooDelegate:self];
}
}
#end
Conform to the delegate protocol:
#import "A.h"
#import "MyView.h"
#interface MyView <ADelegate>
#end
#implementation MyView
-(void)fooDelegate:(A *)a {
// update text field here
}
#end
Finally, whenever you create an instance of A, set the delegate (where self in this example is an instance of MyView:
A *a = [[A alloc] init];
[a setDelegate:self];
I have four classes MainVC, ParentClient and ChildClient1, ChildClient2(which are subclasses of ParentClient). ParentClient has a delegate to MainVC such that in MainVC
- (void)viewDidLoad
{
[super viewDidLoad];
[ParentClient instance].mainViewDelegate = self;
}
And then the ParentClient looks like this
#interface BaseClient : NSObject
#property (assign) id<MainVCInteraction> mainViewDelegate;
+(instancetype) instance;
#end
Now I want to access mainViewDelegate from ChildClient1, ChildClient2 and it returns me nil while [ParentClient instance].mainViewDelegate returns the correct value
Here is what I did I removed the BaseClient Class so that ChildClient1, ChildClient2 were no longer subclasses of BaseClient. I defined a objective-c protocol file MainVCInteaction.h and made Client1, Client2 look like this:
#import "MainVCInteraction.h"
#interface ChildClient1 : NSObject
#property (assign) id<MainVCInteraction> mainViewDelegate;
+(instancetype) instance;
#end
#import "MainVCInteraction.h"
#interface ChildClient2 : NSObject
#property (assign) id<MainVCInteraction> mainViewDelegate;
+(instancetype) instance;
#end
And then MainVC implements this protocol, I assigned the delegate like this
- (void)viewDidLoad
{
[super viewDidLoad];
[ChildClient1 instance].mainViewDelegate = self;
[ChildClient2 instance].mainViewDelegate = self;
}