我有一个 iPhone 应用程序,我想制作一个通用应用程序并在 iPad 上实现拆分视图。我设置了主视图,以便当用户选择一行时,主视图转到另一个表视图。在该表视图中选择一行时,我希望详细视图显示我的 Web 视图。这一切都有效,但我遇到的问题是当 web 视图显示在详细视图上时,它只是被添加到导航堆栈中,而不是仅仅替换当前存在的内容。这使得用户必须按下详细视图导航栏上的后退按钮才能在主视图中进行另一个选择。如果在主视图中进行了其他选择而没有按详细视图上的后退按钮,则应用程序崩溃。
我需要弄清楚如何不将 Web 视图添加到详细视图的导航堆栈中,而是替换当前的详细视图。
主视图控制器:
#import "KFBMasterViewController.h"
#import "KFBDetailViewController.h"
#import "ListViewController.h"
#import "SocialNetworks.h"
#import "WebViewController.h"
@interface KFBMasterViewController () {
NSMutableArray *_objects;
NSMutableArray *menu;
}
@end
@implementation KFBMasterViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.title = NSLocalizedString(@"Master", @"Master");
self.clearsSelectionOnViewWillAppear = NO;
self.contentSizeForViewInPopover = CGSizeMake(320.0, 600.0);
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// self.navigationItem.leftBarButtonItem = self.editButtonItem;
// UIBarButtonItem *addButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(insertNewObject:)];
// self.navigationItem.rightBarButtonItem = addButton;
menu = [NSMutableArray arrayWithObjects:@"Home", @"Public Affairs", @"Action Alerts", @"Market Updates", @"Ag Stories", @"KFB News", @"Member Benefits", @"Monthly Video", @"Photos", @"Social Media", @"About Us", @"Contact Us", @"KYFB.com", nil];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)insertNewObject:(id)sender
{
if (!_objects) {
_objects = [[NSMutableArray alloc] init];
}
[_objects insertObject:[NSDate date] atIndex:0];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
[self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
#pragma mark - Table View
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return menu.count;
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// NSDate *object = _objects[indexPath.row];
// cell.textLabel.text = [object description];
cell.textLabel.text = [menu objectAtIndex:indexPath.row];
return cell;
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the specified item to be editable.
return YES;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
[_objects removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
} else if (editingStyle == UITableViewCellEditingStyleInsert) {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view.
}
}
/*
// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
}
*/
/*
// Override to support conditional rearranging of the table view.
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the item to be re-orderable.
return YES;
}
*/
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// NSDate *object = _objects[indexPath.row];
// self.detailViewController.detailItem = object;
// KFBDetailViewController *detailViewController = (KFBDetailViewController*)self.splitViewController.delegate;
// UIViewController <SubstitutableDetailViewController> *detailViewController = nil;
if (indexPath.row == 1)
{
// [((UINavigationController *)[self.splitViewController.viewControllers lastObject]) pushViewController:[[ListViewController alloc]initWithStyle:UITableViewStylePlain] animated:YES];
// [[self.splitViewController.viewControllers lastObject] pushViewController:[[ListViewController alloc]initWithStyle:UITableViewStylePlain] animated:YES];
// ListViewController *publicAffairs = [[ListViewController alloc] initWithNibName:nil bundle:[NSBundle mainBundle]];
// [self.navigationController pushViewController:publicAffairs animated:YES];
ListViewController *publicAffairs = [[ListViewController alloc]initWithStyle:UITableViewStylePlain];
WebViewController *wvc = [[WebViewController alloc]init];
[publicAffairs setWebViewController:wvc];
publicAffairs.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self.navigationController pushViewController:publicAffairs animated:YES];
// [self presentViewController:publicAffairs animated:YES completion:nil];
}
else if (indexPath.row == 9)
{
// [((UINavigationController *)[self.splitViewController.viewControllers lastObject]) pushViewController:[[SocialNetworks alloc]initWithNibName:@"SocialNetworks" bundle:nil] animated:YES];
// [[self.splitViewController.viewControllers lastObject] pushViewController:[[SocialNetworks alloc]initWithNibName:@"SocialNetworks" bundle:nil] animated:YES];
SocialNetworks *social = [[SocialNetworks alloc] initWithNibName:@"SocialNetworks" bundle:[NSBundle mainBundle]];
[self.navigationController pushViewController:social animated:YES];
}
}
@end
细节视图控制器:
#import "KFBDetailViewController.h"
@interface KFBDetailViewController ()
@property (strong, nonatomic) UIPopoverController *masterPopoverController;
- (void)configureView;
@end
@implementation KFBDetailViewController
#pragma mark - Managing the detail item
- (void)setDetailItem:(id)newDetailItem
{
if (_detailItem != newDetailItem) {
_detailItem = newDetailItem;
// Update the view.
[self configureView];
}
if (self.masterPopoverController != nil) {
[self.masterPopoverController dismissPopoverAnimated:YES];
}
}
- (void)configureView
{
// Update the user interface for the detail item.
if (self.detailItem) {
self.detailDescriptionLabel.text = [self.detailItem description];
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self configureView];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
self.title = NSLocalizedString(@"Detail", @"Detail");
}
return self;
}
#pragma mark - Split view
- (void)splitViewController:(UISplitViewController *)splitController willHideViewController:(UIViewController *)viewController withBarButtonItem:(UIBarButtonItem *)barButtonItem forPopoverController:(UIPopoverController *)popoverController
{
barButtonItem.title = NSLocalizedString(@"Master", @"Master");
[self.navigationItem setLeftBarButtonItem:barButtonItem animated:YES];
self.masterPopoverController = popoverController;
}
- (void)splitViewController:(UISplitViewController *)splitController willShowViewController:(UIViewController *)viewController invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem
{
// Called when the view is shown again in the split view, invalidating the button and popover controller.
[self.navigationItem setLeftBarButtonItem:nil animated:YES];
self.masterPopoverController = nil;
}
@end
列表视图控制器:
#import "ListViewController.h"
#import "RSSChannel.h"
#import "RSSItem.h"
#import "WebViewController.h"
#import "KFBDetailViewController.h"
// #import "CustomCellBackground.h"
@implementation ListViewController
{
UIActivityIndicatorView *loadingIndicator;
}
@synthesize webViewController;
- (void)viewDidLoad
{
self.tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped];
self.title = @"Public Affairs";
loadingIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
loadingIndicator.center = CGPointMake(160, 160);
loadingIndicator.hidesWhenStopped = YES;
[self.view addSubview:loadingIndicator];
[loadingIndicator startAnimating];
// UIRefreshControl *refresh = [[UIRefreshControl alloc] init];
// refresh.attributedTitle = [[NSAttributedString alloc] initWithString:@"Pull to Refresh"];
// [refresh addTarget:self action:@selector(refreshView:)forControlEvents:UIControlEventValueChanged];
// self.refreshControl = refresh;
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict
{
if ([elementName isEqual:@"channel"])
{
// If the parser saw a channel, create new instance, store in our ivar
channel = [[RSSChannel alloc]init];
// Give the channel object a pointer back to ourselves for later
[channel setParentParserDelegate:self];
// Set the parser's delegate to the channel object
[parser setDelegate:channel];
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// return 0;
NSLog(@"channel items %d", [[channel items]count]);
return [[channel items]count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// return nil;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"UITableViewCell"];
if (cell == nil)
{
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"UITableViewCell"];
cell.textLabel.font=[UIFont systemFontOfSize:16.0];
}
RSSItem *item = [[channel items]objectAtIndex:[indexPath row]];
// cell.backgroundView = [[CustomCellBackground alloc] init];
// cell.selectedBackgroundView = [[CustomCellBackground alloc] init];
cell.textLabel.backgroundColor = [UIColor clearColor];
cell.textLabel.highlightedTextColor = [UIColor darkGrayColor];
if (item.isActionAlert) {
NSLog(@"Action Alert...Not Using");
}
else
{
[[cell textLabel]setText:[item title]];
}
return cell;
}
- (void)fetchEntries
{
// Create a new data container for the stuff that comes back from the service
xmlData = [[NSMutableData alloc]init];
// Construct a URL that will ask the service for what you want -
NSURL *url = [NSURL URLWithString:@"http://kyfbnewsroom.com/category/public-affairs/feed"];
// Put that URL into an NSURLRequest
NSURLRequest *req = [NSURLRequest requestWithURL:url];
// Create a connection that will exchange this request for data from the URL
connection = [[NSURLConnection alloc]initWithRequest:req delegate:self startImmediately:YES];
}
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self)
{
[self fetchEntries];
}
return self;
}
// This method will be called several times as the data arrives
- (void)connection:(NSURLConnection *)conn didReceiveData:(NSData *)data
{
// Add the incoming chunk of data to the container we are keeping
// The data always comes in the correct order
[xmlData appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)conn
{
/* We are just checking to make sure we are getting the XML
NSString *xmlCheck = [[NSString alloc]initWithData:xmlData encoding:NSUTF8StringEncoding];
NSLog(@"xmlCheck = %@", xmlCheck);*/
[loadingIndicator stopAnimating];
// Create the parser object with the data received from the web service
NSXMLParser *parser = [[NSXMLParser alloc]initWithData:xmlData];
// Give it a delegate
[parser setDelegate:self];
//Tell it to start parsing - the document will be parsed and the delegate of NSXMLParser will get all of its delegate messages sent to it before this line finishes execution - it is blocking
[parser parse];
// Get rid of the XML data as we no longer need it
xmlData = nil;
// Reload the table.. for now, the table will be empty
NSMutableArray *actionAlerts = [NSMutableArray array];
for (RSSItem *object in channel.items) {
if (object.isActionAlert) {
[actionAlerts addObject:object];
}
}
for (RSSItem *object in actionAlerts) {
[channel.items removeObject:object];
}
[[self tableView]reloadData];
NSLog(@"%@\n %@\n %@\n", channel, [channel title], [channel infoString]);
}
- (void)connection:(NSURLConnection *)conn didFailWithError:(NSError *)error
{
// Release the connection object, we're done with it
connection = nil;
// Release the xmlData object, we're done with it
xmlData = nil;
// Grab the description of the error object passed to us
NSString *errorString = [NSString stringWithFormat:@"Fetch failed: %@", [error localizedDescription]];
// Create and show an alert view with this error displayed
UIAlertView *av = [[UIAlertView alloc]initWithTitle:@"Error" message:errorString delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
[av show];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[((UINavigationController *) [self.splitViewController.viewControllers lastObject]) pushViewController:webViewController animated:YES];
// Grab the selected item
RSSItem *entry = [[channel items]objectAtIndex:[indexPath row]];
NSLog(@"Channel Items: %@", [[channel items]objectAtIndex:[indexPath row]]);
// Construct a URL with the link string of the item
NSURL *url = [NSURL URLWithString:[entry link]];
NSLog(@"Link: %@", [entry link]);
// Construct a request object with that URL
NSURLRequest *req = [NSURLRequest requestWithURL:url];
NSLog(@"URL: %@", url);
// Load the request into the web view
[[webViewController webView]loadRequest:req];
webViewController.hackyURL = url;
NSLog(@"Request: %@", req);
// Set the title of the web view controller's navigation item
// [[webViewController navigationItem]setTitle:[entry title]];
NSLog(@"Title: %@", [entry title]);
}
@end
应用委托:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
KFBMasterViewController *masterViewController = [[KFBMasterViewController alloc] initWithNibName:@"KFBMasterViewController" bundle:nil];
UINavigationController *masterNavigationController = [[UINavigationController alloc] initWithRootViewController:masterViewController];
KFBDetailViewController *detailViewController = [[KFBDetailViewController alloc] initWithNibName:@"KFBDetailViewController" bundle:nil];
UINavigationController *detailNavigationController = [[UINavigationController alloc] initWithRootViewController:detailViewController];
masterViewController.detailViewController = detailViewController;
self.splitViewController = [[UISplitViewController alloc] init];
self.splitViewController.delegate = detailViewController;
self.splitViewController.viewControllers = @[masterNavigationController, detailNavigationController];
self.window.rootViewController = self.splitViewController;
[self.window makeKeyAndVisible];
return YES;
}