如何从现有对象的不同类调用方法(Obj C)

Posted

技术标签:

【中文标题】如何从现有对象的不同类调用方法(Obj C)【英文标题】:How do I call a method from a different class on an existing object (Obj C) 【发布时间】:2013-03-15 11:51:14 【问题描述】:

我是 Objective C 和 Xcode 的新手,可能只是做一些愚蠢的错误,但我尝试了很多不同的建议,但无法让它们发挥作用。

简而言之,当在不同的 UIViewController 中按下按钮时,我想调用现有 UIViewController 上的方法。

(有点背景:两个屏幕是一个主屏幕和一个菜单屏幕。用户向上滑动查看菜单,然后当完成按钮按下我希望菜单屏幕将字符串变量(在本例中为 URL)发送到主屏幕中的方法,然后主屏幕在 UIWebView 中显示 URL。

我尝试将方法/URL 变量放入 AppDelegate/MainViewController 并合成它们。我还尝试使 MenuViewController 成为 MainViewCONtroller 的子类并使用 [super readFile:url] 调用该方法,该方法确实编译但我认为它没有调用现有的 MainViewController 对象,因为 webview 没有出现。

我将在下面粘贴我的代码的相关部分:(感谢您的帮助!)

MainViewController.h

#import <UIKit/UIKit.h>

@interface MainViewController : UIViewController 
IBOutlet UIWebView *vCodeView;


- (void)readFile:(NSString *)newURL;

@end

MainViewController.m

#import "MainViewController.h"
#import "MenuViewController.h"

@interface MainViewController ()

@end

@implementation MainViewController

- (void)readFile:(NSString *)newURL 
    vCodeView.hidden = NO;

    // seperate url by full stops
    NSArray *splitURL = [newURL componentsSeparatedByString:@"."];
    // find extension of file
    NSString *extension = [splitURL objectAtIndex:([splitURL count]-1)];

    // DO SOME OTHER STUFF WITH URL THEN DISPLAY CONTENT IN UIWEBVIEW


- (void)swipeUpRecognised 
    MenuViewController *menuView = [[MenuViewController alloc] initWithNibName:@"MenuViewController" bundle:nil];
    menuView.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
    [self presentViewController:menuView animated:YES completion:nil];

MenuViewController.h

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

@interface MenuViewController : UIViewController 
    IBOutlet UIBarButtonItem *bDone;
    IBOutlet UITextField *fUser;
    IBOutlet UITextField *fPass;
    IBOutlet UITextField *fAddress;
    IBOutlet UITextField *fAutoConnectAddress;


- (IBAction)bDonePressed;

@end

MenuViewController.m

#import "MenuViewController.h"
#import "MainViewController.h"

@interface MenuViewController ()

@end

@implementation MenuViewController

- (IBAction)bDonePressed 

    NSString *user = @"admin";
    NSString *pass = @"password";
    NSString *path = @"54.246.90.95/repos/project1/trunk/dir1/test.c";

    // url of file
    NSArray *pathArray = [[NSArray alloc] initWithObjects:@"http://", user, @":", pass, @"@", path, nil];
    NSString *url = [pathArray componentsJoinedByString:@""];

    //call the method here passing in url

    [self dismissViewControllerAnimated:YES completion:nil];

【问题讨论】:

在 appdelegate.m 文件中声明你的方法,而不是从你的类中调用 @keyur 这是一个非常糟糕的主意。这会让他的视图控制器知道他的应用程序委托中的方法。 你的实现中的一个小错误:你通常会有[self.presentingViewController dismissViewControllerAnimated:YES completion:nil]; 【参考方案1】:

在这种特殊情况下,您可以在dismissViewControllerAnimated 调用之前输入以下内容,它应该可以工作:

if(self.presentingViewController && [self.presentingViewController respondsToSelector:@selector(readFile:)]) 
    [(id)self.presentingViewController readFile:url];

一般来说,你真正想要的是Delegation。

所以,为了更简洁的实现,试试这个:

MenuViewController.h

@protocol MenuViewControllerDelegate <NSObject>
    - (void)menuViewControllerFinishedWithURL:(NSURL *)url;
@end

@interface MenuViewController : UIViewController 
    @property id<MenuViewControllerDelegate> delegate;
// ...

MenuViewController.m

- (IBAction)bDonePressed 
    // ...

    if(self.delegate) 
        [self.delegate menuViewControllerFinishedWithURL:url];
    

    [self.presentingViewController dismissViewControllerAnimated:YES completion:nil];

MainViewController.m

@interface MainViewController () <MenuViewControllerDelegate>

@end

// ...

- (void)swipeUpRecognised 
    MenuViewController *menuView = [[MenuViewController alloc] initWithNibName:@"MenuViewController" bundle:nil];
    menuView.delegate = self;
    menuView.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
    [self presentViewController:menuView animated:YES completion:nil];

【讨论】:

非常感谢!这几天我一直在尝试不同的解决方案! :)【参考方案2】:

