为什么我得到这个“没有已知类”的警告?

时间:2013-11-01 19:10:54

标签: ios objective-c

我有一个简单的测试应用程序来帮助我学习如何将数据从NSMutableArray持久化到plist。一切似乎都运行良好,直到我尝试通过调用AppDelegate.m文件中名为“saveData”的ViewController方法来保存数据:

- (void)applicationDidEnterBackground:(UIApplication *)application
{

    [ViewController saveData];
}

我得到了一个“没有已知的选择器'saveData'类方法,虽然该方法在ViewController.h中明确声明,如下所示:

//
//  ViewController.h
//  PlistTest
//
//  Created by Tim Jones on 10/30/13.
//  Copyright (c) 2013 TDJ. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController

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

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

@property NSMutableArray *mainActivityArray;



- (IBAction)buttonHit:(id)sender;

-(NSString *) getFilePath;
-(void) saveData;
-(void) loadData;


@end

并在ViewController.m中实现,因此:

//
//  ViewController.m
//  PlistTest
//
//  Created by Tim Jones on 10/30/13.
//  Copyright (c) 2013 TDJ. All rights reserved.
//

#import "ViewController.h"
#import "DataClass.h"

@interface ViewController ()

@end

@implementation ViewController

-(NSString *) getFilePath
{
    NSArray *pathArray = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    return [[pathArray objectAtIndex:0] stringByAppendingPathComponent:@"PlistTestData"];
}

-(void) saveData
{
    [self.mainActivityArray writeToFile: self.getFilePath atomically:YES];
}

我将ViewController.h导入AppDelegate.h。

我很绿,所以我希望这里的问题可能很明显。肯定会得到一些帮助。

3 个答案:

答案 0 :(得分:1)

<强>问题:

[ViewController saveData];

您正在使用类名saveData调用ViewController方法。
但是saveData是一个实例方法,而不是类方法。

-(void) saveData;

<强>修正:

1)将saveData声明为类方法

+(void) saveData;

2)使用saveData的对象调用ViewController

ViewController *vControl = [[ViewController alloc] init];
[vControl saveData];

答案 1 :(得分:0)

以前的答案(Midhun#2)可以使用,但我认为您最好使用应用程序输入背景通知并跳过代理。

只需将其添加到“view did load”:只要应用程序转到后台,它就会调用saveData。

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(saveData)name:UIApplicationDidEnterBackgroundNotification object:nil];

希望这有帮助。

答案 2 :(得分:0)

正如其他人所说,您的问题是[ViewController saveData]方法调用明确暗示您正在尝试拨打“class method”,而您无疑需要调用“实例方法”(因为它是您的视图控制器的实例,其中包含您要保存的数据)。为此,您有两个基本选择:

  1. 您可以让您的应用委托调用视图控制器中的saveData方法。

    在各种评论中,你提到你“试图在每个方面以及在我能想象到的每个地方实例化VC。”别。 Midhun的例子是概念性的,说明了类和实例方法之间的区别。但是,当您想要调用实例方法时,您希望为视图控制器的现有实例调用此方法,而不是实例化新的视图控制器。

    那么,您可能会问,如何获得对视图控制器的现有实例的引用?您要做的是(a)在您的app委托中创建一个属性,以使用saveData方法保存对视图控制器的引用; (b)让视图控制器设置app委托的属性。因此,首先,在app delegate的.h文件中创建一个属性以引用视图控制器:

    @property (weak, nonatomic) ViewController *viewController;
    

    显然,不要忘记.h文件中的#import "ViewController.h"行。

    其次,让视图控制器的viewDidLoad方法更新app delegate的viewController属性:

    - (void)viewDidLoad
    {
        [super viewDidLoad];
    
        AppDelegate *delegate = [[UIApplication sharedApplication] delegate];
        delegate.viewController = self;
    }
    

    同样,不要忘记#import "AppDelegate.h"文件顶部的ViewController.m

    完成后,应用委托的applicationDidEnterBackground现在可以引用您在viewDidLoad中设置的此属性

    - (void)applicationDidEnterBackground:(UIApplication *)application
    {
        [self.viewController saveData];
    }
    

    坦率地说,如果你采用这种技术,我可能会建议进一步改进,特别是采用委托协议模式,但是在你掌握了上述技术之后我会推迟这种对话。

  2. 比以上更简单的方法是完全取消此应用委托代理applicationDidEnterBackground代码,并让您的视图控制器本身响应与应用程序输入后台关联的系统通知。而且,不用说,您将此代码放在视图控制器本身中。

    - (void)viewDidLoad
    {
        [super viewDidLoad];
    
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(saveData) name:UIApplicationDidEnterBackgroundNotification object:nil];
    }
    
    - (void)dealloc
    {
        [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidEnterBackgroundNotification object:nil];
    }
    
    - (void)saveData
    {
        // save your data here
    }
    

    如您所见,我注册观察UIApplicationDidEnterBackgroundNotification中的viewDidLoad,同时确保在dealloc中删除我的观察者。我还确保我的@selector方法名称与我的方法名称完全匹配(例如,在我的示例中,没有参数,因此没有冒号)。

相关问题