2012-07-24 127 views
2

之间的沟通,询问了一些问题后,我学会了如何从一个视图控制器发送命令到另一个,并成功地编写代码的工作,但没有任何反应......使用委托给视图控制器

在项目中,我有两个视图控制器名为sayfa1sayfa23。当单击sayfa1处的按钮时,它将打开sayfa23并写在标签上(随机hello查看下面的代码),但没有发生。在模拟器上,该按钮只能打开sayfa23,这就不会发生任何标签。如果你看看代码,你可以更好地理解它。

sayfa1.h

#import <UIKit/UIKit.h> 

@protocol sayfa1Delegate <NSObject> 

- (void)dealWithButton1; 

@end 


@interface sayfa1 : UIViewController 

@property(nonatomic,assign) id<sayfa1Delegate> delegate; 

@end 

sayfa1.m

#import "sayfa1.h" 

@interface sayfa1() 

@end 

@implementation sayfa1 

@synthesize delegate; 

-(IBAction)button 
{ 
    [delegate dealWithButton1]; 
} 

@end 

sayfa23.h

#import <UIKit/UIKit.h> 
#import "sayfa1.h" 

@interface sayfa23 : UIViewController <sayfa1Delegate> 
{ 
    IBOutlet UILabel *label; 
    sayfa1 *vc1 ; 
} 

@end 

sayfa23.m

#import "sayfa23.h" 
#import "sayfa1.h" 

@interface sayfa23() 

@end 

@implementation sayfa23 

- (void)dealWithButton1 
{ 
    vc1.delegate = self;  
    int random_num; 
    random_num = (arc4random() % 5 - 1) + 1; 
    if (random_num == 1) 
    { 
     label.text = @"hello1";  
    } 
    else if (random_num == 2) 
     label.text = @"hello2"; 
    else if (random_num == 3) 
     label.text = @"hello3"; 
    else if (random_num == 4) 
     label.text = @"hello4"; 
} 

@end 

编写此代码后,我连接到sayfa23的按钮,所以它会打开新的页面,我也连接该按钮到sayfa1接收按钮动作和我连接标签(在sayfa23)到sayfa23接收标签订单。但正如我所说没有发生没有错误,没有问候我做错了什么?我在我的一些h文件的顶部导入了sayfa1.hsayfa23.h,导致Xcode给我一个关于未定义和解决该问题的错误,但这是我的错误还是别的。

我想要的例子。

  • 用户打开

  • sayfa1屏幕上所示

  • 用户点击该按钮并sayfa23显示在sayfa23标签文本由按钮其在sayfa1写随机改变该应用hello1..2..3 etc ...

我做错了什么?

+0

执行'vc1.delegate = self;'时'vc1'的值是多少? – 2012-07-24 13:42:17

+1

我怀疑这种方法是否被称为。 @PhillipMills他正在委托方法内分配委托。 – 2012-07-24 13:45:02

+0

好点!尝试设置它之前使用委托作为接收器是一个坏主意。 (有时候,一种已知的错误模式的存在掩盖了另一种模式。) – 2012-07-24 13:46:15

回答

2

重读你的问题,哟你问你的第一个视图控制器如何打开第二个视图控制器并设置一个文本框。如果那的确是你想要做的,那么这是一个更简单的问题,根本不需要委托协议或代表。

以前的两个答案都是由代表们讨论的,但这是为了解决不同的问题而设计的。如果您需要第二个控制器将某些内容传回第一个控制器,则只需要代表。

// FirstViewController.h 

#import <UIKit/UIKit.h> 

@interface FirstViewController : UIViewController 

@end 

与像的实现:

// FirstViewController.m 

#import "FirstViewController.h" 
#import "SecondViewController.h" 

@implementation FirstViewController 

- (NSString *)generateRandomText 
{ 
    NSString *result; 

    int random_num; 
    random_num = (arc4random() % 5 - 1) + 1; 
    if (random_num == 1) 
     result = @"hello1";  
    else if (random_num == 2) 
     result = @"hello2"; 
    else if (random_num == 3) 
     result = @"hello3"; 
    else if (random_num == 4) 
     result = @"hello4"; 

    return result; 
} 

