将 NSManagedObject 属性的字符串值传递给新的视图控制器
Passing String Value of a NSManagedObject attribute to a new view controller
我有一个 tableView
填充了来自 NSFetchedResultsController
的 NSString
个值。我将单元格配置为 check/uncheck 个单元格。效果很好。
我正在尝试配置单元格,因此单击单元格中的一个标签会触发到另一个视图控制器的转场。我配置了标签,并在我想进行 segue 的地方添加了一条日志语句,一切正常。当我添加 segue 时,没有编译器错误,但它在运行时崩溃并出现以下错误:
2015-05-31 08:09:04.656 MyApp[17682:1240919] -[UIViewController selectedItemPhoto:]: unrecognized selector sent to instance 0x7fa42b65d4e0
2015-05-31 08:09:04.694 MyApp[17682:1240919] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIViewController selectedItemPhoto:]: unrecognized selector sent to instance 0x7fa42b65d4e0'
我相当确定我正在做一些非常愚蠢的事情,但我不知道是什么。我欢迎提出建议。
MyCustomCell.h:
@property (strong, nonatomic) IBOutlet UILabel *itemDescription;
@property (strong, nonatomic) IBOutlet UILabel *itemGroup;
@property (strong, nonatomic) IBOutlet UIImageView *itemImage;
FirstVC.m 方法:
cellForRowAtIndexPath
方法
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// implement custom cell
MyCustomCell *customCell = [tableView dequeueReusableCellWithIdentifier:@"customCell" forIndexPath:indexPath];
// Get a hold of myManagedObject from FRC
MyNSManagedObject *myObject = [self.fetchedResultsController objectAtIndexPath:indexPath];
// Configures 1st label to look like a hyperlink
customCell.itemDescription.text = myObject.itemDescription;
customCell.itemDescription.textColor = [UIColor blueColor];
customCell.itemDescription.userInteractionEnabled = YES;
// Enables gesture and sets demoObject to pass along via the segue called from labelTap
UITapGestureRecognizer *labelTapGesture = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(labelTap)];
[customCell.itemDescription addGestureRecognizer:labelTapGesture];
self.demoObject = myObject;
// Configures 2nd label within customCell
customCell.itemGroup.text = myObject.itemGroup;
// add image to cell, already imported into Images.xcassets
NSString *imageName = [NSString stringWithFormat:@"%@-1.jpg", myObject.photo];
customCell.imageView.image = [UIImage imageNamed:imageName];
// The following code ensures random checkmarks don't appear when the user scrolls.
if ([self.selectedObjects containsObject:[self.fetchedResultsController objectAtIndexPath:indexPath]]) {
customCell.accessoryType = UITableViewCellAccessoryCheckmark;
} else {
customCell.accessoryType = UITableViewCellAccessoryNone;
}
return customCell;
}
didSelectRowAtIndexPath
方法
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
self.selectedObject = [self.fetchedResultsController objectAtIndexPath:indexPath];
// Set the checkmark accessory for the selected row.
if ([tableView cellForRowAtIndexPath:indexPath].accessoryType == UITableViewCellAccessoryNone) {
[[tableView cellForRowAtIndexPath:indexPath] setAccessoryType:UITableViewCellAccessoryCheckmark];
[self.selectedObjects addObject:self.selectedObject];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
} else {
[[tableView cellForRowAtIndexPath:indexPath] setAccessoryType:UITableViewCellAccessoryNone];
[self.selectedObjects removeObject:self.selectedObject];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
// Enables save button if there are items in the selectedObjects array
if (self.selectedObjects.count > 0) {
[self.saveButton setEnabled:YES];
} else {
[self.saveButton setEnabled:NO];
}
}
labelTap
方法
- (void) labelTap {
// The "hyperlink" effect I'm trying to achieve works without the segue
NSLog(@"itemDescription tapped");
[self performSegueWithIdentifier:@"mySegue" sender:nil];
}
prepareForSegue
方法
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:@"mySegue"] && self.demoObject != nil) {
// This line returns a value...
NSLog(@"self.demoObject = %@", self.demoObject.itemDescription);
// ...but it crashes here when it tries to set on the destinationViewController
SecondViewController *destinationViewController = [segue destinationViewController];
destinationViewController.selectedItemPhoto = self.demoObject.photo;
destinationViewController.selectedItemTitle = self.demoObject.itemDescription;
}
}
SecondViewController.h 属性
// The photo is a string that references a filename in my app
@property (nonatomic, strong) NSString *selectedItemPhoto;
@property (nonatomic, strong) NSString *selectedItemTitle;
从错误来看,您似乎没有设置第二个视图控制器的 class。好像是 UIViewController
应该是 SecondViewController
.
在您的故事板中 select 第二个视图控制器并将其 class 设置为 SecondViewController
。
另一个建议是,在 Objective C 中,您应该在转换对象之前使用内省。所以在你的代码中我会添加:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:@"mySegue"] && self.demoObject != nil) {
// This line returns a value...
NSLog(@"self.demoObject = %@", self.demoObject.itemDescription);
// ...but it crashes here when it tries to set on the destinationViewController
if ([[segue destinationViewController] isKindOfClass:[SecondViewController class]]) {
SecondViewController *destinationViewController = (SecondViewController *)[segue destinationViewController];
destinationViewController.selectedItemPhoto = self.demoObject.photo;
destinationViewController.selectedItemTitle = self.demoObject.itemDescription;
}
}
}
这样就不会发生 segue 但应用不会崩溃。
我想通了!我遇到了三个问题(两个并列在一起):
问题 1: Juan Catalan 指出我没有为 SecondViewController
设置故事板
问题2: Yuchen & luk2302 提出了我如何执行segue 的问题。
问题三:我不需要prepareForSegue
这是我所做的:
1: 我删除了 prepareForSegue
.
2: 我删除了故事板转场。
2: 我修改了 labelTap
方法,为 labelTapGesture
添加了一个参数
- (void) labelTap:(UITapGestureRecognizer *)sender {
NSLog(@"stretchDescription tapped");
CGPoint location = [sender locationInView:self.view];
if (CGRectContainsPoint([self.view convertRect:self.tableView.frame fromView:self.tableView.superview], location)) {
CGPoint locationInTableview = [self.tableView convertPoint:location fromCoordinateSpace:self.view];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:locationInTableview];
if (indexPath) {
self.demoObject = [self.fetchedResultsController objectAtIndexPath:indexPath];
DisplayStretchViewController *destinationViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"SecondVC"];
// Set properties on destinationVC
destinationViewController.itemPhoto = self.demoObject.photo;
destinationViewController.itemTitle = self.demoObject.stretchDescription;
[self.navigationController pushViewController:destinationViewController animated:YES];
}
}
}
我还发现这个 post 非常有用:
UILabel with Gesture Recognizer inside UITableViewCell blocks didSelectRowAtIndexPath
感谢大家的参与!
我有一个 tableView
填充了来自 NSFetchedResultsController
的 NSString
个值。我将单元格配置为 check/uncheck 个单元格。效果很好。
我正在尝试配置单元格,因此单击单元格中的一个标签会触发到另一个视图控制器的转场。我配置了标签,并在我想进行 segue 的地方添加了一条日志语句,一切正常。当我添加 segue 时,没有编译器错误,但它在运行时崩溃并出现以下错误:
2015-05-31 08:09:04.656 MyApp[17682:1240919] -[UIViewController selectedItemPhoto:]: unrecognized selector sent to instance 0x7fa42b65d4e0
2015-05-31 08:09:04.694 MyApp[17682:1240919] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIViewController selectedItemPhoto:]: unrecognized selector sent to instance 0x7fa42b65d4e0'
我相当确定我正在做一些非常愚蠢的事情,但我不知道是什么。我欢迎提出建议。
MyCustomCell.h:
@property (strong, nonatomic) IBOutlet UILabel *itemDescription;
@property (strong, nonatomic) IBOutlet UILabel *itemGroup;
@property (strong, nonatomic) IBOutlet UIImageView *itemImage;
FirstVC.m 方法:
cellForRowAtIndexPath
方法
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// implement custom cell
MyCustomCell *customCell = [tableView dequeueReusableCellWithIdentifier:@"customCell" forIndexPath:indexPath];
// Get a hold of myManagedObject from FRC
MyNSManagedObject *myObject = [self.fetchedResultsController objectAtIndexPath:indexPath];
// Configures 1st label to look like a hyperlink
customCell.itemDescription.text = myObject.itemDescription;
customCell.itemDescription.textColor = [UIColor blueColor];
customCell.itemDescription.userInteractionEnabled = YES;
// Enables gesture and sets demoObject to pass along via the segue called from labelTap
UITapGestureRecognizer *labelTapGesture = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(labelTap)];
[customCell.itemDescription addGestureRecognizer:labelTapGesture];
self.demoObject = myObject;
// Configures 2nd label within customCell
customCell.itemGroup.text = myObject.itemGroup;
// add image to cell, already imported into Images.xcassets
NSString *imageName = [NSString stringWithFormat:@"%@-1.jpg", myObject.photo];
customCell.imageView.image = [UIImage imageNamed:imageName];
// The following code ensures random checkmarks don't appear when the user scrolls.
if ([self.selectedObjects containsObject:[self.fetchedResultsController objectAtIndexPath:indexPath]]) {
customCell.accessoryType = UITableViewCellAccessoryCheckmark;
} else {
customCell.accessoryType = UITableViewCellAccessoryNone;
}
return customCell;
}
didSelectRowAtIndexPath
方法
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
self.selectedObject = [self.fetchedResultsController objectAtIndexPath:indexPath];
// Set the checkmark accessory for the selected row.
if ([tableView cellForRowAtIndexPath:indexPath].accessoryType == UITableViewCellAccessoryNone) {
[[tableView cellForRowAtIndexPath:indexPath] setAccessoryType:UITableViewCellAccessoryCheckmark];
[self.selectedObjects addObject:self.selectedObject];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
} else {
[[tableView cellForRowAtIndexPath:indexPath] setAccessoryType:UITableViewCellAccessoryNone];
[self.selectedObjects removeObject:self.selectedObject];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
// Enables save button if there are items in the selectedObjects array
if (self.selectedObjects.count > 0) {
[self.saveButton setEnabled:YES];
} else {
[self.saveButton setEnabled:NO];
}
}
labelTap
方法
- (void) labelTap {
// The "hyperlink" effect I'm trying to achieve works without the segue
NSLog(@"itemDescription tapped");
[self performSegueWithIdentifier:@"mySegue" sender:nil];
}
prepareForSegue
方法
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:@"mySegue"] && self.demoObject != nil) {
// This line returns a value...
NSLog(@"self.demoObject = %@", self.demoObject.itemDescription);
// ...but it crashes here when it tries to set on the destinationViewController
SecondViewController *destinationViewController = [segue destinationViewController];
destinationViewController.selectedItemPhoto = self.demoObject.photo;
destinationViewController.selectedItemTitle = self.demoObject.itemDescription;
}
}
SecondViewController.h 属性
// The photo is a string that references a filename in my app
@property (nonatomic, strong) NSString *selectedItemPhoto;
@property (nonatomic, strong) NSString *selectedItemTitle;
从错误来看,您似乎没有设置第二个视图控制器的 class。好像是 UIViewController
应该是 SecondViewController
.
在您的故事板中 select 第二个视图控制器并将其 class 设置为 SecondViewController
。
另一个建议是,在 Objective C 中,您应该在转换对象之前使用内省。所以在你的代码中我会添加:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:@"mySegue"] && self.demoObject != nil) {
// This line returns a value...
NSLog(@"self.demoObject = %@", self.demoObject.itemDescription);
// ...but it crashes here when it tries to set on the destinationViewController
if ([[segue destinationViewController] isKindOfClass:[SecondViewController class]]) {
SecondViewController *destinationViewController = (SecondViewController *)[segue destinationViewController];
destinationViewController.selectedItemPhoto = self.demoObject.photo;
destinationViewController.selectedItemTitle = self.demoObject.itemDescription;
}
}
}
这样就不会发生 segue 但应用不会崩溃。
我想通了!我遇到了三个问题(两个并列在一起):
问题 1: Juan Catalan 指出我没有为 SecondViewController
问题2: Yuchen & luk2302 提出了我如何执行segue 的问题。
问题三:我不需要prepareForSegue
这是我所做的:
1: 我删除了 prepareForSegue
.
2: 我删除了故事板转场。
2: 我修改了 labelTap
方法,为 labelTapGesture
- (void) labelTap:(UITapGestureRecognizer *)sender {
NSLog(@"stretchDescription tapped");
CGPoint location = [sender locationInView:self.view];
if (CGRectContainsPoint([self.view convertRect:self.tableView.frame fromView:self.tableView.superview], location)) {
CGPoint locationInTableview = [self.tableView convertPoint:location fromCoordinateSpace:self.view];
NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:locationInTableview];
if (indexPath) {
self.demoObject = [self.fetchedResultsController objectAtIndexPath:indexPath];
DisplayStretchViewController *destinationViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"SecondVC"];
// Set properties on destinationVC
destinationViewController.itemPhoto = self.demoObject.photo;
destinationViewController.itemTitle = self.demoObject.stretchDescription;
[self.navigationController pushViewController:destinationViewController animated:YES];
}
}
}
我还发现这个 post 非常有用: UILabel with Gesture Recognizer inside UITableViewCell blocks didSelectRowAtIndexPath
感谢大家的参与!