从子视图推送新的视图控制器

Posted

技术标签:

【中文标题】从子视图推送新的视图控制器【英文标题】:Push New View Controller From Subview 【发布时间】:2014-05-05 18:26:10 【问题描述】:

我有一个 UITableViewController 作为我的 UIViewController 的子视图。表格视图是从 RSS 提要填充的,并且工作正常。 I'm trying to push a webviewcontroller onto my main navigation stack when a row in the subview is selected but I'm not sure how to get it to work.我知道如果我单独使用 UITableViewController 而不是子视图,我当前的代码会正常工作。

这是我的代码:

- (void)viewDidLoad

    [super viewDidLoad];
    // Do any additional setup after loading the view from its nib.

    self.title = @"Home";

    GRSNewsViewController *newsView = [[GRSNewsViewController alloc]init];
    [self addChildViewController:newsView];
    [self.view addSubview:newsView.view];

UITableViewController .h:

#import <Foundation/Foundation.h>

@class RSSChannel;
@class WebViewController;

@interface GRSNewsViewController : UITableViewController <NSXMLParserDelegate>

    NSURLConnection *connection;
    NSMutableData *xmlData;
    RSSChannel *channel;


@property (nonatomic, strong)WebViewController *webViewController;

- (void)fetchEntries;


@end

我的 UITableViewController .m:

#import "GRSNewsViewController.h"
#import "RSSChannel.h"
#import "RSSItem.h"
#import "WebViewController.h"
#import "GRSHomeViewController.h"

@interface GRSNewsViewController ()

@end

@implementation GRSNewsViewController
@synthesize webViewController;

- (void)viewDidLoad

    [super viewDidLoad];

    self.tableView = [[UITableView alloc]initWithFrame:CGRectMake(0, 69, 320, 173) style:UITableViewStylePlain];
    self.tableView.backgroundColor = [UIColor clearColor];
    [self.tableView setSeparatorStyle:UITableViewCellSeparatorStyleSingleLine];
    [self.tableView setSeparatorColor:[UIColor whiteColor]];


- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict

    NSLog(@"%@ found a %@ element", self, elementName);
    if ([elementName isEqual:@"channel"])
    
        channel = [[RSSChannel alloc]init];

        [channel setParentParserDelegate:self];

        [parser setDelegate:channel];
    


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

    return [[channel items]count];


- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

    return 50;


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

    UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"UITableViewCell"];
    if (cell == nil)
    
        cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"UITableViewCell"];
        cell.textLabel.font = [UIFont systemFontOfSize:16.0];
    

    RSSItem *item = [[channel items]objectAtIndex:[indexPath row]];

    NSDateFormatter *formatter = [[NSDateFormatter alloc]init];
    [formatter setDateFormat:@"EEE, dd MMM yyyy HH:mm:ssZ"];
    NSDate *pubDate = [formatter dateFromString:[item date]];
    [formatter setDateStyle:NSDateFormatterMediumStyle];
    NSString *dateString = [formatter stringFromDate:pubDate];

    [[cell textLabel]setText:[item title]];
    [[cell detailTextLabel]setText:dateString];

    cell.backgroundColor = [UIColor clearColor];
    cell.textLabel.backgroundColor = [UIColor clearColor];
    cell.textLabel.textColor = [UIColor whiteColor];
    cell.detailTextLabel.backgroundColor = [UIColor clearColor];
    cell.detailTextLabel.textColor = [UIColor whiteColor];

    return cell;


- (void)fetchEntries

    xmlData = [[NSMutableData alloc]init];

    NSURL *url = [NSURL URLWithString:@"http://onmyhonorband.com/rss"];

    NSURLRequest *req = [NSURLRequest requestWithURL:url];

    connection = [[NSURLConnection alloc]initWithRequest:req delegate:self startImmediately:YES];


- (id)initWithStyle:(UITableViewStyle)style

    self = [super initWithStyle:style];

    if (self)
    
        [self fetchEntries];
    

    return self;


- (void)connection:(NSURLConnection *)conn didReceiveData:(NSData *)data

    [xmlData appendData:data];