// if you're using NIBs, it might be something like... 
// you only need this method if you're using NIBs and you've manually hooked a button up to this 
// if you're using segues, get rid of `goToNextViewController` and just use the following `prepareForSegue 

- (IBAction)goToNextViewController:(id)sender 
{ 
    SecondViewController *secondController = [[SecondViewController alloc] initWithNibName:@"SecondView" bundle:nil]; 
    secondController.textFromParent = [self generateRandomText]; 
    [self.navigationController pushViewController:secondController animated:YES]; 
} 

// if you're using segues, give your segue an identifier, e.g. toSecondViewSegue, in Interface Builder and reference the exact same identifier here 
// if you're not using segues, you don't need this prepareForSegue method 

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 
{ 
    if ([segue.identifier isEqualToString:@"toSecondViewSegue"]) 
    { 
     SecondViewController *destinationController = segue.destinationViewController; 

     destinationController.textFromParent = [self generateRandomText]; 
    } 
} 

@end 

而且你的第二个控制器可能类似于:

但如果你只是想你的第二个控制器从第一控制器接收的东西,它就是这么简单
// SecondViewController.h 

#import <UIKit/UIKit.h> 

@interface SecondViewController : UIViewController 

@property (strong, nonatomic) NSString *textFromParent; 
@property (weak, nonatomic) IBOutlet UILabel *label; 

@end 

有了这样的实现:

// SecondViewController.m 

#import "SecondViewController.h" 

@implementation SecondViewController 

@synthesize textFromParent = _textFromParent; 
@synthesize label = _label; 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    self.label.text = self.textFromParent; 
} 

@end 
+0

我会尝试这种方法并与您分享结果是的,我希望我的第一个视图控制器发送第二个。 – 2012-07-24 17:50:15

+0

我粘贴了你写的代码,并创建了两个视图控制器,然后将它们分配为firstviewc ...和第二个vie ...后来我把一个按钮放到firstviewcontroller和一个label到secondviewcontroller.I连接button到nextviewcontroller(转到下一个viewco .. )和标签到secondviewcontoller(作为标签)。在模拟器中有两个问题的按钮不打开第二个viewcontrolelr但它的oke我连接他们usig故事板也在第二页标签不显示任何形式的文本它是那里却空无一物,为什么? – 2012-07-24 17:57:38

+0

@bugrasezer我的代码示例假定您使用的是NIB,并且有一个按钮可以手动调用'pushViewController',它将从NIB加载下一个视图。如果您使用的是故事板,只需在Interface Builder中设置按钮即可继续使用下一个控制器,并且可以使用上面修改的代码示例中所示的“prepareForSegue”。 (如果使用segues,则不再需要'goToNextViewController')。只需确保在Interface Builder中为您的segue提供一个标识符,该标识符与您在'prepareForSegue'代码中引用的标识符的名称完全相同。 – Rob 2012-07-24 18:22:58

0

尝试下面的方法添加到您的sayfa23的实现:

- (void)viewDidLoad 
{ 
    vc1 = [[sayfa1 alloc] init]; 
    vc1.delegate = self; 
} 

,并删除vc1.delegate =自我;从你的dealWithButton1方法。

编辑: 你必须明白,方法dealWithButton1永远不会被调用,因为你永远不会发送消息到对象。因此,你永远不会设置vc1的委托。使用viewDidLoad方法进行一些设置是很好的一点,viewDidLoad方法在加载视图时调用。在那里你可以分配init(创建一个sayfa1类的实例),并将它分配给你的属性vc1。分配对象后,您可以向其发送消息。你可以设置委托。

sayfa23。^ h

#import <UIKit/UIKit.h> 
#import "sayfa1.h" 

@interface sayfa23 : UIViewController <sayfa1Delegate> 



{ 

    IBOutlet UILabel *label; 
} 
    @property (nonatomic, strong) sayfa1 *vc1 ; 



@end 

sayfa23.m

#import "sayfa23.h" 
#import "sayfa1.h" 

@interface sayfa23() 

@end 

@implementation sayfa23 
@synthesize vc1; 


- (void)viewDidLoad 
{ 
    vc1 = [[sayfa1 alloc] init]; 
    vc1.delegate = self; 
} 

- (void)dealWithButton1 

{ 
    int random_num; 
    random_num = (arc4random() % 5 - 1) + 1; 
    if (random_num == 1) 
    { 
     label.text = @"hello1";  
    } 
    else if (random_num == 2) 
     label.text = @"hello2"; 
    else if (random_num == 3) 
     label.text = @"hello3"; 
    else if (random_num == 4) 
     label.text = @"hello4"; 
} 


@end 
+0

我添加了你写给sayfa23.h的代码,它是vc1 = [[sayf ....但是后来什么都没有发生,我尝试从sayfa23.h中删除vc1.delegate = self,但仍然没有发生任何事情。从别处删除它? – 2012-07-24 14:04:31

+0

检查我的编辑。代码进入sayfa23.m,而不是.h – 2012-07-24 14:07:35

+0

我用你写的新代码(void)viewdidload仍然没有任何发生:S – 2012-07-24 14:07:42

1

你的第一个控制器应,当它实例化的第二个控制器,设置第二的委托重新指向第一个视图控制器。因此,你的第一个视图控制器看起来像:

// FirstViewController.h 

#import <UIKit/UIKit.h> 

@protocol FirstViewControllerDelegate <NSObject> 

- (void)dealWithButton; 

@end 

@interface FirstViewController : UIViewController <FirstViewControllerDelegate> 

@end 

与像的实现:

// FirstViewController.m 

#import "FirstViewController.h" 
#import "SecondViewController.h" 

@implementation FirstViewController 

- (IBAction)goToNextViewController:(id)sender 
{ 
    SecondViewController *secondController = [[SecondViewController alloc] initWithNibName:@"SecondView" bundle:nil]; 
    secondController.delegate = self; 
    [self.navigationController pushViewController:secondController animated:YES]; 
} 

- (void)dealWithButton 
{ 
    NSLog(@"Dealt with button from second controller"); 
} 

@end 

而且你的第二个控制器可能类似于:

// SecondViewController.h 

#import <UIKit/UIKit.h> 
#import "FirstViewController.h" 

@class FirstViewController; 

@interface SecondViewController : UIViewController 

@property (weak, nonatomic) id<FirstViewControllerDelegate> delegate; 
@property (weak, nonatomic) IBOutlet UILabel *label; 

- (IBAction)buttonPressed:(id)sender; 

@end 

有了这样的实现:

// SecondViewController.m 

#import "SecondViewController.h" 

@implementation SecondViewController 

@synthesize delegate = _delegate; 
@synthesize label = _label; 

- (IBAction)buttonPressed:(id)sender 
{ 
    int random_num; 
    random_num = (arc4random() % 5 - 1) + 1; 
    if (random_num == 1) 
     self.label.text = @"hello1";  
    else if (random_num == 2) 
     self.label.text = @"hello2"; 
    else if (random_num == 3) 
     self.label.text = @"hello3"; 
    else if (random_num == 4) 
     self.label.text = @"hello4"; 

    [self.delegate dealWithButton]; 
} 
@end 

更新:

您的原始问题并没有说明您是希望标签位于第一个控制器上还是第二个控制器上。我的回答上面假设你想要在第二个控制器上,但回想起来,你可能想要它在第一个控制器(代表)上。如果是这样,下面的代码就是这样做的。请注意,我不只是更新dealWithButton中的第一个视图控制器的标签,因为这很危险,因为您不知道视图是否可见(如果您收到didReceiveMemoryWarning,可能已被卸载)。所以我等待viewWillAppear。如此反复,第一视图控制器:

// FirstViewController.h 

#import <UIKit/UIKit.h> 

@protocol FirstViewControllerDelegate <NSObject> 

- (void)dealWithButton; 

@end 

@interface FirstViewController : UIViewController <FirstViewControllerDelegate> 

@property (weak, nonatomic) IBOutlet UILabel *label; 

@end 

及其实施:

// FirstViewController.m 

#import "FirstViewController.h" 
#import "SecondViewController.h" 

@interface FirstViewController() 
{ 
    NSString *_labelText; 
} 
@end 

@implementation FirstViewController 

@synthesize label = _label; 

// if you're using storyboards, it would be like: 

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 
{ 
    if ([segue.identifier isEqualToString:@"delegateSegue"]) 
    { 
     SecondViewController *destinationController = segue.destinationViewController; 
     FirstViewController *sourceController = segue.sourceViewController; 

     destinationController.delegate = sourceController; 
    } 
} 

// if not using storyboards, you probably have a button like: 

- (IBAction)goToNextViewController:(id)sender 
{ 
    SecondViewController *secondController = [[SecondViewController alloc] initWithNibName:@"SecondView" bundle:nil]; 
    secondController.delegate = self; 
    [self.navigationController pushViewController:secondController animated:YES]; 
} 

- (void)dealWithButton 
{ 
    // note, because this is being called by the second view controller, you should *not* update the UI 
    // directly, because you can't be assured this view controller's view is still in memory (if you got 
    // a didReceiveMemoryWarning while on the second view controller, this first view controller will 
    // stay in memory, but its view could have been released). So save what you want the label to be, 
    // and update it on viewWillAppear (and if the view was released, it will be reloaded by the time 
    // you hit viewWillAppear. 
    // 
    // clearly, if you were doing view controller containment and this was the parent view, you wouldn't 
    // want to do this. But I assume you're dealing with a simple push/present view controller situation. 

    int random_num; 
    random_num = (arc4random() % 5 - 1) + 1; 
    if (random_num == 1) 
     _labelText = @"hello1";  
    else if (random_num == 2) 
     _labelText = @"hello2"; 
    else if (random_num == 3) 
     _labelText = @"hello3"; 
    else if (random_num == 4) 
     _labelText = @"hello4"; 

    NSLog(@"Dealt with button from second controller"); 
} 

- (void)viewWillAppear:(BOOL)animated 
{ 
    self.label.text = _labelText; 
} 

@end 

而第二个视图控制器:

// SecondViewController.h 

#import <UIKit/UIKit.h> 
#import "FirstViewController.h" 

@class FirstViewController; 

@interface SecondViewController : UIViewController 

@property (weak, nonatomic) id<FirstViewControllerDelegate> delegate; 

- (IBAction)buttonPressed:(id)sender; 

@end 

及其实施:

// SecondViewController.m 

#import "SecondViewController.h" 

@interface SecondViewController() 

@end 

@implementation SecondViewController 

@synthesize delegate = _delegate; 

- (IBAction)buttonPressed:(id)sender 
{ 
    [self.delegate dealWithButton]; 
} 
@end 
+0

我将在一个新项目中尝试这些代码并与您分享结果 – 2012-07-24 15:00:48

+0

当我编写第一组代码时,什么也没有发生,在第二组中,我认为我需要进行一些调试。我想要的是当用户单击按钮视图控制器2将来到屏幕上,它的标签被按钮(这是在viewcontroller1),所以我想在视图控制器之间传输数据。当我在两个组中使用你的代码,我不能分配我的按钮做出行动(右键拖动行事)只有nextviewcontroller显示出来。 – 2012-07-24 15:18:40

+0

@bugrasezer这显然只是将按钮连接到方法的基础问题。显然,在Interface Builder中没有正确地连接。在各种按钮方法中放入断点或NSLog语句,您应该能够诊断哪个按钮没有正确连接。不幸的是,正确使用按钮连接方法很难在这样的评论中描述。但是我已经测试了上面的代码,并且它像冠军一样工作,但是我很难远程调试在Interface Builder中连接东西的问题。 – Rob 2012-07-24 15:33:31

相关问题