I am trying to pass a data through a segue under prepareForSegue function but i keep getting exc_bad_access.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
//NSIndexPath *indexPath = [NSIndexPath indexPathForRow:rowIndex inSection:0];
// Make sure your segue name in storyboard is the same as this line
if ([[segue identifier] isEqualToString:#"itemListSegue"])
{
itemList *vc = [segue destinationViewController];
vc.inv = [inv_list objectAtIndex:indexPath.row];
vc.title = vc.inv;
}
}
bellow is the error i got
EDIT:
inv_list is declared as followed:
#interface downloadInv (){
NSMutableArray *inv_list;
}
and in viewDidLoad:
inv_list = [[NSMutableArray alloc] init];
Content:
vc.inv is a particular element in inv_list that I want to pass to the destination view controller when a table is selected.
it was declared as followed:
#interface itemList : UITableViewController
#property(nonatomic, strong) NSString *inv;
#end
Anyone know how to fix this?
Thanks in advance.
Because in_list is not declared as a strong property, it is probably being released.
Try declaring it like this:
#property (strong, nonatomic) NSMutableArray * inv_list;
Could you please check your segue identifier, If that's not given, may cause the exception
otherwise if it's made as strong property like:
#property(nonatomic,strong) NSString *inv_list;
It may solve the problem.
Related
In tableViewControllerA.h I declare a delegate ,and in tableViewControllerA.m I implement the method when click a cell of the tableView, A will pass the value to B, and execute the perfromSegueWithIdentifier to jump to tableViewControllB,in tableViewControllB.m the getting method is called, and I get the value, but after the viewDidLoad() method call, the value become nil. Please help me to solve the problem.By the way , the property of the value is strong,nonatomic.
DTZHomeTableViewController.h
#import <UIKit/UIKit.h>
#import "PassData.h"
#protocol PassDataDelegate
-(void)passData:(PassData*) dataToProgram;
#end
#interface DTZHomeTableViewController :
UITableViewController<UITableViewDelegate,UITableViewDataSource>
#property(assign,nonatomic) id<PassDataDelegate> dataDelegate;
#end
PassData is an user-defined class
DTZHomeTableViewController.m
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
ProgramTableViewController *programViewController=
[[ProgramTableViewController alloc]init];
self.dataDelegate=programViewController;;
PassData *jump=[[PassData alloc]init];
jump.livingStatus=YES;
jump.role=0;
jump.index=indexPath.row;
jump.curOnlineNum=305605;
[self.dataDelegate passData:jump];
[self performSegueWithIdentifier:#"showSelectedProgram" sender:self];
}
ProgramTableViewController.h
#import <UIKit/UIKit.h>
#import "DTZHomeTableViewController.h"
#interface ProgramTableViewController :
UITableViewController<PassDataDelegate,UITableViewDataSource,UITableViewDelegate>
#property(strong,nonatomic) PassData * dataFromHome;
#end
ProgramTableViewController.m
#implementation ProgramTableViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(#"view did load%#",self.dataFromHome); // log :null
}
- (void) passData:(PassData *)dataToProgram
{
self.dataFromHome=dataToProgram;
}
#end
Delegation isn't the proper way to pass data to a segued view controller. Instead, you want to pass the data in prepareForSegue:sender:
Remove the protocol and delegate.
Add properties to your ProgramTableViewController for the data you want to pass.
#property (nonatomic, assign) BOOL livingStatus;
#property (nonatomic, assign) NSInteger role;
#property (nonatomic, assign) NSInteger row;
#property (nonatomic, assign) NSInteger curOnlineNum;
In prepareForSegue:sender:, set the ProgramTableViewController's passed properties to the values associated with the selected row:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)__unused sender
{
if ([[segue identifier] isEqualToString:#"showDetail"])
{
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
ProgramTableViewController *controller = (ProgramTableViewController *)[segue destinationViewController];
controller.livingStatus = YES;
controller.role = 0;
controller.row = indexPath.row;
controller.curOnlineNum = 305605;
}
}
You shouldn't allocate and init ProgramTableViewController in tableView:didSelectRowAtIndexPath:. Your segue will instantiate the destination view controller for you.
You don't even need to have a tableView:didSelectRowAtIndexPath: method. You can create a push segue from the tableViewCell to ProgramTableViewController, right within Storyboard. Give the segue an identifier (such as "showDetail"). Then in prepareForSegue, you assign the values, as I explained.
When you tap on that row, the segue will create a ProgramTableViewController, set the parameters, and present it for you.
I have a prepareForSegue method setup in that sends everything I want to the destinationViewController except the value for a UILabel on the destinationVC. I threw a NSLog statement in to see what value it prints and it prints what I want.
It doesn't crash, but it doesn't set. I know I'm missing something very basic here, but it's not jumping out at me.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(UIButton *)sender {
if ([[segue identifier] isEqualToString:#"directionsSegue"]) {
// Set destination view controller
DirectionsViewController *destinationVC = segue.destinationViewController;
// Pick out the "thing" you want to send to destinationVC
CGPoint point = [sender convertPoint:CGPointZero toView:self.tableView];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:point];
// Set the "thing" on the destinationVC
PointOfInterest *poi = [self.fetchedResultsController objectAtIndexPath:indexPath];
destinationVC.destinationLabel.text = poi.name;
NSLog(#"destinationVC.destinationLabel.text = %#", poi.name);
destinationVC.destinationLatitude = poi.latitude;
destinationVC.destinationLongitude = poi.longitude;
}
}
My property declared in the header of my destinationVC:
#property (strong, nonatomic) IBOutlet UILabel *destinationLabel;
Solution from answers below:
Mystery solved! Here's what I did:
on my destinationVC, I added this to my header:
#property (nonatomic, strong) NSString *destinationName;
I put this back in the implementation:
#property (strong, nonatomic) IBOutlet UILabel *destinationLabel;
In destinationVC, I added this to my viewDidLoad:
self.destinationLabel.text = self.destinationName;
Your label will be nil in prepareForSegue because it won't be instantiate at this time. In fact, IBOutlet are initialised yet once your view is loaded. That's why it's not working.
The best way to solve your issue is to create another property in your DirectionsViewController where will be stored your text. This one is available directly after your controller initialisation, and then you can set your label directly wherever in your controller.
IBOutlet objects are not initialized until the view controller's view loads. That happens after the segue. Create a custom property and update that during prepare and then copy it to your label during viewDidLoad.
I am trying to pass a custom object to a new view's property though it gives an error because it cannot find the "setter" for the property.
When I select a row in my table this method is called:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
self.actionIndexPath = indexPath;
[self performSegueWithIdentifier:SELECTED_PERSON sender:self];
}
Next:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:CREATE_EDIT_PERSON]) {
PersonDebtViewController *editPerson = [segue destinationViewController];
editPerson.editPerson = self.oweMePeople[self.actionIndexPath.row];
}
else if ([segue.identifier isEqualToString:SELECTED_PERSON]) {
EmailViewController *emailPerson = [segue destinationViewController];
emailPerson.selectedPerson = self.oweMePeople[self.actionIndexPath.row];
}
self.actionIndexPath = nil;
}
It is in the emailPerson.selectedPerson =... it goes wrong.
I have declared the property in the destinationview:
#import <UIKit/UIKit.h>
#import <MessageUI/MessageUI.h>
#import "Person.h"
#interface EmailViewController : UIViewController <MFMailComposeViewControllerDelegate>
#property (nonatomic) Person *selectedPerson;
#end
What am I missing?
You probably forgot to set your view controller to a EmailViewController in Storyboard. Your error is telling you:
[UIViewController setSelectedPerson:]
Trying to send the message setSelectedPerson: to an instance of UIViewController
Xcode failing to recognize #property in detail controller.
.m file of ViewController2:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"showDetail"])
{
NSIndexPath *selectedIndexPath = [[self.collectionView indexPathsForSelectedItems] objectAtIndex:0];
// load the image.
NSString *imageNameToLoad = [NSString stringWithFormat:#"%d", selectedIndexPath.row];
NSString *pathToImage = [[NSBundle mainBundle] pathForResource:imageNameToLoad ofType:#"JPG"];
UIImage *image2 = [[UIImage alloc] initWithContentsOfFile:pathToImage];
Detail_ViewController_Biffy *detailViewController = [segue destinationViewController];
Detail_ViewController_Biffy.**image = image;** <--- fails [property 'image'not found on object of type 'detail_ViewController_Biffy'
}
}
.h file of detail_view
#import "ViewController.h"
#interface ViewController_Biffy : ViewController
#property (strong, nonatomic) IBOutlet UIImageView *image;
#end
Tried to change the import ViewController.h to ViewController_Biffy.h but causes more errors.
If you need further info, let me know.
You are trying to get a property from a class rather than the instance. Try
Detail_ViewController_Biffy *detailViewController = [segue destinationViewController];
detailViewController.image = image
Also the type you have says detail_ViewController2 which is not anywhere in your code
First: image is a property not a class method so you would need to access it:
detailViewController.image =
Secondly image in your prepareForSegue:sender: does not exist. I am guessing you are trying to set your property to image2 which you create a couple lines up. In that case the failing line of code would look like:
detailViewController.image = image2;
All properties are accessed through instances of classes. Although you may not know it, you are already creating a detailViewController instance on your line:
Detail_ViewController_Biffy *detailViewController = [segue destinationViewController];
I am using the following to create a reference to a view controller in my code like this:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if([segue.identifier isEqualToString:#"detailSegue"]){
NSIndexPath *indexPath=[self.tableView indexPathForSelectedRow];
TRDetailViewController *vc=segue.destinationViewController;
vc.item=self.items[indexPath.row];
[vc setValue:self forKeyPath:#"delegate"];
[vc setValue:indexPath.row forKeyPath:#"itemIndex"];
}
}
and this is declared as in TRDetailViewController
#interface TRDetailViewController : UIViewController
#property (weak, nonatomic) IBOutlet UILabel *detailLabel;
#property NSString *item;
#property (nonatomic, weak)id delegate;
#property NSInteger itemIndex;
- (IBAction)deleteItem:(id)sender;
#end
but I get the following error
and I'm not sure why. I am trying to pass the location in an index of the cell selected in a UITableView. If a better way, please let me know. Why am I getting this error?
thx
setValue:forKey: is expecting an object for its value argument and you are passing it a primitive (in this case, an integer). You can work around this by amending your method to read as follows:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if([segue.identifier isEqualToString:#"detailSegue"]){
NSIndexPath *indexPath=[self.tableView indexPathForSelectedRow];
TRDetailViewController *vc=segue.destinationViewController;
vc.item=self.items[indexPath.row];
[vc setValue:self forKeyPath:#"delegate"];
[vc setValue:[NSNumber numberWithInt:indexPath.row] forKeyPath:#"itemIndex"];
}
}
And then access it like:
[[vc valueForKey:#"itemIndex"] intValue];
setValue:forKeyPath: requires an object (i.e. id) as first argument.
You are instead passing a NSInteger.
You will have to use an object type, which means to turn your itemIndex into a NSNumber.
Then you can store it using
[vc setValue:#(indexPath.row) forKeyPath:#"itemIndex"];
and retrieve it by
NSInteger myIndex = [vc valueForKey:#"itemIndex"].integerValue;