سؤال

I have a UITableViewController as a subview of my UIViewController. The table view is populated from an RSS feed and that works fine. 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. I know my current code would work correctly if I was using the UITableViewController on it's own and not as a subview.

Here is my code:

- (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

My 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
هل كانت مفيدة؟

المحلول

As others have pointed out in the comments, and as indicated by the console message you get, your primary problem is that you never initialize webViewController. Add a line that looks something like this to your table view controller's initWithStyle: initializer.

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

Other things that I spotted:

  • In viewDidLoad you alloc/init a new UITableView. You should not do this because you are overwriting the UITableView instance that was already created by the UITableViewController base class in loadView. Check out my other answer for more info about the lifecycle of views and view controllers.

  • In the parent view controller you forgot to invoke didMoveToParentViewController. You need to do this after you call addChildViewController. Read the section "Implementing a Container View Controller" in the UIViewController class reference for details.

نصائح أخرى

If UIViewController addSubView a view of UITableViewController,you want to push in the method of tableView:didSelectRowAtIndexPath,you should check if self.navigationController is nil. If it's nil,You probably should use

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

if self.parentViewController is also nil,Sometimes,you have to set a @property to point out the parentViewController In UITableViewController,like:

@property (nonatomic, weak) UIViewController *parentVC;

and in UIViewController:

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

In UITableViewController ,-tableView:didSelectRowAtIndexPath:

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

When you execute :

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

It may print as:

‼️‼️‼️‼️‼️self.navigationController is(null),
self.parentViewController.navigationController is (null),
self.parentVC.navigationController is <UINavigationController: 0x7af32ae0>
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top