繁体   English   中英

配置tableview单元格以将获取的对象传递给另一个视图(NSFetchedResultsController)

[英]Configure tableview cell to pass fetched object to another view (NSFetchedResultsController)

编辑:发布大量更新以支持Mike A.的NSFetchedResultsController方法,请查看以前的NSFetchRequest实现的编辑历史记录。

我有一个带有多个ViewControllers的简单调查应用程序-

StartViewController
InfoViewController
Q1ViewController
...
Q4ViewController
EndViewController
ResultsViewController
DetailsViewController

我的managedObject是在InfoViewController上创建的:

// Identify the app delegate
MMUAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];

// Use appDelegate object to identify managed object context
NSManagedObjectContext *context = [appDelegate managedObjectContext];

// Create new managed object using the MMU entity description
NSManagedObject *ManagedObjectMMU;
ManagedObjectMMU = [NSEntityDescription insertNewObjectForEntityForName:@"MMU" inManagedObjectContext:context];

// Declare managed object
self.ManagedObjectMMU = ManagedObjectMMU;

每个视图都有按钮和文本字段以及一个navController 当选择一个按钮或输入文本时,点击导航栏上的“下一个”按钮,每个值都会保存在我的managedObject如下所示:

- (IBAction)nextBtnPressed:(UIButton *)sender {
// error checks etc before
    [self.ManagedObjectMMU setValue:timeStamp forKeyPath:@"timeStamp"];
    [self.ManagedObjectMMU setValue:timeStamp forKeyPath:@"name"];
    [self.ManagedObjectMMU setValue:timeStamp forKeyPath:@"doB"];
// next viewcontroller pushed here
}

ManagedObjectMMU ,直到它达到获得通过每个视图通过ENDViewController它保存到managedObjectContext

// Pass managed object to next ViewController
Q1.ManagedObjectMMU = self.ManagedObjectMMU;

保存所有结果:

// Save managed object to managedObjectContext
NSError *error;
[[self.ManagedObjectMMU managedObjectContext] save:&error];

我的模型非常基础,所有字符串类型都有10个属性。

资料模型

这是完整提交的示例:

data: {
    dateOfBirth = "Sep 5, 1989";
    gender = Male;
    name = Ross;
    q1 = "Computing, Mathematics & Digital Technology";
    q2 = Yes;
    q3 = Football;
    q4 = "Commute From Home";
    q5 = Bicycle;
    status = University;
    timeStamp = "3/26/14, 2:56 PM";
}

ResultsViewController是所有结果的UITableView ,每个cell.textLabel.text包含每个提交的name ,而cell.detailLabel.text包含timeStamp 我正在使用NSFetchedResultsController从我的模型中获取结果(请参阅Mike A.的回答,我已经实现了他的方法)。

ResultsViewController

我想发生的是,当用户点击一个单元格时,具有特定“名称”的获取结果对象将传递到下一个视图,显示与该对象关联的数据(dataOfBirth,gender,q1等) )。

我的问题是:如何将已经获取的对象传递到下一个视图,以显示该特定名称的所有对象? 我可以在另一个UITableView上显示这些指定的对象,还是应该创建一些UITextFieldsLabels来显示结果? 我应该在tableView:didSelectRowAtIndexPath:方法中传递获取的对象,还是应该实现prepareForSegue 抱歉,如果这是一个简单的解决方案,我已经在线搜索了好几天,却找不到合适的解决方案! 谢谢。

更新:

感谢Mike A的建议和代码片段,我使用以下代码实现了该解决方案:

- (UITableViewCell *)tableView:(UITableView *)tableView
         cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier];
    }

    // Configure the cell...
    [self configureCell:cell atIndexPath:indexPath];

    return cell;
}

- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {
    MMU *results = [self.fetchedResultsController objectAtIndexPath:indexPath];
    cell.textLabel.text = results.name;
    cell.detailTextLabel.text = results.timeStamp;

}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{

    DetailViewController *detailView = [[DetailViewController alloc]initWithNibName:@"DetailViewController" bundle:nil];

    // Pass fetched object to next ViewController
    detailView.ManagedObjectMMU = [self.fetchedResultsController objectAtIndexPath:indexPath];

    // Push the view controller.
    [self.navigationController pushViewController:detailView animated:YES];
}

而且DetailView仅仅具有一些文本字段和标签,以显示从单元格传递的对象的问题和适当的提交:

