I have a custom UITableViewCell with a class linked to it called customCell.m. (I didn't use xib.) In the cell there is a button. Is there a way to create the buttons action on the mainVC.m file, as apposed to customCell.m?
Update
Here is the code I tried implementing. What I did is, I called a method from mainVC.m.
CustomCell.m
- (IBAction)myButton:(id)sender
{
CategorieViewController *mainVC = [[CategorieViewController alloc] init];
[mainVC myMethod];
}
MainVC.m
- (void)myMethod:(id)sender
{
UITableViewCell *clickedCell = (UITableViewCell *)[[[sender superview] superview] superview];
NSIndexPath *clickedButtonPath = [self.myTableView indexPathForCell:clickedCell];
NSLog(#"%#", clickedButtonPath);
}
CategorieViewController myMethod]: unrecognized selector sent to instance 0x7fd2dbd52a00
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[CategorieViewController myMethod]: unrecognized selector sent to instance 0x7fd2dbd52a00'
You're calling myMethod, but the method is actually myMethod: and takes the sender as a parameter. Try changing:
[mainVC myMethod];
to:
[mainVC myMethod:sender];
Also, any sender you currently pass to myMethod: as a parameter, won't belong to mainVC's tableview yet because you're creating a brand new CategorieViewController instance to perform the method call and its table has never been loaded.
Assuming MainVC is the visible view controller, you can change:
CategorieViewController *mainVC = [[CategorieViewController alloc] init];
to:
UINavigationController *nav = (UINavigationController*)self.window.rootViewController;
CategorieViewController *mainVC = (CategorieViewController*)nav.visibleViewController;
to get the current the current MainVC instance with the loaded tableview.
Related
As a follow up to this question: Skip/ignore method in iOS, I'm trying to implement separate delegates for my UITableView in iOS7 and iOS8.
So, as a first step, in viewDidLoad of my MyTableViewController, I added the following code:
if ([[[UIDevice currentDevice] systemVersion] compare: #"8.0" options: NSNumericSearch] != NSOrderedAscending)
{
[self.tableView setDelegate: [[MyTVDelegate alloc] initWithIdentifier: myTVCellIdentifier]];
}
else
{
[self.tableView setDelegate: [[MyTVDelegate7 alloc] initWithIdentifier: myTVCellIdentifier]];
}
I'm adding an identifier, since I will have to apply this to multiple view controllers (or I may have just create a delegate class for each TV, I haven't figured that out yet).
I'm using CoreData, so my dataSource is an NSFetchedResultsController.
Then, I have the following for MyTVDelegate/myTVDelegate7:
#import "MyTVDelegate.h"
#implementation MyTVDelegate
- (instancetype)initWithIdentifier: (NSString *) identifier
{
if ([super init])
{
self.identifier = identifier;
}
return self;
}
#end
#implementation MyTVDelegate7
- (CGFloat)tableView: (UITableView *)tableView heightForRowAtIndexPath: (NSIndexPath *)indexPath
{
return 44;
}
- (CGFloat)tableView: (UITableView *)tableView estimatedHeightForRowAtIndexPath: (NSIndexPath *)indexPath
{
return UITableViewAutomaticDimension;
}
#end
If I run this, I'm getting the following runtime error in iOS7:
2015-01-18 10:42:51.894 -[__NSArrayI tableView:estimatedHeightForRowAtIndexPath:]: unrecognized selector sent to instance 0x7b9dd220
2015-01-18 10:42:57.731 *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArrayI tableView:estimatedHeightForRowAtIndexPath:]: unrecognized selector sent to instance 0x7b9dd220'
on iOS8, there is no crash.
The instance 0x7b9dd220 is an NSArray. My hunch is that it crashes, because the indexPath is invalid because the delegate and 'dataSource' are now separate?
I've tried moving the call to performFetch to either before or after setting the delegate, but I get the same error.
How do I fix this, should I for instance move all the NSFetchedResultsController code to the new delegate class as well?
self.tableView setDelegate: assigns a weak reference; if you don't hold your own reference to this object, it will get collected. This is why you're seeing the crash. The system has collected the memory that was assigned to your delegate, then reassigned the memory to an NSArray. Your table tries to call methods on the delegate and can't because NSArray does not respond to them.
Alongside the self.tableView property definition, define another property:
#property (strong) id<UITableViewDelegate> myTableViewDelegate;
I am trying to load a UITableViewController however i keep getting this error and my app crashes.
* Assertion failure in -[UITableView dequeueReusableCellWithIdentifier:forIndexPath:], /SourceCache/UIKit_Sim/UIKit-2935.137/UITableView.m:5439
2014-04-15 00:40:55.244 TradingGame[966:60b]* Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'unable to dequeue a cell with identifier cell - must register a nib or a class for the identifier or connect a prototype cell in a storyboard'
Heres my code
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cell" forIndexPath:indexPath];
if (cell) {
// will eventually put labels etc here.
}
return cell;
}
Here is where i call my UITableViewController to push to the screen:
if (indexPath.row == 1) {
Foo *foo = [[Foo alloc] init];
[self.navigationController pushViewController:foo animated:YES];
}
Problem solved. Thanks to #Paulw11 for pointing out about instantiating the table view.
Those who have a similar issue to me make the following changes to your instantiation of tableview:
Try this first:
Foo *foo = [[Foo alloc] init];
[self.navigationController pushViewController:foo animated:YES];
If that does not work you may have a similar problem to me therefore use this code:
Foo *foo = [self.storyboard instantiateViewControllerWithIdentifier:#"Foo"];
[self.navigationController pushViewController:foo animated:YES];
Replace classes where applicable and "Foo" should be equal to the Storyboard ID of the view controller you are trying to instantiate.
I have UIViewController that performs a login check with the code below, and a UITableViewController as its parent controller. I'm trying to add another row to the UITableViewController after switching back to it, however I'm getting the following error:
[UINavigationController insertNewObject:]: unrecognized selector sent to instance 0x14de164d0
2014-03-08 17:00:27.379 MyApp[2562:60b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UINavigationController insertNewObject:]: unrecognized selector sent to instance 0x14de164d0'
-
if(loginSuccess)
{
[self.navigationController popViewControllerAnimated:YES];
[self.navigationController performSelector:#selector(insertNewObject:) withObject:#"Another Row"];
}
The method definition of insertNewObject is:
- (void)insertNewObject:(NSString *)name
{
if (!_objects) {
_objects = [[NSMutableArray alloc] init];
}
[_objects insertObject:name atIndex:0];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
[self.tableView insertRowsAtIndexPaths:#[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
Can someone help me with what I'm doing wrong?
You're calling insertNewObject on a UINavigationController not your UITableViewController.
Try creating a property on your UIViewController that points to the original TableViewController and calling it through the property. Or calling it when the TableViewController reappears.
so I am using a PFQueryForTableViewController class connected to my storyboard. I use the queryForTable method to get the information in the back, but the information is in a different order every time that the user queries for the table. When the user presses on the cell it segues to another viewController. I need to retain the information at that cell when the user presses the cell to fill in the information on the next view controller. I am currently using the tableView: didSelectRowAtIndexPath: object: method, as well as the prepareForSegue: method. I am not sure how to retain the information, and with the code I am currently running, I am getting the error:
"'NSInvalidArgumentException', reason: '-[UITableViewCell objectAtIndex:]: unrecognized selector sent to instance 0x9b6e420'"
Here is the code for the segue:
- (void) tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[super tableView:tableView didSelectRowAtIndexPath:indexPath];
self.selectedCell = indexPath;
[self performSegueWithIdentifier:#"profile" sender:[self.objectId objectAtIndex:self.selectedCell.row]];
}
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"profile"]) {
ProfileViewController *userInfo = [segue destinationViewController];
userInfo.userInfo = [NSMutableArray arrayWithArray:sender];
}
}
Using sender for passing this information is not good practice. Instead, I would use a private property in the table view and setting this when you select the row.
In didSelectRowAtIndexPath:
self.currentProfile = [self objectAtIndexPath:indexPath];
[self performSegueWithIdentifier:#"profile" sender:self];
Then, in prepareForSegue:
ProfileViewController *userInfo = [segue destinationViewController];
userInfo.user = self.currentProfile; // Or, if you want to pass user details as array, create array here
This question already has answers here:
Passing data between view controllers
(45 answers)
Closed 9 years ago.
I have the code below : where Cell new is Custom cell which has array which has object at index when user selects a row which has to be transfered to anothe uiviewcontroller to display that msg But I am unable to do that.
by doing this : I get an error
Incompatible pointer types assigning to 'NSString *' from 'UILabel *'
VC2.DisplayMsg.text = cell.textLabel;
displayMsg is a label in uiviewcontroller where the text has to be displayed.Where Am I going wrong?
Please help me out or suggest any other way to transfer value from navigational uitableviwController to another viewcontroller on selecting the row and displaying the message in that uiviewController.Please help me out.I appreciate a great deal.
Thanks in Advance.
Complete code:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
Cellnew *cell = [array objectAtIndex:indexPath.row];
ViewControllerDisplayMsg *VC2 = [[ViewControllerDisplayMsg alloc] init];
VC2.DisplayMsgtext = cell.textLabel.text;
[self performSegueWithIdentifier:#"displayMsgSegueIdentifier" sender:self];
}
The error :
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFString textLabel]: unrecognized selector sent to instance
You should define a NSString property in other viewController and first assign the value from your table to this string and finally in your viewController's viewDidLoad method you can assign this string to the label text. It is good idea to define your Other Controller as a property to your FirstController.
You should keep the graphical elements updated within the class because this corresponding class or controller is responsible to show the graphical elements & values.
YourTableViewController.h
#class SecondViewController;
#property(strong,nonatomic)SecondViewController secondVC;
YourTableViewController.m
self.secondVC=[SecondViewContrlller alloc]initwithNibName:#"SecondViewController" bundle:nil];
self.secondVC.stringValue= cell.textLabel.text;
YourOtherViewController.h
#property(strong,nonatomic)NSString *stringValue;
YourOtherViewController.m
-(void)viewDidLoad{
self.displayMsg.text=self.stringValue;
[super viewDidLoad];
}
Take a NSString property in your UIViewController, say DisplayMsg:
then in didSelectRowAtIndexPath method:
VC2.DisplayMsg=cell.textLabel.text;
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Make sure your segue name in storyboard is the same as this line
if ([[segue identifier] isEqualToString:#"YOUR_SEGUE_NAME_HERE"])
{
// Get reference to the destination view controller
YourViewController *vc = [segue destinationViewController];
// Pass any objects to the view controller here, like...
[vc setMyObjectHere:object];
}
}
This code will help you