无法从AppDelegate调用变量

时间:2014-06-26 15:00:21

标签: ios objective-c

我的AppDelegate.m中有一个名为message的变量,我想在视图控制器中使用它,但它不起作用。我试过这个解决方案:

  • 如果我将AppDelegate.m导入我的ViewController.m,我会收到错误:clang: error: linker command failed with exit code 1 (use -v to see invocation),但如果我不导入它,我会收到:No known class method for selector 'message'此处line:self.toSort = [AppDelegate message];。但是当我将ViewController.m导入AppDelegate.m时,我没有收到链接器命令错误,但是其他错误已经存在。

我的AppDelegate.h

@property (strong, nonatomic) UIWindow *window;
@property (nonatomic, strong) PNChannel *myChannel;
- (void)getMessage;


AppDelegate.m
#import "AppDelegate.h"
#import "ViewController.m"

static NSArray *_message = nil;

@implementation AppDelegate 

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
 //   [self.window makeKeyAndVisible];   
    self.myChannel = [PNChannel channelWithName:currentChannel.username
         shouldObservePresence:YES];

    [self getMessage];

}   
+ (NSArray *)message
{
    if (_message)
        return _message;

    AppDelegate *appDelegate =(AppDelegate *)[[UIApplication sharedApplication] delegate];
    [appDelegate getMessage];

    return nil;
}

- (void)getMessage {

    [PubNub requestFullHistoryForChannel:self.myChannel withCompletionBlock:^(NSArray *contentArray, PNChannel *channel, PNDate *fromDate, PNDate *toDate, PNError *error) {

        _message = contentArray;
        NSLog(@"test log %@", _message);   
    }];
}

ViewController.m

#import "ViewController.h"

//#import "AppDelegate.h"
//#import "AppDelegate.m"

@interface ViewController ()

@end

@implementation ViewController


- (void)viewDidLoad
{
    [super viewDidLoad];

}

- (void)viewWillAppear:(BOOL)animated {

    //AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];

    //[appDelegate getMessage];

    self.toSort = [AppDelegate message];
    [self getMessageList];

}

我确定我做了一些初学者的错误,但我无法理解。 “测试日志”有效,所以我认为我必须以不同的方式调用它。

已经尝试过这个,但也会收到错误,因为邮件不是属性。

AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSArray *variableTest = appDelegate.message;
NSLog(@"TEST : %@",variableTest);

更新:我试过这个,但测试日志显示为null,所以有些事情仍然是错误的。

AppDelegate.h

@property (strong, nonatomic) UIWindow *window;
@property (nonatomic, strong) PNChannel *myChannel;
@property (strong, nonatomic) NSArray *message;
- (void)getMessage;

AppDelegate.m

#import "AppDelegate.h"

@implementation AppDelegate 

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{    
 //   [self.window makeKeyAndVisible];
    self.myChannel = [PNChannel channelWithName:currentChannel.username
         shouldObservePresence:YES];

    [self getMessage];

    }
    return YES;
}

+ (NSArray *)message
{
    if (self.message)
        return self.message;

    AppDelegate *appDelegate =(AppDelegate *)[[UIApplication sharedApplication] delegate];
    [appDelegate getMessage];

    return nil;
}

- (void)getMessage {

    [PubNub requestFullHistoryForChannel:self.myChannel withCompletionBlock:^(NSArray *contentArray, PNChannel *channel, PNDate *fromDate, PNDate *toDate, PNError *error) {

         self.message = contentArray;

         NSLog(@"dev log %@", self.message);
    }];
}

ViewController.m

- (void)viewWillAppear:(BOOL)animated {


    AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
    NSArray *variableTest = appDelegate.message;
    NSLog(@"TEST : %@",variableTest);


}

我的尝试基于o Pi的回答:

@interface MessageHistoryData : NSObject {
    NSArray *yourData;
}
@property(nonatomic,retain) NSArray *yourData;
+(MessageHistoryData *)getInstance;

@end

#import "MessageHistoryData.h"

@implementation MessageHistoryData @synthesize yourData;
static MessageHistoryData *instance =nil;
+(MessageHistoryData *)getInstance {
    @synchronized(self) {
        if(instance==nil) {
            instance= [MessageHistoryData new];
        }
    }
    return instance;
}

@end

在我的ViewController.m中(MessageHistoryData导入.h)

- (void)setupArray {

[PubNub requestHistoryForChannel:my_channel from:nil to:nil limit:100 reverseHistory:NO withCompletionBlock:^(NSArray *contentArray, PNChannel *channel, PNDate *fromDate, PNDate *toDate, PNError *error) {

        MessageHistoryData *data = [MessageHistoryData getInstance];

        data.yourData = contentArray;

        NSLog(@"Dev log2 %@", data.yourData);


}];

}

8 个答案:

答案 0 :(得分:4)

我设置了一个示例项目来验证这是否有效。

