iOS Protocol Issues - ios

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).

Related

I need to pass a string from a NSObject class to a UIViewController with a delegate

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];
}

iOS: how class notify something to UI view?

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];

Simple delegate example for iOS not working

I know there are tons of questions out there about passing messages between different view controllers. I've checked them all but I can't get it working.
I've followed this tutorial: http://www.youtube.com/watch?v=XZWT0IV8FrI replacing the storyboard with a navigation controller but I run across the following issue over and over again: 'Cannot find protocol declaration for...'
Here is the code:
FirstViewController.h
#import "SecondViewController.h"
#interface FirstViewController : UIViewController <SecondViewControllerDelegate>{
//In this line above is where I get the error 'Cannot find protocol declaration for SecondViewControllerDelegate'
IBOutlet UITextField *userNameTextField;
}
#property (nonatomic, strong) UITextField *userNameTextField;
-(IBAction)goNext:(id)sender;
#end
FirstViewController.m
#import "FirstViewController.h"
#interface FirstViewController ()
#end
#implementation FirstViewController
#synthesize userNameTextField;
-(void)goNext:(id)sender{
SecondViewController *secondVC = [[SecondViewController alloc]init];
secondVC.delegate = self;
[self.navigationController pushViewController:secondVC animated:YES];
}
-(void)done:(NSString*)name{
NSLog(#"BACK in firstVC");
userNameTextField.text = name;
}
#end
SecondViewController.h
#import "FirstViewController.h"
#protocol SecondViewControllerDelegate <NSObject>
-(void)done:(NSString*)someText;
#end
#interface SecondViewController : UIViewController{
IBOutlet UITextField *someText;
IBOutlet UIButton *returnButton;
id delegate;
}
#property (assign, nonatomic) id <SecondViewControllerDelegate> delegate;
#property (strong, nonatomic) UITextField *someText;
-(IBAction)goBack:(id)sender;
#end
SecondViewController.m
#import "SecondViewController.h"
#interface SecondViewController ()
#end
#implementation SecondViewController
#synthesize someText;
#synthesize delegate = _delegate;
-(void)goBack:(id)sender{
[self.delegate done:someText.text];
FirstViewController *firstVC = [[FirstViewController alloc]init];
[self.navigationController pushViewController:firstVC animated:YES];
}
#end
In your SecondViewController goBack implementation you are creating a new FirstViewController rather than popping your navigation controller, code should read...
-(void)goBack:(id)sender{
[self.delegate done:someText.text];
[self.navigationController popViewControllerAnimated:YES];
}
And also in your SecondViewController.h remover this #import "FirstViewController.h" as it is no longer needed and could be confusing the compiler
Your protocol name is EYSSecondViewControllerDelegate:
#protocol EYSSecondViewControllerDelegate <NSObject>
but you call it SecondViewControllerDelegate in two places:
#interface EYSFirstViewController : UIViewController <SecondViewControllerDelegate>{...
#property (assign, nonatomic) id <SecondViewControllerDelegate> delegate;...
Make sure that the name match and it should works fine.
In SecondViewController.h
remove line id delegate;
In SecondViewController.m
Update code -> [delegate done:someText.text];
'self.' remove
Try it

Delegate method not executing

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!

How to correctly access a variable from another class in Objective C

