【问题标题】:Reloading a DetailViewController that contains a UIPageViewController重新加载包含 UIPageViewController 的 DetailViewController
【发布时间】:2014-03-13 00:37:25
【问题描述】:

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

DetailViewController 充当具有三个视图控制器的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. 所有变量数据都是从初始加载开始维护的,因此当主屏幕弹出时,我拥有所有以前的数据和新数据。

致电viewDidLoad 已达到我的预期。 viewDidLoad 启动一系列 API 调用以从服务器获取数据,然后填充 PageViewController 的内容 viewControllers。但是,我需要一些能够从一开始就重新加载它的东西,从而消除过去的数据。

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

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

这里有一些可能需要的更多信息。

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

DetailViewController 充当PageViewController 的数据源,因此当在DetailViewController 中调用viewDidLoad 时,会调用一系列方法来填充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 来启动该过程会很容易,但我不确定这是不是合适的方式。最好的方法是什么?

对小说感到抱歉,只是想澄清那些提出意见的人。

【问题讨论】:

    标签: ios uitableview uipageviewcontroller viewdidload


    【解决方案1】:

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

    现在是你的例外,

    1. 你得到这个错误是因为你的属性声明是错误的——它应该是,

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

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

    self.vc = detailViewControllerId;
    

    反正你用那条线做什么还不是很清楚,因为你没有说 detailViewControllerId 是什么。

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

    【讨论】:

    • rdelmar,看来我对我的问题中的一些重要点有点含糊。我必须离开我的电脑,直到明天晚上。我将澄清一些观点并添加一些额外的代码。感谢您迄今为止提出的建议。
    • 好的,rdelmar,我已经添加了一些代码和解释。我发誓我尝试了您对 DetailViewController 的属性定义,它给了我一个错误,但现在它可以工作了,所以我一定是打错了。我同意建立一个委托协议来传回数据。我也觉得我能胜任消除新旧数据问题的任务。最后,我尊重你的 38.4k 英雄声望,并谦虚地问,既然你首先看到了我是如何做到这一点的,那么你将如何重新加载场景。
    • @Ben,我有点困惑,在用户在第二个控制器中选择一行后,对服务器的调用会获得重新加载详细控制器所需的信息?无论调用是什么,您都应该在委托方法的实现中调用该方法。
    • 让我确保我们在同一页面上。当您说“详细控制器”时,您是指 PVC 中的 DetailViewController 还是 FirstViewController?假设您的意思是 FVC,那么获取所需数据的调用是 getDetailInfoFromServer。所以我只会在didSelectRowAtIndexPath 方法中调用该方法。我认为这会奏效!
    • 按预期工作,感谢 rdelmar。 Tableview 是完美的,但在 UITextView 的初始加载中我仍然有一些剩余的文本。我可以弄清楚我在哪里保留了这些数据。我一直对使用 viewDidLoad 持怀疑态度,但这似乎很容易。不知道为什么我没有看到你的建议。我的同事会说“新鲜的眼睛”……“知道他们在说什么的眼睛”是我一直在做的。再次感谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-24
    • 1970-01-01
    • 1970-01-01
    • 2015-07-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多