简体   繁体   English

为什么会收到“未知班级”警告?

[英]Why am I getting this “No known class” warning?

I have a simple test app to help me learn how to persist data from a NSMutableArray to a plist. 我有一个简单的测试应用程序,可以帮助我学习如何将数据从NSMutableArray持久化到plist。 Everything seems to be working well, until I try to save the data by calling a ViewController method called "saveData" in my AppDelegate.m file: 一切似乎都运行良好,直到我尝试通过在AppDelegate.m文件中调用一个名为“ saveData”的ViewController方法来保存数据之前:

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

    [ViewController saveData];
}

I get a "No known class method for selector 'saveData', although the method is clearly declared in ViewController.h, like so: 我得到了“选择器'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

and implemented in ViewController.m, thusly: 并在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];
}

I imported the ViewController.h into AppDelegate.h. 我将ViewController.h导入AppDelegate.h。

I'm pretty green, so I expect the problem may be obvious to many here. 我很绿,所以我希望问题对于这里的许多人来说可能是显而易见的。 Would sure appreciate some help. 希望能得到一些帮助。

Issue: 问题:

[ViewController saveData];

You are calling saveData method using class name ViewController . 您正在使用类名称ViewController调用saveData方法。
But saveData is an instance method, not class method. 但是saveData是实例方法,而不是类方法。

-(void) saveData;

Fixes: 修正:

1) Declare saveData as class method 1)将saveData声明为类方法

+(void) saveData;

2) Call saveData using the object of ViewController . 2)使用ViewController的对象调用saveData

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

Previous answer (Midhun #2) can work, but I think you would be better off using the Application Did Enter Background Notification and skip the delegate. 先前的答案(Midhun#2)可以工作,但我认为使用“应用程序确实输入后台通知”并跳过委托会更好。

Just add this to "view did load": it will call saveData whenever the app goes to background. 只需将其添加到“视图确实已加载”:只要应用程序进入后台,它将调用saveData。

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(saveData) name:UIApplicationDidEnterBackgroundNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:自我选择器:@selector(saveData)名称:UIApplicationDidEnterBackgroundNotification对象:无];

Hope this helps. 希望这可以帮助。

As others have noted, your issue is that your [ViewController saveData] method invocation clearly suggests that you're trying to call a " class method ", and you undoubtedly want to call your "instance method" (because it's your instance of your view controller that has the data you want to save). 正如其他人指出的那样,您的问题是[ViewController saveData]方法调用明确表明您正在尝试调用“ 类方法 ”,并且无疑要调用“实例方法”(因为这是您的视图实例)具有您要保存的数据的控制器)。 To achieve that, you have two basic choices: 为此,您有两个基本选择:

  1. You can have your app delegate call the saveData method in your view controller. 您可以让您的应用程序委托在视图控制器中调用saveData方法。

    In various comments, you mention that you've "tried instantiating the VC every way and in every place I can imagine." 在各种评论中,您提到您“尝试过以我能想象的所有方式实例化VC”。 Don't. 别。 Midhun's example was a conceptual one, illustrating the difference between a class and instance method. Midhun的示例是一个概念性示例,说明了类方法和实例方法之间的区别。 But, while you want to call the instance method, you want to call this for your existing instance of your view controller, definitely not instantiating a new view controller. 但是,当您要调用实例方法时,您想为视图控制器的现有实例调用此方法,绝对不要实例化新的视图控制器。

    So, you may ask, how do you get a reference to the existing instance of your view controller? 因此,您可能会问,如何获得对视图控制器的现有实例的引用? What you'll want to do is to (a) create a property in your app delegate to hold the reference to the view controller with the saveData method; 您要做的是(a)在应用程序委托中创建一个属性,以使用saveData方法保存对视图控制器的saveData (b) have that view controller set that property of the app delegate. (b)让该视图控制器设置应用程序委托的该属性。 So, first, create a property in your app delegate's .h file to reference the view controller: 因此,首先,在您的应用程序委托的.h文件中创建一个属性以引用视图控制器:

     @property (weak, nonatomic) ViewController *viewController; 

    Obviously, don't forget the #import "ViewController.h" line early in the .h file. 显然,不要忘记在.h文件中的#import "ViewController.h"行。

    Second, have the viewDidLoad method of the view controller update the app delegate's viewController property: 其次,让视图控制器的viewDidLoad方法更新应用程序委托的viewController属性:

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

    Again, don't forget to #import "AppDelegate.h" at the top of your ViewController.m file. 同样,不要忘记在ViewController.m文件顶部#import "AppDelegate.h"

    Having done that, then app delegate's applicationDidEnterBackground can now reference this property that you set in viewDidLoad 完成此操作后,应用程序委托的applicationDidEnterBackground现在可以引用您在viewDidLoad设置的此属性。

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

    Frankly, if you did this technique, I might suggest further refinements, notably employing a delegate-protocol pattern, but I'm going to defer that conversation until after you have mastered the above technique. 坦白说,如果您使用了这种技术,我可能会建议您进一步完善,尤其是采用委托协议模式,但是我将把讨论推迟到您掌握了上述技术之后。

  2. Even easier than the above is to eliminate this app delegate applicationDidEnterBackground code altogether, and just have your view controller, itself, respond to the system notification that is associated with the app entering background. 比上述方法更容易的是,完全消除此应用程序委托applicationDidEnterBackground代码,只让您的视图控制器本身响应与应用程序进入后台相关的系统通知。 And, needless to say, you put this code right in the view controller itself. 而且,不用说,您可以将此代码直接放在视图控制器中。

     - (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 } 

    As you can see, I register to observe UIApplicationDidEnterBackgroundNotification in viewDidLoad , but also make sure to remove my observer in dealloc . 如您所见,我在viewDidLoad注册以观察UIApplicationDidEnterBackgroundNotification ,但还要确保在dealloc删除观察者。 I also made sure that my @selector method name exactly matched my method name (eg, in my example, no parameters, and hence no colon). 我还确保我的@selector方法名称与我的方法名称完全匹配(例如,在我的示例中,没有参数,因此也没有冒号)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么我会收到UIBarButtonItem自定义警告? - Why am I getting an UIBarButtonItem customization warning? 为什么会收到此编译器警告? - Why am I getting this compiler warning? 为什么我会收到“标题集但使用系统标识符”警告? - Why am I getting a “Title set but using a system Identifier” warning? 为什么会收到“未使用表达式结果”警告? - Why am I getting an 'Expression Result Unused' warning? 我在Xcode for iOS中得到了“枚举类型的隐式转换”警告,我不知道为什么 - I am getting an “Implicit conversion from enumeration type” warning in Xcode for iOS and I don't know why 为什么我收到CIFilter的“无法识别的选择器发送给类”错误? - Why am I getting an “unrecognized selector sent to class” error for CIFilter? 为什么我会收到发送到 class 的无法识别的选择器? - Why am I getting unrecognized selector sent to class? 为什么我在Objective-C的枚举中收到类型冲突警告? - Why am I getting a type conflict warning on my enum in Objective-C? 为什么我从Xcode收到此警告? iOS代码似乎很好 - Why am I getting this warning from Xcode? The iOS code seems fine 为什么在显示我的自定义 UIAlert 时会收到 Nil Layout Anchor 警告? - Why am I getting Nil Layout Anchor warning while presenting my custom UIAlert?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM