将 NSManagedObject 属性的字符串值传递给新的视图控制器

Passing String Value of a NSManagedObject attribute to a new view controller

我有一个 tableView 填充了来自 NSFetchedResultsControllerNSString 个值。我将单元格配置为 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

感谢大家的参与!