在AppDelegate.h文件中,公开声明message属性和-getMessage方法:

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;
@property (readonly, nonatomic) NSString *message;

- (void)getMessage;

@end

在AppDelegate.m文件中,像往常一样实现你的方法(我为了举例明确地设置了属性):

#import "AppDelegate.h"

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    return YES;
}

- (void)getMessage {
    self.message = @"This is a message";
}

@end

ViewController.m文件中,您应该导入AppDelegate标头,您应该可以自由访问这些属性:

#import "AppDelegate.h"
#import "ViewController.h"

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    AppDelegate *delegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
    NSLog(@"The delegate's message is: %@", delegate.message);  // Logs "The delegate's message is: (null)"
    [delegate getMessage];
    NSLog(@"The delegate's message is: %@", delegate.message);  // Logs "The delegate's message is: This is a message"
}

@end

如果上述方法无效,您应该测试PubNub课程并确保其行为可预测。

我不建议永久存储AppDelegate中的信息,因为这使得该课程不仅仅是作为您的应用程序的系统委托。这样的信息应存储在专用存储中,或通过自定义PubNub子类提供,该子类作为单例访问(如果没有要管理的全局状态!)或逐个实例

如果您需要任何澄清或上述解决方案对您不起作用,请告诉我。

编辑:单身人士建议

根据我的评论,这是处理跨视图控制器共享网络数据的一种方法

@interface NetworkClient : PubNub

@property (readonly, nonatomic) NSString *message;

/**
 *  Returns a shared network client to be used throughout the app
 */
+ (instancetype)sharedClient;  

- (void)configureWithChannel:(PNChannel*)channel;
- (void)clearChannel;

- (void)getMessagesWithCompletionHandler:(void (^)(NSArray *, PNChannel *, PNDate *, PNDate *, PNError *))

@end

其中sharedInstance使用technique described here来设置您的实例。从那里,您可以使用[NetworkClient sharedClient]访问客户端,并通过客户端上的实例方法或属性检索任何数据。

我也猜测你是新手单身人士或iOS的新手,所以我建议你阅读this article关于使用单身人士的信息,以及博客objc.io来熟悉自己有一些绝对会让你的生活更轻松的最佳实践。

答案 1 :(得分:2)

首先,不需要声明变量static,因为[UIApplication sharedAppliction] delegate]将始终是同一个实例。所以只需在AppDelegate.h文件中声明一个属性并使用它。

AppDelegat.h中的

@property(nonatomic, strong) NSArray *message;
AppDelegate.m中的

使用它:

self.message

在您的视图控制器中导入.h并执行:

AppDelegate *appDelegate =(AppDelegate *)[[UIApplication sharedApplication] delegate];
NSArray *arr = appDelegate.message;

答案 2 :(得分:1)

您必须将公共变量放入头文件中。

答案 3 :(得分:1)

您的getMessage方法使用异步调用来获取消息。如果您无法以同步方式检索它,则可以尽快致电getMessage

更好的是,您还可以使用块来返回消息异步:

+ (void)asyncMessage:(void(^)(NSArray * message))callbackBlock
{
    if (_message)
    {
        callbackBlock(_message);
        return;
    }

    [PubNub requestFullHistoryForChannel:self.myChannel withCompletionBlock:^(NSArray *contentArray, PNChannel *channel, PNDate *fromDate, PNDate *toDate, PNError *error) {

        _message = contentArray;
        callbackBlock(_message);
        NSLog(@"test log %@", _message);
    }];
}

答案 4 :(得分:1)

永远不会在xcode中导入.m类,因为这会抛出cling:error。 如果你想在NSArray中定义的appdelegate稍后在你的任何视图控制器中使用,可能会有很多方法。其中一些是 -

  1. appdelegate.h中像这样启动你的数组

    @property(nonatmoic,retain)nsarray *message;
    

    然后在appdelegate.m类的didfinishlaunchingwithOptions类中为此数组分配内存 -

    message=[[nsarray alloc]initwithobjects:@"abc"];
    

    然后在你的视图控制器中创建app委托对象并访问此属性,如下所示 -

    NSLog(@"array is %@",appdelegateobject.message);
    
  2. 在你的第一个问题中,你试图通过类方法返回这个数组,但是在appdelegate中你返回nil,那么你将如何得到这个消息数组,

答案 5 :(得分:0)

获取消息变量并将其粘贴到.h中,然后从.m

中删除它

答案 6 :(得分:0)

您无法像这样在工具文件中导入工具文件。

AppDelegate.m
#import "AppDelegate.h"
#import "ViewController.m"  // This is the reason causes error.

我之前犯过这个错误....

像这样修改很容易解决这个问题。

AppDelegate.m
#import "AppDelegate.h"
#import "ViewController.h"  

答案 7 :(得分:-1)

您需要将消息数组的属性设为公开

AppDelegate.h

@property (strong, nonatomic) NSArray *message;

希望它可以帮助你..