ios - UISplitView,设置委托(delegate)时接收语义问题

标签 ios xcode delegates uisplitviewcontroller

我一直按照 Big Nerd Ranch 的 iOS 编程指南(第 3 版)来设置我的 Xcode 项目,该项目显示我公司产品的列表,然后显示每个产品的详细 View 。

我让应用程序按照我需要的方式顺利运行,但当我试图改善用户体验时,我开始遇到麻烦。为 iPad 添加 UISplitViewController 给我带来了无尽的头痛和浪费了下午的时间。

目前,我收到了有关委托(delegate)相关代码的语义问题报告。一个在 DetailViewController.h 中,另一个在 ListViewController.m 中。

在发布这段代码之前,我会总结一下我的意图,但由于我缺乏经验,我可能会错过一些微妙之处:

AppDelegate 分配 UITableViewController(ListViewController 类)和 UIViewController(DetailViewController 类),然后检查 iPad。如果是 iPad,它会使用两个 View 的数组创建一个 UISplitViewController。否则,它将加载 ListViewController 作为主视图。

在我尝试在两个 View 之间创建委托(delegate)关系之前,应用程序已成功构建,但 iPad UISplitViewController 仅加载了一个空的详细 View 。 iPhone加载ListViewController,然后选择一行显示一个空的详细 View (DetailViewController)。当您返回到 TableView 并选择相同或另一个表格单元格时,正确的信息将加载到 DetailView 中。这让我相信 TableView 的初始实例没有正确传递选择,但返回它(重新分配它?)会纠正问题。我希望委托(delegate)设置能够解决这个问题。由于我无法使该部分正常工作,因此无法测试该理论。我只是想我应该提一下。

关于 UISplitViewController 问题和教程,我已经尽我所能地四处查看(正确的关键字和搜索词让我困惑),但它们都与我在项目中已经设置的内容有很大不同,无论是应用程序的行为还是代码的整体结构。当我看起来如此接近时,我宁愿不必重新开始。

我已经打开了 BigNerdRanch 示例代码(它确实有效),正如我所说,唯一的差异似乎与我想要显示信息的方式有关。此时我需要一些帮助,请找出我做错了什么。

提前致谢!

AppDelegate.m:

#import "ProductFeedAppDelegate.h"
#import "ListViewController.h"
#import "DetailViewController.h"

@implementation ProductFeedAppDelegate

@synthesize window = _window;
@synthesize managedObjectContext = _managedObjectContext;
@synthesize managedObjectModel = _managedObjectModel;
@synthesize persistentStoreCoordinator = _persistentStoreCoordinator;

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{

    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

    ListViewController *lvc = [[ListViewController alloc] initWithStyle:UITableViewStylePlain];
    UINavigationController *masterNav = [[UINavigationController alloc] initWithRootViewController:lvc];

    DetailViewController *dvc = [[DetailViewController alloc] init];
    [lvc setDetailViewController:dvc];

    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {


        UINavigationController *detailNav = [[UINavigationController alloc] initWithRootViewController:dvc];
        NSArray *vcs = [NSArray arrayWithObjects:masterNav, detailNav, nil];
        UISplitViewController *svc = [[UISplitViewController alloc] init];

        //set delegate
        [svc setDelegate:dvc];
        [svc setViewControllers:vcs];

        [[self window] setRootViewController:svc];

    } else {

        [[self window] setRootViewController:masterNav];

    }



    self.window.backgroundColor = [UIColor whiteColor];
    [self.window makeKeyAndVisible];
    return YES;
}

//... trimmed out some template code to spare you
@end