- (void)displayDetails {
    self.nameDetail.text = [_ManagedObjectMMU valueForKey:@"name"];
    self.genderDetail.text = [_ManagedObjectMMU valueForKey:@"gender"];
    self.dateOfBirthDetail.text = [_ManagedObjectMMU valueForKey:@"dateOfBirth"];
    self.statusDetail.text = [_ManagedObjectMMU valueForKey:@"status"];
    self.timeStampDetail.text = [_ManagedObjectMMU valueForKey:@"timeStamp"];

    self.q1Answer.text = [_ManagedObjectMMU valueForKey:@"q1"];
    self.q2Answer.text = [_ManagedObjectMMU valueForKey:@"q2"];
    self.q3Answer.text = [_ManagedObjectMMU valueForKey:@"q3"];
    self.q4Answer.text = [_ManagedObjectMMU valueForKey:@"q4"];
    self.q5Answer.text = [_ManagedObjectMMU valueForKey:@"q5"];
}

如果没有Mike A,我就做不到,如果您想了解解决方案,请仔细阅读他的回答和下面的评论!

我建议在每个视图控制器中使用NSFetchedResultsController 这样,您不必在每个视图控制器中都处理数组,只需要获取请求即可。 我不建议您在App Delegate中创建它们。 最好在每个视图控制器中或在一个类别中。

因此,请在您的视图控制器中尝试为NSFetchedResultsController创建一个属性并实现其getter。

NSFetchedResultsController示例

@property (nonatomic, strong) NSFetchedResultsController *fetchedResultsController;


- (NSFetchedResultsController *)fetchedResultsController
{
    if (!_fetchedResultsController) {

        _fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:[self fetchRequest]
                                                                        managedObjectContext<# your managedObjectContext #>
                                                                          sectionNameKeyPath:nil
                                                                                   cacheName:nil];

        self.fetchedResultsController.delegate = self;

        NSError *error = nil;
        if (![self.fetchedResultsController performFetch:&error]) {
            NSLog(@"Error: %@ %@", error.localizedDescription, error.userInfo);
        }
    }

    return _fetchedResultsController;
}

并为您的提取请求实现方法:

- (NSFetchRequest *)fetchRequest
{
    NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"MMU"];

    // predicates, sort descriptors and other options go here...

    return fetchRequest
}

然后,您可以使用来更新tableview数据源

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    // Return the number of rows in the section.
    return self.fetchedResultsController.fetchedObjects.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier];
    }

    MMU *results = [self.fetchedResultsController objectAtIndexPath:indexPath];
    cell.textLabel.text = [NSString stringWithFormat:@"%@ ",results.name]; // Consider results.name without stringWithFormat.
    cell.detailTextLabel.text = [NSString stringWithFormat:@"%@ ", results.timeStamp];

    return cell;
}

现在,像这样设置视图控制器之后,当您在文本上触摸或放置文本时,就可以更新模型。 在下一个视图控制器中,您可以设置一个新的获取结果控制器和一个新的获取请求,以请求已更改的数据。

根据您拥有的视图控制器的数量,更好的方法是将UITableViewController子类化,以默认情况下实现获取的结果控制器,并每次更改获取请求。

如果这样做没有帮助,请提供更多有关如何显示新视图控制器以及如何更新模型的信息。

更新

您可以通过实现prepareForSegue:tableView:didSelectRowAtIndexPath:来将每个对象从视图控制器传递到视图控制器。 在这种情况下,您将必须在头文件中为要将对象传递到的每个视图控制器声明一个公共属性。 请注意,实现这些方法将通过点按单元格而不是您在示例中提供的IBAction来导航到下一个视图控制器。

如果您使用segues推送视图控制器,则可以使用以下示例。

prepareForSegue:示例

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 
{
   [super prepareForSegue:segue sender:sender];

   UIViewController *nextViewController = segue.destinationViewController;
   nextViewController.mmuModel = self.mmuModel; // The initial model that you have from InfoViewController.
}

该方法将与下一个视图控制器共享您的mmuModel。 但是,您将需要分别在每个视图控制器中更新模型。

这样就可以完成工作,但是CoreData不能以这种方式使用。 CoreData是一个功能强大的框架,通常可以为您做很多事情。 另一种方法是像在InfoViewController一样创建一个新的NSManagedObject ,然后不必像我向您展示的那样每次使用NSFetchedResultsController来将其传递到问题视图控制器中。 只有这一次,您才需要找出一种过滤结果的方法,以便获得所需的对象。 有多种方法可以执行此操作,一种方法是使用某种id或谓词。

此外,在数据模型中,不要将所有内容都放在一个实体(MMU)中,而是要考虑分离某些事物并使用关系。

同样,对于您的属性,使用不同的数据类型也非常有用,例如,timeStamp应该是日期,如果唯一的选择是男性,女性等,则性别可以是BOOL。

我希望这能有所帮助。 如果您仍有问题,请告诉我。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM