重新加载包含UIPageViewController的DetailViewController

时间:2014-03-13 00:37:25

标签: ios uitableview uipageviewcontroller viewdidload

我基本上有一个使用RestKit从远程服务器提取数据的Master-Detail应用程序。

DetailViewController充当具有三个viewControllers的PageViewController的数据源。我的问题只涉及其中两个,所以我将重点关注这一点。我会称这两个重要的viewControllersFirstViewControllerSecondViewController

FirstViewController显示在主视图中选择的项目的详细内容,基本上是图像和一些文本。滚动到SecondViewController会显示UITableView,其中包含与主视图中内容相关的项目。请参阅此链接How to implement UIPageViewController that utilizes multiple ViewControllers,查看与该应用类似的故事板的图片。

为了更清楚地说明一个食谱应用程序,您可以在其中选择要在主场景中查看的食谱。细节场景显示所选的配方。滚动到下一页显示的表格中包含与所选配方相关的配方。

这里建立的背景是我的问题:

我正在尝试进行设置,以便用户可以在tableview中选择一个单元格,DetailViewController将使用所选单元格中的数据重新加载。例如,用户看到他们感兴趣的相关配方,选择单元格,并使用所选单元格中的数据将视图重新加载到PageViewController中的主页面。

我觉得最简单的方法就是将一些必需的变量传递给DetailViewController并像这样调用viewDidLoad

-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    //Grab index object at index path
    NSManagedObject *object = [[self fetchedResultsController] objectAtIndexPath:indexPath];
    //Initialize DVC class to utilize variables and methods
    DetailViewController *vc = detailViewControllerId;
    vc.articleId = [object valueForKey:@"articleId"];
    vc.imageUrl = [object valueForKey:@"image"];
    //Reload the DetailViewController
    [vc viewDidLoad];
}

这有一个例外:

  1. 所有可变数据都是从初始加载中维护的,因此当主屏幕弹回时,我拥有所有以前的数据和新数据。
  2. 致电viewDidLoad做了我所希望的事。 viewDidLoad启动一系列API调用以从服务器获取数据,然后填充viewControllers的内容PageViewController。但是,我需要从头开始重新加载过去数据的东西。

    有没有人有更好的建议来完成我想做的事情?感谢

    ========== EDIT ===============

    以下是可能需要的更多信息。

    从头开始,用户选择MasterViewController中的一个单元格,该单元格触发DetailViewController的segue。我正在使用prepareForSegue将所需数据传递到DetailViewController

    DetailViewController充当PageViewController的数据源,因此在viewDidLoad中调用DetailViewController时会调用一系列方法来填充所需的数据源元素PageViewController。这是基础知识。

    DetailViewController.h

    @interface DetailViewController : UIViewController<UINavigationControllerDelegate, UIPageViewControllerDataSource>
    

    {

    }

    @property (strong, nonatomic) UIPageViewController *pageViewController;
    @property (strong, nonatomic) NSURL *imageUrl;
    @property (strong, nonatomic) NSData *passingPhotoData;  //used to pass to the  pageViewController;
    @property (strong, nonatomic) NSAttributedString *passingString; //passes text to pageViewController;
    @property (strong, nonatomic) NSArray *vc1;
    @property (strong, nonatomic) NSManagedObjectContext *managedObjectContext;
    @property (strong, nonatomic) NSString *articleId;
    
    @end
    

    DetailViewController.m

    -(void)viewDidLoad
    {
        //There is other things in the method but these are the only significant line for the question.
        //The method call below is to start a call to the server to get the information needed about the cell that was selected.
        vc1 = [[NSArray alloc] init];
        [self getDetailInfoFromServer]
    }
    
    -(void)getDetailInfoFromServer
    {
        //Here I make a call to the server using Restkit… it is not significant for the question so I'll leave it out.
        //The data that is retrieved from this server call is everything that I will use to populate the FirstViewController which is again an image and some text.
        //If the call to the server was successful RestKit maps out the data in Core Data and I move on to the next method.
        [self getInfoRelatedToDetailView]
    }
    
    -(void)getInfoRelatedToDetailView
    {
        //The data that is retrieved from this server call is everything that I will use to populate the SecondViewController.
        //The SecondViewController is a tableView and the data retrieved will be an array of images and the associated text.
        //If the call to the server was successful Restkit will again map the data into Core Data entities and I move on to the next method.
        [self getTextForFVC]
    }
    
    -(void)getTextForFVC
    {
        //In this method I fetch the text from Core Data that was received back in getDetailInfoFromServer.
        //It is all HTML which I parse to a string using DTCoreText and finally set passingString equal to the result.  
        //passingString is one of the variables I use to pass needed info to the FirstViewController.
        self.passingString = parsedString
    
        //At this point I start the setup of the pageViewController, this is just standard stuff that goes with a PageViewController
    
        FirstViewController *selectedController = [self populateFirstViewController];
        vc1 = @[selectedController];
    
        // Create page view controller
        self.pageViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"PageViewController"];
        self.pageViewController.dataSource = self;
        [self.pageViewController setViewControllers:vc1  direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil];
    
        //Notice above the call to a method populateFirstViewController That is where I go next.
    
    -(FirstViewController *)populateFirstViewController
    {
        //This is a simple method that gets called whenever the PageViewController delegate methods deem it necessary to load the FirstViewController.
        FirstViewController *fvc = [self.storyboard instantiateViewControllerWithIdentifier:@"FirstController"];
        fvc.imageData = self.passingPhotoData; //This variable was set earlier but I left out the code
        fvc.nodeText = self.passingString;
        return nvc;
    }
    
    -(SecondViewController *)populateSecondViewController
    {
        //This method is like the one above, it is called when the PVC delegate methods deem it necessary to load the page
        SecondViewController *svc =[self.storyboard instantiateViewControllerWithIdentifier:@"SecondController"];
        //Here are some of the variables I pass in
        svc.managedObjectContext = self.managedObjectContext;
        cvc.detailViewControllerId = self;  //This line allows me to call the viewDidLoad method for the DetailViewController from the SecondViewController.
    
        return cvc;
    }
    

    一旦发生这一切,PageViewController将显示从服务器收到的数据。 FirstViewController处理填充UIImageViewUITextField。同样,SecondViewController处理填充UITableView

    现在问题的关键......用户看到他们对表感兴趣的东西并选择它。我使用didSelectRowAtIndexPath获取调用服务器所需的信息,然后需要PageViewController重新加载。鉴于DetailViewControllerPVC的数据源,我需要数据源来刷新/重新加载。我认为只需要调用viewDidLoad来启动流程就很容易,但我不确定这是否合适。什么是最好的方法呢?

    对小说感到抱歉,只是想澄清那些投入其中的人。

1 个答案:

答案 0 :(得分:1)

将数据传递回先前控制器的常用方法是通过委派。您应该在控制器中有一个委托协议,显示相关的配方(在您的示例中),并且初始详细控制器应将自己设置为委托。当用户选择其中一个相关项时,调用委托方法,该方法将传回重新加载详细控制器所需的数据。

现在你的例外,

  1. 您收到该错误是因为您的属性声明错误 - 应该是

    @property(强,非原子)DetailViewController * vc;

  2. 在您的代码中,您应该使用self.vc来引用它,而不是创建一个局部变量(这是您在发布的代码中所做的),其名称与属性相同,

    self.vc = detailViewControllerId;
    

    无论如何,你还不清楚你在使用那条线路做什么,因为你没有说明是什么detailViewControllerId。

    1. 你真的不应该直接调用viewDidLoad。控制器在加载视图时调用它。由于您没有首先说明如何加载细节控制器,因此很难说为什么要获得旧数据和新数据。您应该做的是将用于填充表的数组设置为您在委托方法中发回的值。