- (void)connectionDidFinishLoading:(NSURLConnection *)conn
   
    NSXMLParser *parser = [[NSXMLParser alloc]initWithData:xmlData];

    [parser setDelegate:self];

    [parser parse];

    xmlData = nil;

    [[self tableView] reloadData];

    NSLog(@"%@\n %@\n %@\n", channel, [channel title], [channel infoString]);


- (void)connection:(NSURLConnection *)conn didFailWithError:(NSError *)error

    connection = nil;

    xmlData = nil;


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

    [[webViewController webView]loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"about:blank"]]];

    [self.navigationController pushViewController:webViewController animated:YES];

    RSSItem *entry = [[channel items]objectAtIndex:[indexPath row]];

    NSURL *url = [NSURL URLWithString:[entry link]];

    NSURLRequest *req = [NSURLRequest requestWithURL:url];

    [[webViewController webView]loadRequest:req];
    webViewController.hackyURL = url;



- (void)didReceiveMemoryWarning

    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.


@end

【问题讨论】:

你应该检查 self.navigationController 是否为 nil。您可能应该使用 [self.parentViewController.navigationController push...]。 不相关:您将 subview 称为 childViewController..a subview 是一个 view..而且您正在解析 viewController 中的文件..在架构上不正确。 @rdelmar,这是我在控制台中收到的消息:应用程序试图在目标 上推送一个 nil 视图控制器。 你在哪里初始化webViewController 初始化不声明,他问你在哪里初始化它。即你在哪里创建 webViewController?将其声明为属性并不是创建它。你不能使用不创建它的东西,即你需要分配它 【参考方案1】:

正如其他人在 cmets 中指出的那样,并且正如您收到的控制台消息所示,您的主要问题是您从未初始化 webViewController。在表视图控制器的 initWithStyle: 初始化程序中添加如下所示的行。

self.webViewController = [[WebViewController alloc] init];

我发现的其他东西:

viewDidLoad 中分配/初始化一个新的UITableView。您不应该这样做,因为您正在覆盖由UITableViewController 基类在loadView 中创建的UITableView 实例。查看my other answer,了解有关视图和视图控制器生命周期的更多信息。

在父视图控制器中您忘记调用didMoveToParentViewController。您需要在致电addChildViewController 后执行此操作。请阅读UIViewController class reference 中的“实现容器视图控制器”部分了解详细信息。

【讨论】:

【参考方案2】:

如果 UIViewController addSubView 是 UITableViewController 的一个视图,你想推入 tableView:didSelectRowAtIndexPath 的方法,你应该检查 self.navigationController 是否为 nil。如果它是 nil,你可能应该使用

[self.parentViewController.navigationController pushViewController:controller animated:YES];

如果self.parentViewController也是nil,有时候,你必须设置一个@property来指出UITableViewController中的parentViewController,比如:

@property (nonatomic, weak) UIViewController *parentVC;

在 UIViewController 中:

UITableViewController *tableViewVC = [[UITableViewController alloc] init];
tableViewVC.parentVC = self;

在 UITableViewController 中,-tableView:didSelectRowAtIndexPath:

[self.parentVC.navigationController pushViewController:controller animated:YES];

当你执行时:

NSLog(@"‼️‼️‼️‼️‼️self.navigationController is%@,\n 
self.parentViewController.navigationController is %@,\n 
self.parentVC.navigationController is %@",self.navigationController,self.parentViewController.navigationController,self.parentVC.navigationController);

它可以打印为:

‼️‼️‼️‼️‼️self.navigationController is(null),
self.parentViewController.navigationController is (null),
self.parentVC.navigationController is <UINavigationController: 0x7af32ae0>

【讨论】:

以上是关于从子视图推送新的视图控制器的主要内容,如果未能解决你的问题,请参考以下文章

从表视图(子视图)推送新的视图控制器

在 iOS 拆分视图控制器上推送新的视图控制器

从目标视图控制器推送新的视图控制器(swift)

在推送新的视图控制器之前移除键盘

如何从嵌入在视图控制器中的表视图中的集合视图中传递数据并推送新的视图控制器?

从标签栏应用程序中的表格视图推送新的视图控制器