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
Related
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];
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 ;)
I have been staring at code too long and know i am doing something silly here with my Protocols if someone could enlighten me that would be great.
Trying to get my areaNameLabel to change to cell.nameLabel.text across viewcontrollers.
FirstTableViewController.h
#import <UIKit/UIKit.h>
#import "FirstTableCell.h"
#import "SecondViewController.h"
#interface FirstTableViewController : UITableViewController <UITableViewDataSource, UITableViewDelegate, passNames>
#property (nonatomic, strong) NSString *passedNameString;
#property (strong, nonatomic) NSMutableArray *names;
FirstTableViewController.m
#import "FirstTableViewController.h"
#interface FirstTableViewController ()
#end
#implementation FirstTableViewController
#synthesize names;
#synthesize passedNameString;
- (void)viewDidLoad
{
[super viewDidLoad];
names = [NSMutableArray arrayWithObjects:#"Bondi", #"Miranda", nil];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
FirstTableCell *cell = (FirstTableCell *)[tableView cellForRowAtIndexPath:indexPath];
if ([cell.nameLabel.text isEqualToString:#"Bondi"]) {
SecondViewController *mapController = [[SecondViewController alloc] init];
NSString *passedName = cell.nameLabel.text;
mapController.passedNameString = passedName;
[mapController setDelegate:self];
self.tabBarController.selectedIndex = 1;
NSLog(#"Hola");
}
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
#pragma mark - Protocol Methods
-(void)setAreaName:(NSString *)areaName {
passedNameString = areaName;
}
SecondViewController.h
#import <UIKit/UIKit.h>
#protocol passNames <NSObject>
-(void)setAreaName:(NSString *)areaName;
#end
#interface SecondViewController : UIViewController <RMMapViewDelegate>
#property (retain) id <passNames> delegate;
#property (nonatomic, strong) NSString *passedNameString;
#property (weak, nonatomic) IBOutlet RMMapView *mapView;
#property (weak, nonatomic) IBOutlet UILabel *areaNameLabel;
#end
SecondViewController.m
#import "SecondViewController.h"
#import "FirstTableViewController.h"
#interface SecondViewController ()
#end
#implementation SecondViewController #synthesize areaNameLabel; #synthesize delegate, passedNameString;
- (void)viewDidLoad {
[super viewDidLoad];
passedNameString = areaNameLabel.text;
[[self delegate] setAreaName:passedNameString];
if ([areaNameLabel.text isEqualToString:#"Bondi"]) {
NSLog(#"You got it!");
}
}
Any other critiques feel free to throw in - I've had a look at some other Protocol questions and examples but i know it is something obvious i am missing.
The problem is that your SecondViewController has no relationship to the passNames protocol (being declared in the same header does not count).
Since protocol methods need to be implemented (or their implementation be inherited from the base) and your SecondViewController does not do that, you cannot call setAreaName: without triggering an error.
If you would like to use a common protocol in two view controllers, you need to do this:
Give passNames protocol a more conventional name that starts in a capital letter, and put it in a separate header file
Include that header in both view controllers (the #import "SecondViewController.h" in the FirstTableViewController.h does not look right)
Put implementations of setAreaName: in both view controllers.
Note that you cannot put the common functionality in a superclass, because your view controllers inherit from different bases (i.e. UIViewController and UITableViewController).
I'm really having a tough time figuring out why one of my delegate methods performs perfectly, but another won't. Here is the relevant code for the delegate that isn't working:
SideBarController.h
#import <UIKit/UIKit.h>
#import "Report.h"
#protocol ReportSelectViewControllerDelegate <NSObject>
#optional
- (void) viewSelectMonitoredArea:(Report *)report;
#end
#interface SidebarController : UIViewController <UITableViewDataSource, UITableViewDelegate>
#property (nonatomic, weak) id <ReportSelectViewControllerDelegate> delegate;
#property (nonatomic, weak) IBOutlet UITableView *tableView;
#property (nonatomic, weak) Report *selectedReport;
#end
SideBarController.m
#import "SidebarController.h"
#interface SidebarController ()
#end
#implementation SidebarController
#synthesize tableView = _tableView;
#synthesize delegate;
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSMutableArray *sectionArray = [self.tableViewItems objectAtIndex:indexPath.section];
NSDictionary* item = sectionArray[indexPath.row];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:item[#"title"] forKey:#"CurrentReportTitle"];
self.selectedReport = [Report where:#{#"reportTitle": item[#"title"]}].lastObject;
[self.delegate viewSelectMonitoredArea:self.selectedReport];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
DetailReportViewController.h
#import <UIKit/UIKit.h>
#import "BDBSplitViewController.h"
#import "SidebarController.h"
#interface DetailReportViewController : BDBDetailViewController <UISplitViewControllerDelegate, ReportSelectViewControllerDelegate >
#end
DetailReportViewController.m
#import "DetailReportViewController.h"
#interface DetailReportViewController ()
#end
#implementation DetailReportViewController
- (void)viewDidLoad
{
[super viewDidLoad];
SidebarController *sideBarController = [[SidebarController alloc] init];
sideBarController.delegate = self;
}
- (void) viewSelectMonitoredArea:(Report *)report {
NSLog(#"viewSelectMonitoredArea was called");
}
Another delegate written exactly the same way from another controller to the DetailReportViewController works just fine. When I put a breakpoint right after the delegate is called, I notice that the delegate has a nil value. Any help would be greatly appreciated.
EDIT:
Sorry, I forgot to put in sideBarController.delegate = self in the DetailReportViewController.h example. It is in the original code.
The DetailReportViewController class needs to get a reference to the "SideBarController" instance and then set itself as the delegate. In DetailReportViewController:
// This needs to be in the DetailReportViewController class
// Assume we have a reference to the SideBarController in the DetailReportViewController class called sideBarControllerInstance
sideBarControllerInstance.delegate = self;
The solution spurred on by Michael Dautermann was to put
DetailReportViewController *detailReport = [[DetailReportViewController alloc] init];
self.delegate = detailReport;
right before
[self.delegate createSelectMonitoredArea:self.selectedReport];
Thanks!