Ios -[NSDictionary initWithObjects:forKeys:]:对象计数(0)与键计数(2)不同

Ios -[NSDictionary initWithObjects:forKeys:]:对象计数(0)与键计数(2)不同,ios,objective-c,plist,nsdictionary,Ios,Objective C,Plist,Nsdictionary,我得到的错误是 -[NSDictionary initWithObjects:forKeys:]:对象计数(0)与键计数(2)不同” 这是我保存plist的代码 @interface setting : UIViewController{ UIDatePicker *datePicker; IBOutlet UILabel * morningtime; UIDatePicker *afternoonpicker; NSString*morningtime1

我得到的错误是

-[NSDictionary initWithObjects:forKeys:]:对象计数(0)与键计数(2)不同”

这是我保存plist的代码

    @interface setting : UIViewController{
    UIDatePicker *datePicker;
    IBOutlet UILabel * morningtime;
    UIDatePicker *afternoonpicker;
    NSString*morningtime1;
    NSString*afternoontime1;
     IBOutlet UILabel *afternoontime;
}
@property (nonatomic,retain) IBOutlet UIDatePicker *datePicker;
@property (strong, nonatomic) IBOutlet UIDatePicker *afternoonpicker;

@property (nonatomic, retain) IBOutlet NSString *morningtime1;

@property (nonatomic, retain) IBOutlet NSString *afternoontime1;
@property (nonatomic, retain) IBOutlet UILabel *morningtime;

@property (nonatomic, retain) IBOutlet UILabel *afternoontime;
@property (weak, nonatomic) IBOutlet UIButton *morning;




- (IBAction)savetext:(id)sender {
    NSArray *paths = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES);
    // get documents path
    NSString *documentsPath = [paths objectAtIndex:0];
    // get the path to our Data/plist file
    NSString *plistPath = [documentsPath stringByAppendingPathComponent:@"Data.plist"];

    self.morningtime1 = morningtime.text;
    self.afternoontime1 = afternoontime.text;
    NSDictionary *plistDict = [NSDictionary dictionaryWithObjects: [NSArray arrayWithObjects: morningtime1, afternoontime1, nil] forKeys:[NSArray arrayWithObjects: @"Morning", @"Afternoon", nil]];

    NSString *error = nil;
    // create NSData from dictionary
    NSData *plistData = [NSPropertyListSerialization dataFromPropertyList:plistDict format:NSPropertyListXMLFormat_v1_0 errorDescription:&error];

    // check is plistData exists
    if(plistData)
    {
        // write plistData to our Data.plist file
        [plistData writeToFile:plistPath atomically:YES];
    }
    else
    {
        NSLog(@"Error in saveData: %@", error);
    }
}

morningtime1
在这里几乎肯定是
nil
,过早地结束了数组列表

如果在此处使用新的数组文字语法:

@[morningtime1, afternoontime1];
您将获得崩溃,因为将nil分配给
NSArray
元素是非法的

这一行:

NSDictionary *plistDict = [NSDictionary dictionaryWithObjects: [NSArray arrayWithObjects: morningtime1, afternoontime1, nil] forKeys:[NSArray arrayWithObjects: @"Morning", @"Afternoon", nil]];
应该是:

NSDictionary *plistDict = [NSDictionary dictionaryWithObjects: [NSArray arrayWithObjects: self.morningtime1, self.afternoontime1, nil] forKeys:[NSArray arrayWithObjects: @"Morning", @"Afternoon", nil]];
换句话说,引用属性,而不是IVAR。如您所知,从未设置
morningtime1
ivar(您设置的属性实际上是设置名为
\u morningtime1
的生成的ivar)

旁注:


去掉所有显式IVAR和属性的
@synthesis
行。这将避免这种混淆。

为什么不
午后1
nil?因为对象的计数为零。(午后1也可以是零,但你永远不会走那么远。)嗯,
午后1
也可以是零,但如果数组计数为0,这意味着列表中的第一项将终止列表。你们没有说明ivar为零的原因。ivar可能为零至少有三种不同的原因,但是确定它是nil,并且将nil变量传递到varargs列表中会导致意外的结果,似乎是这里最突出的一点-为什么?
morningtime1
ivar为零,因为它从未设置过。通过将代码更改为使用属性,问题就消失了。我不是您的反对者,我同意这些都是好的做法,但这里无法保证使用ivar引用是问题所在。为什么
NSString
属性标记为
IBOutlet
?这是没有理由的。