` ListViewController.h:

    #import <Foundation/Foundation.h>
#import "ProductItemCell.h"
//#import "ItemStore.h"
#import "DetailViewController.h"

@class DetailViewController;

@class RSSChannel;

@interface ListViewController : UITableViewController 
{

    RSSChannel *channel;
}

@property (nonatomic, strong) DetailViewController *detailViewController;

-(void)fetchEntries;

@end

//A new protocol named ListViewControllerDelegate
@protocol ListViewControllerDelegate

//Classes that conform to this protocol must implement this method:
- (void)listViewController:(ListViewController *)lvc handleObject:(id)object;
@end

ListViewController.m:

#import "ListViewController.h"
#import "RSSChannel.h"
#import "RSSItem.h"
#import "DetailViewController.h"
#import "ContactViewController.h"
#import "FeedStore.h"

@implementation ListViewController
@synthesize detailViewController;

- (void)transferBarButtonToViewController:(UIViewController *)vc
{
    // Trimming Code
}
- (id)initWithStyle:(UITableViewStyle)style
{
    // Trimming Code
}

- (void)showInfo:(id)sender
{
    // Create the contact view controller
    ContactViewController *contactViewController = [[ContactViewController alloc] init];

    if ([self splitViewController]) {
        [self transferBarButtonToViewController:contactViewController];

        UINavigationController *nvc = [[UINavigationController alloc]
                                       initWithRootViewController:contactViewController];

        // Create an array with our nav controller and this new VC's nav controller
        NSArray *vcs = [NSArray arrayWithObjects:[self navigationController],
                        nvc,
                        nil];

        // Grab a pointer to the split view controller
        // and reset its view controllers array.
        [[self splitViewController] setViewControllers:vcs];

        // Make contact view controller the delegate of the split view controller
        [[self splitViewController] setDelegate:contactViewController];

        // If a row has been selected, deselect it so that a row
        // is not selected when viewing the info
        NSIndexPath *selectedRow = [[self tableView] indexPathForSelectedRow];
        if (selectedRow)
            [[self tableView] deselectRowAtIndexPath:selectedRow animated:YES];
    } else {
        [[self navigationController] pushViewController:contactViewController
                                               animated:YES];
    }

    // Give the VC the channel object through the protocol message
   // [channelViewController listViewController:self handleObject:channel];
}


- (void)viewDidLoad
{
    // Trimming Code
}


- (NSInteger)tableView:(UITableView *)tableView
 numberOfRowsInSection:(NSInteger)section
{
    return [[channel items] count];
}

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

    // Trimming Code

}

- (void)fetchEntries
{
    // Trimming Code
}

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

    if (![self splitViewController])
        [[self navigationController] pushViewController:detailViewController animated:YES];
    else {
        [self transferBarButtonToViewController:detailViewController];
        // We have to create a new navigation controller, as the old one
        // was only retained by the split view controller and is now gone
        UINavigationController *nav =
        [[UINavigationController alloc] initWithRootViewController:detailViewController];

        NSArray *vcs = [NSArray arrayWithObjects:[self navigationController],
                        nav,
                        nil];

        [[self splitViewController] setViewControllers:vcs];

        // Make the detail view controller the delegate of the split view controller
        [[self splitViewController] setDelegate:detailViewController];

    }

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

     // Next line reports: No visible @interface for 'DetailViewController' declares the selector 'listViewController:handleObject:'
    [detailViewController listViewController:self handleObject:item]; 



}


@end

DetailViewController.h:

#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import "ListViewController.h"

@class RSSItem;
@class Reachability;

@interface DetailViewController : UIViewController <ListViewControllerDelegate> // Cannot find protocol declaration for 'ListViewControllerDelegate' 
{
    __weak IBOutlet UILabel *nameField;
    __weak IBOutlet UITextView *descriptField;
    __weak IBOutlet UIImageView *imageView;
    __weak IBOutlet UITextView *introtextField;
    __weak IBOutlet UIButton *dsButton;
    __weak IBOutlet UIButton *aeButton;
    __weak IBOutlet UIButton *imButton;
}

-(BOOL)reachable;

@property (nonatomic, strong) RSSItem *item;
@property (nonatomic, strong) UIImage *productImage;

@end

DetailViewController.m:

#import "DetailViewController.h"
#import "RSSItem.h"
#import "RSSChannel.h"
#import "Reachability.h"


@interface DetailViewController ()

@end

@implementation DetailViewController

- (void)listViewController:(ListViewController *)lvc handleObject:(id)object
{
    //RSSItem *item = object; //This was in the example code but if left in the next line reported "Local declaration of 'item' hides instance variable"
    // Validate the RSSItem
    if (![item isKindOfClass:[RSSItem class]])
          return;

    [self setItem:item];
    [[self navigationItem] setTitle:[item name]];


    [nameField setText:[item name]];
    [descriptField setText:[item descript]];
    [introtextField setText:[item introtext]];
}

@synthesize item;

- (BOOL)reachable{
    // Trimming Code
}
- (void)viewDidLoad
{
    [super viewDidLoad];
    [[self view] setBackgroundColor:[UIColor whiteColor]];
}

- (void)viewWillAppear:(BOOL)animated
{
    if (item){
        [super viewWillAppear:animated];

        [nameField setText:[item name]];
        [descriptField setText:[item descript]];
        [introtextField setText:[item introtext]];
        // Trimming Code (all the stuff that looks for this or that value and acts upon it)
    }  else {
        // The following appears in the log:
        NSLog(@"There's no item selected");
    }

}



@end

最佳答案

我认为您遇到了编译器因有多个而感到困惑的问题

#import "DetailViewController.h"

如果您从 ListViewController.h 中删除此导入并保留

@class DetailViewController;

那么我认为这将解决你的编译器问题。

您可能需要添加< UISplitViewControllerDelegate >不过,还有其他几门课。看起来您将它们设置为分割 View 上的委托(delegate),但没有采用协议(protocol)。

关于ios - UISplitView,设置委托(delegate)时接收语义问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13423348/

相关文章:

iphone - UITextField 字体样式没有改变

ios - UIViewContentModeRedraw 与 setNeedsDisplay?

ios - 如何在同一委托(delegate)类中将委托(delegate)方法作为选择器调用

c# - "event"关键字的用途

objective-c - 将 NSTokenField 绑定(bind)到数组 Controller

ios - 如何以编程方式获取正确的 iOS 版本?

ios - IBOutlet 在 IBAction 实现后返回 nil (IOS)

ios - 按 dateTimeString 属性对 NSMutableArray 对象进行排序

ios - 带有swift的服务器套接字

ios - 无法使用 AVCapturePhotoOutput 捕捉照片 swift + xcode