Delegate not getting set in iOS5 StoryBoard UISplitViewController - iphone

I have a Universal app with UISplitViewConroller. I am using storyboards.
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad)
{
UISplitViewController *splitViewController = (UISplitViewController *)self.window.rootViewController;
UINavigationController *masterNavigationController = [splitViewController.viewControllers objectAtIndex:0];
LeftViewContrller *lcontroller = (LeftViewContrller *)masterNavigationController.topViewController;
id<SplitViewDelegate> rightController = (id<SplitViewDelegate>)[splitViewController.viewControllers objectAtIndex:1];
lcontroller.delegate = rightController;
}
I have a left and right controller for UISplitViewController app.
LeftViewController has a custom delegate, which is set as RightViewController.
//Custom delegate
#protocol SplitViewDelegate <NSObject>
- (void) matchSelectionChanged:(NSString *)curSelection;
#end
//LeftViewContoller
#interface LeftViewContrller : UITableViewController {
id<SplitViewDelegate> _delegate;
NSMutableArray *_matches;
}
#property (strong) id<SplitViewDelegate> delegate;
#property (strong) NSMutableArray *matches;
#end
RightViewController implements this delegate protocol. However, when cell inside row is clicked in LeftViewController the delegates failing.
//RightViewController
#interface RightViewController : UIViewController <SplitViewDelegate>
#property (weak,nonatomic) IBOutlet UILabel *matchLabel;
#end
//Implementation of RightViewController
- (void) matchSelectionChanged:(NSString *)curSelection {
self.matchLabel.text = curSelection;
//[self refresh];
}
//Did select row in LeftViewController
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSMutableString *s = [[NSMutableString alloc] initWithString:#"Row selected"];
if (_delegate != nil) {
[s appendFormat:#" %d ", indexPath.row];
[_delegate matchSelectionChanged:s];
}
}
//Get error
CustomViewTab[1200:11303] * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UINavigationController matchSelectionChanged:]: unrecognized selector sent to instance 0xda6a770'
* First throw call stack:
(0x1559052 0x1da8d0a 0x155aced 0x14bff00 0x14bfce2 0x1204e 0x62071d 0x620952 0x25986d 0x152d966 0x152d407 0x14907c0 0x148fdb4 0x148fccb 0x2500879 0x250093e 0x590a9b 0x1df8 0x1d55)
terminate called throwing an exception
I see didSelectRowAtIndex called but then RightViewController's matchSelectionChanged:(NSString *)curSelection never gets called.

Bit of an old question but I stumbled up on it and at a glance do you have the correct delegate?
#interface RightViewController : UIViewController <UISplitViewControllerDelegate>
I'm looking at iOS7 so maybe its changed since iOS5

Related

SIGARBT error crashing app