I have looked at various forums trying to find a solution to this problem. I currently have 2 classes, BluetoothViewController and AccountViewController. What I am trying to do is pass an account that the user selects from the AccountViewController to BluetoothViewController, so I can use that string later in the BluetoothViewController. What I have done is create an instance of AccountViewController in BluetoothViewController.h and I have created a property for the string in the AccountViewController.h file. The string that I am trying to access is "account8"
My AccountViewController.h file:
#interface AccountViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>
{
NSArray *tableData;
int cellValue;
NSString *cellContents;
NSString *account8;
}
#property (nonatomic, retain) NSArray *tableData;
#property (nonatomic, retain) NSString *cellContents;
#property (nonatomic, retain) NSString *account8;
My AccountViewController.m file:
#import "AccountViewController.h"
#interface AccountViewController ()
#end
// Implementing the methods of ViewController
#implementation AccountViewController
#synthesize tableData;
#synthesize cellContents;
#synthesize account8;
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
account8 = [tableData objectAtIndex:indexPath.row];
BluetoothViewController *bluetoothViewController = [[BluetoothViewController alloc] initWithNibName:#"BluetoothViewController" bundle:nil];
[kAppDelegate setSelectedTabWithTag:-1];
[self.navigationController pushViewController:bluetoothViewController animated:YES];
}
My BluetoothViewController.h
#import "AccountViewController.h"
#interface BluetoothViewController : UIViewController <GKPeerPickerControllerDelegate, GKSessionDelegate>{
AccountViewController *classobj;
}
#property(nonatomic, retain) AccountViewController *classObj;
My BluetoothViewController.m file:
#import "AccountViewController.h"
#import "BluetoothViewController.h"
#interface BluetoothViewController ()
#end
// Implementing the methods of ViewController
#implementation BluetoothViewController
- (void)viewDidLoad {
[connect setHidden:NO];
[disconnect setHidden:YES];
[super viewDidLoad];
count = 0;
classobj = [[AccountViewController alloc] init];
accountSelected = classobj.account8;
accountSelection.text = accountSelected;
}
When the user selects the row from a table, the contents will be saved in the variable account8. BluetoothViewController will then be called. Now, when BluetoothViewController loads up, the account that was selected by the user is supposed to be shown. However the label returns blank. I am wondering why it does not correctly access the variable saved in AccountViewController.
What you can do is to create an instance variable in Bluetoothcontroller and then after instantiating that object you set it from your AccountViewController. For example:
AccountViewController:
BluetoothViewController *bluetoothViewController = [[BluetoothViewController alloc] initWithNibName:#"BluetoothViewController" bundle:nil];
bluetoothViewController.accountVariable = _account8;
BluetoothViewController:
#property (nonatomic, copy) NSString *accountVariable;
Or are there any other reason you need to have classobj?
Please check code given below:
AccountViewController.h file:
#import "AccountViewController.h"
#interface BluetoothViewController : UIViewController <GKPeerPickerControllerDelegate, GKSessionDelegate>{
AccountViewController *classobj;
}
#property(nonatomic, retain) AccountViewController *classObj;
BluetoothViewController.h file:
#import "AccountViewController.h"
#interface BluetoothViewController : UIViewController <GKPeerPickerControllerDelegate, GKSessionDelegate>
#property(nonatomic, retain) AccountViewController *classObj;
AccountViewController.m file:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
account8 = [tableData objectAtIndex:indexPath.row];
BluetoothViewController *bluetoothViewController = [[BluetoothViewController alloc] initWithNibName:#"BluetoothViewController" bundle:nil];
[kAppDelegate setSelectedTabWithTag:-1];
[bluetoothViewController.view setAlpha:1.0f];
[bluetoothViewController setClassObj:self];
[self.navigationController pushViewController:bluetoothViewController animated:YES];
}
BluetoothViewController.m file:
- (void)viewDidLoad {
[connect setHidden:NO];
[disconnect setHidden:YES];
[super viewDidLoad];
count = 0;
// Here classObj is already assigned to a reference so you can directly use that one
}
Hope this will help you.
Using your XCode you need to make import, create object by declaring it as the property, and then use "object.variable" syntax. The file "AccountViewController.m" would look in the following way:
#import AccountViewController.h
#import BluetoothViewController.h;
#interface AccountViewController ()
...
#property (nonatomic, strong) BluetoothViewController *bluetoothViewController;
...
#end
#implementation AccountViewController
//accessing the variable from balloon.h
...bluetoothViewController.variableFromBluetoothViewController...;
...
#end

Resources