Have declared a protocol in a header file, but the implementation file says that it can't see the delegate. Why?
The Xcode compiler message is commented out in the implementation file.
Thanks in advance.
AddItemViewController.h
#import <UIKit/UIKit.h>
#class AddItemViewController;
#class ChecklistItem;
#protocol AddItemViewControllerDelegate <NSObject>
- (void)addItemViewControllerDidCancel:(AddItemViewController *)controller;
- (void)addItemViewController:(AddItemViewController *)controller didFinishAddingItem:(ChecklistItem *)item;
#property (nonatomic, weak) id <AddItemViewControllerDelegate> delegate;
#end
#interface AddItemViewController : UITableViewController <UITextFieldDelegate>
#property (weak, nonatomic) IBOutlet UITextField *textField;
#property (weak, nonatomic) IBOutlet UIBarButtonItem *doneBarButton;
- (IBAction)cancel;
- (IBAction)done;
#end
AddItemViewController.m
- (IBAction)cancel
{
[self.delegate addItemViewControllerDidCancel:self]; /* Semantic issue: Property 'delegate' not found on object of type "AddItemViewController" */
}
- (IBAction)done
{
ChecklistItem *item = [[ChecklistItem alloc] init];
item.text = self.textField.text;
item.checked = NO;
[self.delegate AddItemViewController:self didFinishAddingItem:item]; /* Semantic issue: Property 'delegate' not found on object of type "AddItemViewController" */
}
aeh .. is that a typo? the delegate property is defined on the delegate protocol. of course the VC class can't see it ;)
Related
I created a custom UIView with the buttons above , this view opens as a pop- up to a viewcontroller . I want the view controller intercepts the pressure of the buttons so I created a protocol methods but delegates in the view controller is never called.
The protocol:
#protocol InsertDelegate <NSObject>
-(void)addNode:(double)x pointY:(double)y radius:(double)r forw:(int)forw;
-(void)cancelView:(UIView*)view;
#end
In the AddNewNode.h
#interface AddNewNode : UIView
#property (assign, nonatomic)id <InsertDelegate> delegate;
- (IBAction)actionCancel:(id)sender;
- (IBAction)actionAdd:(id)sender;
#end
In the AddNewNode.m
- (IBAction)actionCancel:(id)sender { //this action is connect with storyboard
NSLog(#"%#", self.delegate);
//(null)
[self.delegate cancelView:self];
}
- (IBAction)actionAdd:(id)sender { //this action is connect with storyboard
NSLog(#"%#", self.delegate);
//(null)
[self.delegate addNode:x pointY:y radius:r forw:f];
}
In ViewController.h:
#interface ViewController : UIViewController <InsertDelegate>
In ViewController.m
(IBAction)addNewNode:(id)sender {
AddNewNode * addRowView =[[AddNewNode alloc]init];
addRowView.delegate=self;
[self.view addSubview: addRowView];
}
//delegate methods never called
-(void)addNode:(double)x pointY:(double)y radius:(double)r forw:(int)forw{
}
-(void)cancelView:(UIView*)view{
}
In UIView custom self.delegate become null and I don't understand why
What about making an IBOutlet for your
ViewController.h
#interface ViewController : UIViewController <InsertDelegate>
#property (strong, nonatomic) AddNewNode * addNewNode;
//or connect IBOutlet of your `addNewNode`
#property (strong, nonatomic) IBOutlet (addNewNode);
#end
ViewController.m
- (IBAction)addNewNode:(id)sender
{
// you dont need to allocate anymore
self.addRowView.delegate=self;
// and you need to trigger the delegate from `- (IBAction)actionAdd:(id)sender;`
[self.addRowView actionAdd:sender];
}
try the following
Create a private property to hold the instance
#implement AddNewNode()
#propery (nonatomic, strong) AddNewNode * addNewNode;
#end
from inside the button handler
(IBAction)addNewNode:(id)sender {
self.addNewNode =[[AddNewNode alloc]init];
self.addRowView.delegate=self;
}
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'm building my first iOS app to try and learn iOS coding. However, I need to pass a value xAuthToken from one controller to the other. I can't seem to get it working to. I init the value in the first controller ViewController, but then I need it in SettingsController. I keep getting errors and the one it throws now is: Property 'ViewController' not found on object of type 'ViewController'
What am I doing wrong?
ViewController.h
#import <UIKit/UIKit.h>
#import "SettingsController.h"
#interface ViewController : UIViewController <UITextFieldDelegate>
#property (weak, nonatomic) IBOutlet UITextField *txtUsername;
#property (weak, nonatomic) IBOutlet UITextField *txtPassword;
- (IBAction)sigininClicked:(id)sender;
- (IBAction)backgroundTap:(id)sender;
#end
ViewController.m
#import "ViewController.h"
#interface ViewController ()
#property (nonatomic) NSString *xAuthToken;
#end
#implementation ViewController
- (IBAction)sigininClicked:(id)sender {
NSString *xAuthToken = #"0";
self.viewController = [[SettingsController alloc] init];
self.viewController.xAuthToken = xAuthToken;
[self performSegueWithIdentifier:#"login_success" sender:self];
}
SettingsController.h
#import <Foundation/Foundation.h>
#interface SettingsController : UIViewController
#end
SettingsController.m
#interface SettingsController ()
#property (weak, nonatomic) IBOutlet UITextField *myTextField;
#property (weak, nonatomic) IBOutlet UISwitch *mySwitch;
#end
#implementation SettingsController
//THIS IS WHERE I NEED XAUTHTOKEN
If you have a segue that presents your SettingsController, pass the information it needs in prepareForSegue. Don't create a new local SettingsController.
You can do something like
viewController = [self.storyboard instantiateviewcontrollerwithidentifier:#"your vc name"];
viewController.Xauthtoken = data;
// Do something else with this.
Or another way ( I don't know if it's good or bad, use it while your vc is already active ):
Use NSNotificationCenter and pass values between it.
Third way is create delegate for first Viewcontroller.
Try this in your ViewController.m:
#import "ViewController.h"
#interface ViewController ()
#property (nonatomic) NSString *xAuthToken;
#end
#implementation ViewController
- (IBAction)sigininClicked:(id)sender {
xAuthToken = #"Your Value Here";
[self performSegueWithIdentifier:#"login_success" sender:self];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"login_success"]) {
SettingsController *destViewController = segue.destinationViewController;
destViewController.xAuthToken = xAuthToken;
}
}
And in your SettingsController.h
#import <Foundation/Foundation.h>
#interface SettingsController : UIViewController
#property (nonatomic,strong) NSString *xAuthToken;
#end
SettingsController.m
#interface SettingsController ()
#property (weak, nonatomic) IBOutlet UITextField *myTextField;
#property (weak, nonatomic) IBOutlet UISwitch *mySwitch;
#end
#implementation SettingsController
-(void)viewDidLoad{
NSLog("%#",xAuthToken);
}
I'm trying to see why the type can't be read from the protocol. I figured that the it's because the #interface is below the protocol but if someone can help me figure out the problem and explain to me why that would be great.
#import <UIKit/UIKit.h>
#protocol ARCHCounterWidgetDelegate <NSObject>
- (UIColor *) counterWidget: (ARCHCounterWidget *) counterWidget;
#end
#interface ARCHCounterWidget : UIView
#property (weak, nonatomic) id<ARCHCounterWidgetDelegate> delegate;
#end
You have to either forward declare the class or the protocol:
// tell the compiler, that this class exists and is declared later:
#class ARCHCounterWidget;
// use it in this protocol
#protocol ARCHCounterWidgetDelegate <NSObject>
- (UIColor *) counterWidget: (ARCHCounterWidget *) counterWidget;
#end
// finally declare it
#interface ARCHCounterWidget : UIView
#property (weak, nonatomic) id<ARCHCounterWidgetDelegate> delegate;
#end
or:
// tell the compiler, that this protocol exists and is declared later
#protocol ARCHCounterWidgetDelegate;
// now you can use it in your class interface
#interface ARCHCounterWidget : UIView
#property (weak, nonatomic) id<ARCHCounterWidgetDelegate> delegate;
#end
// and declare it here
#protocol ARCHCounterWidgetDelegate <NSObject>
- (UIColor *) counterWidget: (ARCHCounterWidget *) counterWidget;
#end
The compiler is not yet aware of the ARCHCounterWidget, and therefore cannot resolve the type in the delegate method. Simple solution is:
#import <UIKit/UIKit.h>
// Reference the protocol
#protocol ARCHCounterWidgetDelegate
// Declare your class
#interface ARCHCounterWidget : UIView
#property (weak, nonatomic) id<ARCHCounterWidgetDelegate> delegate;
#end
// Declare the protocol
#protocol ARCHCounterWidgetDelegate <NSObject>
- (UIColor *) counterWidget: (ARCHCounterWidget *) counterWidget;
#end
It just makes it so that the compiler knows that the protocol is defined SOMEWHERE and can be referenced
I have application where i have two view controllers my first view and second view controller is in uipopovercontroller. i want value of second view controller in first view for that i have created protocol. here is my code.
#import
#import "SearchPopoverController.h"
#import "AppDelegate.h"
#interface ViewController : UIViewController<PassSearchValueDelegate>{
AppDelegate *appDelegate;
SearchPopoverController *popSearch;
IBOutlet UILabel *lblAdd;
}
-(IBAction)showpop:(id)sender;
#end
#import "ViewController.h"
// my ViewController.m file code
-(void) getLocationList:(NSString *)strSearch{
lblAdd.text = strSearch;
}
-(IBAction)showpop:(id)sender{
if(![appDelegate.delObjSearchPopoverCon isPopoverVisible]){
SearchPopoverController *popser = [[SearchPopoverController alloc] init];
popSearch = popser;
[popSearch setDelegate:self];
appDelegate.delObjSearchPopoverCon = [[UIPopoverController alloc] initWithContentViewController:popSearch] ;
[appDelegate.delObjSearchPopoverCon setPopoverContentSize:CGSizeMake(400 , 150)];
[appDelegate.delObjSearchPopoverCon presentPopoverFromRect:CGRectMake(0, 0, 1, 1) inView:self.view permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
}
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
#protocol PassSearchValueDelegate
#required
-(void) getLocationList:(NSString *)strSearch;
#end
#interface SearchPopoverController : UIViewController <UITextFieldDelegate>{
AppDelegate *appDelegate;
IBOutlet UITextField *txtSearchAdd;
IBOutlet UILabel *lblSearchAdd;
id<PassSearchValueDelegate> _delegate;
}
#property (retain) id _delegate;
#end
// my SearchPopoverController.m file code
-(IBAction)btnDoneSearch_clicked:(id)sender{
NSString *strAdd = [txtSearchAdd.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
strAdd = [strAdd stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
[appDelegate.delObjSearchPopoverCon dismissPopoverAnimated:YES];
if (strAdd != nil || strAdd.length != 0) {
[_delegate getLocationList:strAdd];
}
}
i am getting warning at this line.
[popSearch setDelegate:self];
and app getting crashed very next line.
Please help me for this. Any help will be appreciated.
id<PassSearchValueDelegate> _delegate;
// ...
#property (retain) id _delegate;
Your property should be named just delegate and maybe synthesized to use the _delegate instance variable. You should also specify the protocol on the property type.
Additionally, delegates should be assign (or weak under ARC) properties.
rename _delegate to delegate
You will need to change
#property (retain) id delegate;
to
#property (assign) id<PassSearchValueDelegate> delegate;
Also in PassSearchValueDelegate.m add
#implementation PassSearchValueDelegate //After this
#synthesize delegate; //add this