I built this calculator app in xcode 4.5 the digits work as expected but the operations ie (+,- ,c)worked once and never since they only return Nan and inf and the enter button always crashes the app and returns the error below.I built the UI in the storyboard and linked buttons to relevant methods
#autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([CalculatorAppDelegate
class]));
This is my CalculatorViewController.h
#import <UIKit/UIKit.h>
#interface CalculatorViewController : UIViewController
#property (weak, nonatomic) IBOutlet UILabel *display;
#end
This is my CalculatorViewController.m
#import "CalculatorViewController.h"
#import "CalculatorBrain.h"
#interface CalculatorViewController ()
#property(nonatomic) BOOL userIsInTheMidleOfEnteringANumber;
#property (nonatomic, strong)CalculatorBrain *brain;
#end
#implementation CalculatorViewController
#synthesize display = _display;
#synthesize userIsInTheMidleOfEnteringANumber =_userIsInTheMidleOfEnteringANumber;
#synthesize brain = _brain;
- (CalculatorBrain *)brain
{
if (!_brain)_brain=[[CalculatorBrain alloc]init];
return _brain;
}
- (IBAction)digitPressed:(UIButton *)sender
{
NSString *digit = sender.currentTitle;
if (self.userIsInTheMidleOfEnteringANumber){
self.display.text = [self.display.text stringByAppendingString:digit];
}
else {
self.display.text = digit;
self.userIsInTheMidleOfEnteringANumber=YES;
}
}
- (IBAction)enterPressed
{
NSLog(#"im hre");
[self.brain pushOperand:[self.display.text doubleValue]];
self.userIsInTheMidleOfEnteringANumber=NO;
}
- (IBAction)operationPresed:(UIButton *)sender
{
if (self.userIsInTheMidleOfEnteringANumber) [self enterPressed];
double result =[self.brain performOperation:sender.currentTitle];
NSString *resultString= [NSString stringWithFormat:#"%g",result];
self.display.text= resultString;
}
#end
This is my CalculatorBrain.h
#import <Foundation/Foundation.h>
#interface CalculatorBrain : NSObject
-(void)pushOperand:(double)operand;
-(double)performOperation:(NSString *)operation;
#end
This is my CalculatorBrain.m
#import "CalculatorBrain.h"
#interface CalculatorBrain()
#property (nonatomic,strong)NSMutableArray *operandStack;
#end
#implementation CalculatorBrain
#synthesize operandStack = _operandStack;
-(NSMutableArray *)operandStack
{
if (_operandStack== nil) _operandStack =[[NSMutableArray alloc] init];
return _operandStack;
}
-(void)pushOperand:(double)operand
{
[self.operandStack addObject:[NSNumber numberWithDouble:operand]];
}
-(double)popOperand
{
NSNumber *operandObject = [self.operandStack lastObject];
if (operandObject) [self.operandStack removeLastObject];
return [operandObject doubleValue];
}
-(double)performOperation:(NSString *)operation
{
double result=0;
//calculate result
if ([operation isEqualToString:#"+"])
{
result =[self popOperand]+ [self popOperand];
}
else if ([operation isEqualToString:#"*"])
{
result = [self popOperand] * [self popOperand];
}
else if ([operation isEqualToString:#"-"]) {
result = [self popOperand] - [self popOperand];
}
else if ([operation isEqualToString:#"/"]) {
result = [self popOperand] / [self popOperand];
}
[self pushOperand:result];
return result;
}
#end
Im working from an example and have followed all steps i dont understand what im doing wrong the enterPressed method does not have a type ie UIButton This is my console output
2013-05-17 15:05:15.221 Calculator[786:11303] im hre
2013-05-17 15:05:15.280 Calculator[786:11303] -[CalculatorViewController enterPressed:]: unrecognized selector sent to instance 0x922a620
2013-05-17 15:05:15.288 Calculator[786:11303] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[CalculatorViewController enterPressed:]: unrecognized selector sent to instance 0x922a620'
*** First throw call stack:
(0x1c8e012 0x10cbe7e 0x1d194bd 0x1c7dbbc 0x1c7d94e 0x10df705 0x16920 0x168b8 0xd7671 0xd7bcf 0xd6d38 0x4633f 0x46552 0x243aa 0x15cf8 0x1be9df9 0x1be9ad0 0x1c03bf5 0x1c03962 0x1c34bb6 0x1c33f44 0x1c33e1b 0x1be87e3 0x1be8668 0x1365c 0x1f0d 0x1e35)
libc++abi.dylib: terminate called throwing an exception
(lldb)
any help will b appreciated
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[CalculatorViewController enterPressed:]: unrecognized selector sent to instance 0x922a620' is the answer here. Check if your have the method enterPressed:in your CalculatorViewController class. I'm sure it's somehow misspelled if not missing
Change method signature:
- (IBAction)enterPressed
to
- (IBAction)enterPressed:(id)sender
In your CalculatorViewController.m file replace
- (IBAction)enterPressed
to
- (IBAction)enterPressed:(UIButton *)sender
I had this exact same problem actually... I deleted the Enter button and recreated it and then it worked after. Good luck, I wanted to pull my hair out
There are many working answers out there below. The reason why you have ran into this issue is, the method which you have linked in your xib file against one of your button appear on xib, points to enterPressed: - A method with an argument (enterPressed followed by a colon), but you have coded a method without an argument (enterPressed), hence it leads to a crash. Code tried to find a method with an argument which you have linked in your xib file, but it didn't find it, leads to a crash saying - ' unrecognized selector sent to instance'
Hence just replace
- (IBAction)enterPressed
with this:
- (IBAction)enterPressed:(UIButton *)sender

iOS: trouble sharing data between two view controllers

I have an app, which has a first view controller called MainViewController that's sorta like a stopwatch, and when I click finish, it displays a UIAlertView pushes another view controller, EndViewController, which shows how long the stopwatch was running and how long it was paused. I am getting the following errors:
My Point[851:c07] -[EndViewController topViewController]: unrecognized selector sent to instance 0x754db60
My Point[851:c07] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[EndViewController topViewController]: unrecognized selector sent to instance 0x754db60'
Can anyone point ou to me what's wrong?
heres my code:
MainViewController.h:
#import "EndViewController.h"
#interface MainViewController : UIViewController <UITableViewDataSource, UITableViewDelegate, UITextFieldDelegate, UIAlertViewDelegate>
#property (strong, nonatomic) IBOutlet UILabel *out;
#property (strong, nonatomic) IBOutlet UILabel *in;
#end
MainViewController.m:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([segue.identifier isEqualToString:#"endtask"]){
UINavigationController *navController = (UINavigationController *)segue.destinationViewController;
EndViewController *controller = (EndViewController *)navController.topViewController;
controller.timeIn.text=_in.text;
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
_alert = [[UIAlertView alloc] initWithTitle:#"Are you sure?"
message:nil
delegate:self
cancelButtonTitle:#"NO"
otherButtonTitles:#"YES", nil];
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex == 0) {
//do nothing
}
else if (buttonIndex == 1) {
[self performSegueWithIdentifier:#"endtask" sender:self];
}}
- (IBAction)endButton:(UIButton *)sender {
[_alert show];
}
- (IBAction)endButton:(UIButton *)sender {
[_alert show];
}
EndViewController.h:
#interface EndViewController : UIViewController
#property (weak, nonatomic) IBOutlet UILabel *timeIn;
#end
You're calling a method named topViewController on an object which doesn't have the method/property. It's this line here:
EndViewController *controller = (EndViewController *)navController.topViewController;
I would suspect its because the view controller you are assigning to navController isn't actually a navigation controller, but is something else. Check your storyboards/nibs for this.
Also, try logging navController, as one commentor said, and see what that gives you.
NSLog(#"%#", navController);
If you are passing a string with timeIn you should have #property of a NSString in the endViewController.h
#property (strong, nonatomic) NSString * timeIn ;
Then in you endViewController.m you put the timeIn into a labe for example.
myLabel.text = timeIn;

Why is my tableView not displaying objects?

First of I would like to start with I am 100% new to iPhone development. I believe this is a quite simple question for someone experienced. Anyhow, what I am trying to do is:
The user should via the SearchUI be able to search for objects from my database. If the object exist, display it in the tableView where the search-objects will be displayed. I manage to get the objects from the database but not instance them into the tableview and display them.
Honestly I don't know what I am doing wrong. All help will be really appreciated and also some explaining if possible. Under method - (void)objectLoader:(RKObjectLoader *)objectLoader didLoadObjects:(NSArray *)objects - I try to move the objects into the tableView without any success. You find the method in FirstViewController.m at the end of pragma mark TableView Data Scource methods. Here is my code:
FirstViewController.h class
#import <UIKit/UIKit.h>
#import <RestKit/RestKit.h>
#interface FirstViewController : UIViewController <UITableViewDataSource, RKObjectLoaderDelegate>
{
UISearchDisplayController *searchDisplayController;
UISearchDisplayController *searchBar;
UITableView *table;
NSArray *allItems;
NSArray *searchResults;
}
#property (nonatomic, retain) IBOutlet UISearchDisplayController *searchDisplayController;
#property (nonatomic, retain) IBOutlet UISearchDisplayController *searchBar;
#property (nonatomic, retain) IBOutlet UITableView *table;
#property (nonatomic, copy) NSArray *allItems;
#property (nonatomic, copy) NSArray *searchResults;
#end
FirstViewController.m class
#import "FirstViewController.h"
#import "Task.h"
interface FirstViewController ()
end
implementation FirstViewController
#synthesize searchDisplayController;
#synthesize searchBar;
#synthesize allItems;
#synthesize searchResults;
#synthesize table;
#pragma mark - View lifecycle
- (void)viewDidLoad
{
//self.listContent = [[NSArray alloc] initWithObjects:#"John", #"Paul", nil];
//self.filteredListContent = [NSMutableArray arrayWithCapacity:10];
[super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib.
}
- (void)viewDidUnload
{
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation)interfaceOrientation
{
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone)
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
else
{
return YES;
}
}
-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
return NO;
}
- (BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchScope:(NSInteger)searchOption
{
return NO;
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)pSearchBar
{
[[RKObjectManager sharedManager].mappingProvider setMapping:[Task getMapping] forKeyPath:#"tasks"];
NSString *path = [NSString stringWithFormat:#"%#/%#/%#", #"/book/1/tasks/", pSearchBar.text, #".json"];
[[RKObjectManager sharedManager] loadObjectsAtResourcePath:path delegate:self];
NSLog(#"Search: %#", pSearchBar.text);
}
#pragma mark - TableView Data Scource methods
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.searchResults count];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
{
UITableViewCell *cell = nil;
cell = [tableView dequeueReusableCellWithIdentifier:#"MyCell"];
if(cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"MyCell"];
}
cell.textLabel.text = [self.searchResults objectAtIndex:indexPath.row];
return cell;
}
- (void) deselect {
//[self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES];
}
// Respond to user selection tap by coloring the navigation bar
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)newIndexPath
{
}
- (void)objectLoader:(RKObjectLoader *)objectLoader didLoadObjects:(NSArray *)objects
{
self.searchResults = objects;
[self.table reloadData];
for(Task *task in objects)
{
if ([task isKindOfClass:[Task class]])
{
NSLog(#"Loaded Book ID: %# ; Name: %# ; Book: %#", task.id, task.name, task.book.name);
}
}
}
- (void)objectLoader:(RKObjectLoader *)objectLoader didFailWithError:(NSError *)error
{
NSLog(#"Encountered an error: %#", error);
}
#end
Step1. Since your TableView is an IBOutlet, check you tableView datasource and delegate mappings in the .xib file for this view controller. My doubt is that the hooking is not correct.
Step2. If the hook ups in .xib file are correct, then you should do
- (void)objectLoader:(RKObjectLoader *)objectLoader didLoadObjects:(NSArray *)objects
{
self.searchResults = objects;
NSLog(#"%#", searchResults)
[self.table reloadData];
....
}
and check if the NSLog is logging the searchResults array. If that's empty for some reason, your numberOfRowsInSection delegate method will return 0 and hence your tableView will be empty.
Hope this helps.
in the first line
#interface FirstViewController : UIViewController <UITableViewDataSource, RKObjectLoaderDelegate>
{
UISearchDisplayController *searchDisplayController;
UISearchDisplayController *searchBar;
UITableView *table;
NSArray *allItems;
NSArray *searchResults;
}
replace this line with below code
#interface FirstViewController : UIViewController <UITableViewDataSource, UITableViewDelegate, RKObjectLoaderDelegate>
{
UISearchDisplayController *searchDisplayController;
UISearchDisplayController *searchBar;
IBOutlet UITableView *table;
NSArray *allItems;
NSArray *searchResults;
}
and connect the tableview delegate and tableview datasource in interface builder.
Hope it helps.

Passing Values Between Master and Detail in UISplitViewController Using Storyboards

I have defined the protocol in Customer.h file which is shown below:
#class Customer;
#protocol CustomerDelegate <NSObject>
-(void) didSelectCustomer:(Customer *) customer;
#end
#interface Customer : NSObject
{
}
#property (nonatomic,copy) NSString *name;
#property (nonatomic,copy) NSString *occupation;
#end
The MasterViewController (left side) invokes the didSelectCustomer method as shown below:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
Customer *selectedCustomer = [customers objectAtIndex:[indexPath row]];
[self.delegate didSelectCustomer:selectedCustomer];
}
Now, I need to tell the DetailViewController (right side) to do something. The DetailViewController complies with the CustomerDelegate protocol.
#interface DetailViewController : UIViewController<UISplitViewControllerDelegate,CustomerDelegate>
{
}
-(void) didSelectCustomer:(Customer *)customer
{
NSLog(#"sssdasdasdasd");
}
The didSelectCustomer method is never invoked. I think I need to set the masterViewController.delegate = self but I am not sure where to set this thing up.
UPDATE 1:
I added the instance of MasterViewController inside the DetailViewController but it did not work:
- (void)viewDidLoad
{
[super viewDidLoad];
MasterViewController *master = [[MasterViewController alloc] init];
master.delegate = self;
}
SOLUTION:
In AppDelegate:
else
{
UISplitViewController *splitViewController = (UISplitViewController *) self.window.rootViewController;
splitViewController.delegate = [splitViewController.viewControllers lastObject];
UINavigationController *navigationController = [splitViewController.viewControllers lastObject];
// splitViewController.delegate = (id)navigationController.topViewController;
DetailViewController *detail =(DetailViewController *) [splitViewController.viewControllers lastObject];
UINavigationController *masterNavigationController = [splitViewController.viewControllers objectAtIndex:0];
MasterViewController *master = (MasterViewController *)masterNavigationController.topViewController;
master.delegate = detail;
}
You never explicitly declare yourself as the delegate to the Consumer class. Merely conforming to it won't cut it. Declare it in -viewDidLoad by creating an instance of Consumer, possibly like this:
-(void)viewDidLoad {
Consumer *consumer = [[Consumer alloc]init];
[consumer setDelegate:self];
}
You also don't declare a property for your delegate object in Consumer, so it can never actually be accessed. Do this first:
#class Customer;
#protocol CustomerDelegate <NSObject>
-(void) didSelectCustomer:(Customer *) customer;
#end
#interface Customer : NSObject
{
}
#property (nonatomic,copy) NSString *name;
#property (nonatomic,copy) NSString *occupation;
#property (weak) id <CustomerDelegate> delegate; //use assign or __unsafe_unretained if targeting <5.0.
#end
You can check if your class conforms to your protocol like so:
if (![delegate conformsToProtocol:#protocol(CustomerDelegate)]) {
[NSException raise:#"Delegate Exception"
format:#"Parameter does not conform to CustomerDelegate protocol at line %d", (int)__LINE__];
}
the split view controller's last object.
this object is return a UI navigation controller.
you know, then you can do yourself.

Pushing UITableViewController onto [self navigationController] causes an EXC_BAD_ACCESS

In the current view that I am in, a button touch-up-inside event leads to the following action:
(Note that while in the Debugger, I've verified that both [self navigationController] and the instantiated historyViewController do indeed exist.
I am unable to determine why this bad access is happening. I can pop/push this view/other views from the navigation controller. Any ideas on how to go about investigating why this view in particular is having problems when getting pushed onto the nav controller?
-(IBAction) viewOrEditHistory: (id) sender {
HistoryViewController *historyViewController = [[HistoryViewController alloc] initWithStyle:UITableViewStyleGrouped];
historyViewController.title = #"View or Edit by date";
historyViewController.sameExSessions = [[NSMutableArray alloc] init];
historyViewController.exercise = [[Exercise alloc] initWithName:self.title muscleGroup:muscleGroupLabel.text];
/*** EXC_BAD_ACCESS happens after following line is executed ***/
[[self navigationController] pushViewController:historyViewController animated:YES];
}
Here is my HistoryViewController.h
#import
#interface HistoryViewController : UITableViewController {
NSMutableArray *sameExSessions;
Exercise *exercise;
}
#property (nonatomic, retain) NSMutableArray *sameExSessions;
#property (nonatomic, retain) Exercise *exercise;
-(NSMutableArray *) SameExerciseSessionList;
-(NSString *) getDocPath;
-(NSInteger) tableView:(UITableView *) tableView numberOfRowsInSection: (NSInteger)section;
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *) indexPath;
#end
Please also get your memory management straight or you will run into a lot more problems. Every alloc should be followed by either a release or an autorelease.