无法使用 Xcode 4.2.1、iOS 5.0 和 Storyboards 连接 IBOutlet

发布于 2024-12-29 14:29:33 字数 1186 浏览 1 评论 0原文

我正在尝试将一个类(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

我做错了什么?

I'm trying to connect an IBOutlet in a class (DataViewController) to another class (RootViewController) so that I can access the instance of RootViewController in DataViewController.

There are no compile warnings or errors. When I select DataViewController in the IB scene, I can see the outlet I've defined in Connections Inspector->Outlets. But when I try to drag a connection from the outlet to RootViewController, it doesn't work. It just fails without any error or indication of what's wrong.

I've verified that the RootViewController scene has Custom Class "RootViewController".

Here's my code:

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

What am I doing wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

蘑菇王子 2025-01-05 14:29:33

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

在当前项目中,我创建了一个委托协议来在两个控制器之间进行通信:SelectNoteViewController(选择)和EditNoteViewController(编辑)。基本思想是“选择”用于从注释列表中进行选择,“编辑”用于编辑这些注释。现在,我需要 Edit 才能访问 Select 保留的数据和方法,因为我在编辑中有按钮可以从 Select 管理的列表中调用上一个或下一个注释,因此我实现了委托协议。 Select 是编辑的委托。这意味着 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 需要在其末端定义协议,它将用于访问 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 时设置一些参数。我对委托协议的使用返回到“选择”,并将另一个注释(上一个或下一个)传递给“编辑”。我希望这有帮助。您可以看到创建委托协议有几个步骤。我给它们编号为1-9。如果数据没有恢复,我通常会发现我忘记了其中一个步骤。

You can't do that. You need to setup a delegate protocol. See This tutorial
and search down for the words "new delegate" and it will explain how that is done. That is the design pattern you need to use. There are several steps involved so follow closely. It is worth learning. Delegate protocols are common in iPhone Apps.

In a current project I created a delegate protocol to communicate between two controller: SelectNoteViewController (Select) and EditNoteViewController (Edit). The basic idea is that Select is used to select from a list of notes and Edit is used to edit those notes. Now, I need Edit to have access back into the data and methods kept by Select because I have buttons in edit to call up the previous or next note from the list which is managed by Select so I implement a delegate protocol. Select is a delegate for Edit. That means Select does things for Edit. Here is the essential code.

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 now has the structure to do be a delegate for Edit. Now Edit needs to define the protocol on its end that it is going to use to get to those methods in 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];

That is it. Of course the protocol methods are like and other method and they can be passed parameters which what you need to do to pass data back which was your question in the first place. As a side note, see that I can pass data from Select to Edit without a protocol by creating properties in Edit and setting those properties in the prepareForSegue method of Select. Doing so gives me one shot to set some parameters when Edit is instantiated. My use of a the delegate protocol goes back to Select and has it pass another note (previous or next) to Edit. I hope that helps. You can see there are several steps to creating a delegate protocol. I numbered them 1-9. If the data is not making it back, I usually find I forgot one of the steps.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文