为了调用 MainViewController 方法,应该很简单:

    将 MainViewController.h 包含到 MenuViewController.h 中。

    在你想要的地方调用这个 sn-p:

    NSString * vcid = @""; //put id you have assigned to your MainViewController. This should be in your storyboard. If it is empty, fill it with proper name, then use it here.
    UIStoryboard *storybord = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
    MainViewController *mainvc =[storybord instantiateviewcontrollerwithidentifier:vcid];
    [mainvc method];
    

注意method 必须在 MainViewController.h 文件中声明才能被调用。

也就是说,我想知道您是否真的需要为菜单设置单独的视图控制器。如果您想为用户提供一组按钮以供选择,请考虑包含所有按钮的 UIView。这个 UIView 应该会在你的swipeUpRecognised 中弹出。

【讨论】:

对不起,我可能应该提一下,我使用的是 .xib 而不是故事板。不管怎么说,还是要谢谢你! :) 即使在那里你也应该能够指定这个属性。只需选择视图控制器,然后查看属性检查器显示的内容。【参考方案3】:

此代码将适用于您... 像这样修改你的代码....

MainViewController.h

#import <UIKit/UIKit.h>

@interface MainViewController : UIViewController 
IBOutlet UIWebView *vCodeView;


- (void)readFile:(NSString *)newURL;

@end

MainViewController.m

#import "MainViewController.h"
#import "MenuViewController.h"

@interface MainViewController ()

@end

@implementation MainViewController

- (void)readFile:(NSString *)newURL 
    vCodeView.hidden = NO;

    // seperate url by full stops
    NSArray *splitURL = [newURL componentsSeparatedByString:@"."];
    // find extension of file
    NSString *extension = [splitURL objectAtIndex:([splitURL count]-1)];

    // DO SOME OTHER STUFF WITH URL THEN DISPLAY CONTENT IN UIWEBVIEW


- (void)swipeUpRecognised 
    MenuViewController *menuView = [[MenuViewController alloc] initWithNibName:@"MenuViewController" bundle:nil];
menuView.delegate = self;
    menuView.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
    [self presentViewController:menuView animated:YES completion:nil];

MenuViewController.h

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

@interface MenuViewController : UIViewController 
    IBOutlet UIBarButtonItem *bDone;
    IBOutlet UITextField *fUser;
    IBOutlet UITextField *fPass;
    IBOutlet UITextField *fAddress;
    IBOutlet UITextField *fAutoConnectAddress;

@property(nonatomic, retain) MainViewController *delegate;
- (IBAction)bDonePressed;

@end

MenuViewController.m

#import "MenuViewController.h"
#import "MainViewController.h"

@interface MenuViewController ()

@end

@implementation MenuViewController
@synthesize delegate = _delegate;
- (IBAction)bDonePressed 

    NSString *user = @"admin";
    NSString *pass = @"password";
    NSString *path = @"54.246.90.95/repos/project1/trunk/dir1/test.c";

    // url of file
    NSArray *pathArray = [[NSArray alloc] initWithObjects:@"http://", user, @":", pass, @"@", path, nil];
    NSString *url = [pathArray componentsJoinedByString:@""];

    //call the method here passing in url
    [self.delegate readFile:url];

    [self dismissViewControllerAnimated:YES completion:nil];

【讨论】:

以上是关于如何从现有对象的不同类调用方法(Obj C)的主要内容,如果未能解决你的问题,请参考以下文章

如何继承从一个基类继承的不同类的特定变量?

如何从已在其中创建的不同类对象中访问类对象的成员函数?

C# 一个列表中的不同类对象

从 C# 调用 C++ dll 方法/类

什么是反射?

GC.SuppressFinalize()的正确用法