【问题标题】:Can't connect IBOutlet using Xcode 4.2.1, iOS 5.0 and Storyboards无法使用 Xcode 4.2.1、iOS 5.0 和 Storyboard 连接 IBOutlet
【发布时间】:2012-01-28 07:57:20
【问题描述】:

我正在尝试将一个类 (DataViewController) 中的 IBOutlet 连接到另一个类 (RootViewController),以便我可以访问 DataViewController 中的 RootViewController 实例。

没有编译警告或错误。当我在 IB 场景中选择 DataViewController 时,可以看到我在 Connections Inspector->Outlets 中定义的插座。但是当我尝试将连接从插座拖到 RootViewController 时,它不起作用。它只是失败了,没有任何错误或错误指示。

我已验证 RootViewController 场景具有自定义类“RootViewController”。

这是我的代码:

//RootViewController.h
#import <UIKit/UIKit.h>

@interface RootViewController : UIViewController <UIPageViewControllerDelegate>
@property (strong, nonatomic) UIPageViewController *pageViewController;
@end


//DataViewController.h
#import <UIKit/UIKit.h>
@class RootViewController;

@interface DataViewController : UIViewController < UIWebViewDelegate > {
    IBOutlet UIWebView *webView;
}
@property (strong, nonatomic) IBOutlet RootViewController *rvc; //this one won't connect. Why?
@property (strong, nonatomic) IBOutlet UILabel *dataLabel;
@property (strong, nonatomic) id dataObject;
@end

//DataViewController.m
#import "DataViewController.h"
#import "RootViewController.h"

@implementation DataViewController

@synthesize rvc;

//...
@end

我做错了什么?

【问题讨论】:

    标签: ios5 xcode4.2 storyboard iboutlet


    【解决方案1】:

    你不能那样做。您需要设置委托协议。见This tutorial 并搜索“新代表”一词,它将解释如何完成。这就是您需要使用的设计模式。涉及多个步骤,因此请密切关注。值得学习。委托协议在 iPhone 应用程序中很常见。

    在当前项目中,我创建了一个委托协议来在两个控制器之间进行通信:SelectNoteViewController (Select) 和 EditNoteViewController (Edit)。基本思想是 Select 用于从笔记列表中进行选择,而 Edit 用于编辑这些笔记。现在,我需要 Edit 才能访问 Select 保存的数据和方法,因为我在编辑中有按钮可以从 Select 管理的列表中调用上一个或下一个注释,因此我实现了一个委托协议。 Select 是 Edit 的代表。这意味着 Select 为 Edit 做事。这是基本代码。

    SelectNoteViewController.h:

    // this next statement is need to inform Select of the protocols defined in Edit
    #import "EditNoteViewController.h" // STEP 1
    
    
    @interface SelectNoteViewController : UITableViewController <EditNoteViewControllerDelegate> { ... // STEP 2: this says Select implements the protocol I created
    ...
    // STEP 3: EditNoteViewController Delegate Methods - these are the methods in the protocol
    - (Notes *)selectPreviousNote;
    - (Notes *)selectNextNote;
    

    SelectNoteViewController.m:

    // STEP 4: the protocol methods are implemented
    - (Notes *)selectPreviousNote {
        if (isPreviousToSelectedNote) {
            NSIndexPath *indexPath, *previousIndexPath;
            indexPath = [self.tableView indexPathForSelectedRow];
            previousIndexPath = [NSIndexPath indexPathForRow:indexPath.row+1 inSection:0];
            // update the selected row
            self.selectedNote = [self.fetchedResultsController objectAtIndexPath:previousIndexPath];
            [self.tableView selectRowAtIndexPath:previousIndexPath animated:NO scrollPosition:UITableViewScrollPositionMiddle];
            [self setPreviousNote];
            [self setNextNote];
        } 
    return selectedNote;
    }
    
    - (Notes *)selectNextNote {
        if (isNextToSelectedNote) {
            NSIndexPath *indexPath, *nextIndexPath;
            indexPath = [self.tableView indexPathForSelectedRow];
            nextIndexPath = [NSIndexPath indexPathForRow:indexPath.row-1 inSection:0];
            // update the selected row
            self.selectedNote = [self.fetchedResultsController objectAtIndexPath:nextIndexPath];
            [self.tableView selectRowAtIndexPath:nextIndexPath animated:NO scrollPosition:UITableViewScrollPositionMiddle];
            [self setPreviousNote];
            [self setNextNote];
        }
    return selectedNote;
    }
    ...
        ...
    if ([[segue identifier] isEqualToString:@"editNote"])  {
        // STEP 5: this is where Edit is told that its delegate is Select
        [[segue destinationViewController] setEditNoteViewControllerDelegate:self]; // STEP 5
    

    Select 现在具有作为 Edit 代表的结构。现在 Edit 需要在其末端定义协议,它将用于访问 Select 中的那些方法。

    EditNoteViewController.h

    #import ... // put protocol after import statements
    // STEP 6
    @protocol EditNoteViewControllerDelegate <NSObject>
    
    - (Notes *)selectPreviousNote;
    - (Notes *)selectNextNote;
    
    @end
    
    
    @interface ...
    // STEP7: Edit needs a property to tell it who the delegate is - it was set back in Select.m
    @property (weak) id <EditNoteViewControllerDelegate> editNoteViewControllerDelegate; 
    

    EditNoteViewController.m

    // STEP 8: the property is synthesized
    @synthesize editNoteViewControllerDelegate;
    
    ...
    
    // STEP 9: now when any method needs to call selectPreviousNote or selectNext Note it does it like this:
    selectedNote = [self.editNoteViewControllerDelegate selectPreviousNote];
    // or
    selectedNote = [self.editNoteViewControllerDelegate selectNextNote];
    

    就是这样。当然,协议方法和其他方法一样,它们可以传递参数,你需要做什么才能将数据传回,这首先是你的问题。附带说明一下,通过在 Edit 中创建属性并在 Select 的 prepareForSegue 方法中设置这些属性,我可以在没有协议的情况下将数据从 Select 传递到 Edit。这样做可以让我在实例化 Edit 时设置一些参数。我对委托协议的使用返回到 Select 并将另一个注释(上一个或下一个)传递给 Edit。我希望这会有所帮助。您可以看到创建委托协议有几个步骤。我将它们编号为 1-9。如果数据没有返回,我通常会发现我忘记了其中一个步骤。

    【讨论】:

    • 感谢您的回复,我通读了教程并对委托协议模式进行了更多阅读。我基本上明白了,但如果你不介意的话,我需要更多的提示来应用它。我是否在正确的轨道上认为我想让 RootViewController 符合委托协议?我可以通过在 RootViewController.h 中创建一个委托属性,然后在 RootViewController.m 中 @synthesizing 来实现这一点?还是我很困惑?
    • 感谢您让我走上正确的道路——最终我需要做的是返回并确保我正确理解了底层的 MVC 模式。我使用了出色的斯坦福讲座系列(可通过 iTunes U 获得),现在对正在发生的事情有了更深入的了解,而在此之前,我只了解一半就胡思乱想。
    猜你喜欢
    • 1970-01-01
    • 2013-03-12
    • 2012-03-17
    • 1970-01-01
    • 1970-01-01
    • 2011-12-11
    • 2014-11-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多