Ios NSMutableArray中的奇数自定义对象行为(复制一个对象,删除另一个对象);从NSUserDefaults恢复的

Ios NSMutableArray中的奇数自定义对象行为(复制一个对象,删除另一个对象);从NSUserDefaults恢复的,ios,objective-c,nsmutablearray,nsuserdefaults,Ios,Objective C,Nsmutablearray,Nsuserdefaults,我对Objective-C(以及一般的编码)非常陌生,我正在开发一个iOS项目来熟悉定制对象的持久存储 在开发的第一阶段,一切都进行得很顺利(也要感谢我在StackOverflow上找到的许多答案),直到几天前,当我遇到一个奇怪的行为时,我无法理解也无法解决。我将尽我所能描述这个应用程序并解释我遇到的问题(对不起,英语不是我的主要语言) 应用程序的结构已具有: 权重对象的自定义类(每个对象都有几个属性:NSDate,int表示千克,int表示克,float表示千克,等等) 一个MainView

我对Objective-C(以及一般的编码)非常陌生,我正在开发一个iOS项目来熟悉定制对象的持久存储

在开发的第一阶段,一切都进行得很顺利(也要感谢我在StackOverflow上找到的许多答案),直到几天前,当我遇到一个奇怪的行为时,我无法理解也无法解决。我将尽我所能描述这个应用程序并解释我遇到的问题(对不起,英语不是我的主要语言)

应用程序的结构已具有:

  • 权重对象的自定义类(每个对象都有几个属性:
    NSDate
    ,int表示千克,int表示克,float表示千克,等等)
  • 一个MainViewController,包含一个UIPickerView和两个组件(千克和克),一个“保存选定重量”按钮,用于将当前重量对象(实际上是它的精确副本-我实现了NSCoping协议)添加到
    NSMutableArray
    在索引0处插入它,即“历史记录”按钮,该按钮触发FlipSideViewController的序列和两个标签,显示上次记录的重量及其值的日期
  • 一个
    FlipSideViewController
    ,它包含一个表视图,我在其中加载NSMutableArray的值
  • 还有一个setingsviewcontroller,但它还没有做任何事情,它与这个问题无关(我之所以提到它,是因为我在后面的代码中有一些引用)
我通过
NSUserDefaults
实现了数据持久化,并在我的自定义权重类中添加了
NSCoding
方法(initWithCoder和encodeWithCoder):我对包含自定义权重对象的数组进行编码和解码(
nsKeyedArchivedDataWithRootObject:obj
),因为如果我得到正确的结果,NSUserDefaults不允许存储未在
NSData
中编码的自定义对象

基本的交互已经起作用了:

  • 如果我开始清理,而不恢复以前存储的数据,我可以创建许多新的权重对象,这些对象将添加到NSMutableArray中,并显示在FlipSideViewController的TableView中
  • 即使我恢复了以前记录的数据,一切看起来都很好(但不是,我将在后面解释):
    MainViewController
    中的标签显示了以前记录的最后一个对象的值,PickerView的行与最后选择的值相匹配,
    FlipSideViewController
    中的TableView显示阵列的还原值
但是有一个问题:当我恢复以前的数据(上面第2点)时,即使一切看起来都是正确的,当我点击“保存按钮”添加新记录时,数组中的值也会被弄乱

用一个例子来解释他们是如何搞砸的可能更容易:

假设在第一次训练中,我保存了3个不同的重量值:第一个12,0千克,然后是25,0千克,最后是70,0千克。 然后,TableView在顶部显示70,0 kg,25,0 kg作为第二个值,12,0作为第三个值;MainViewController上的标签明显显示70,0 kg,因为这是最后记录的值。 现在,如果我退出应用程序并再次启动它,在它加载后,一切看起来都与我退出前完全一样:标签显示70,0 kg,TableView以相同的顺序具有相同的3个值。 如果我想通过按下保存按钮添加一个新值,比如说100,5 kg,那么问题就开始了:之后,TableView中显示的值会以我不理解的方式发生变化:从上到下,现在的值是100,5-100,5(是的,它是重复的,而不是显示70,0)、25,0、12,0。

我对这个问题一无所知;当数组的索引被重新创建时,可能会发生一些事情,但我不知道原因和方法

我想为了清晰起见,我最好也提供代码;如果我的变量名和方法名通常是意大利语的,请原谅(我不会再这样做了,我现在意识到,如果我必须用英语提问,最好我的代码也不包含意大利语的痕迹)

我不知道是否应该包含所有代码;由于这种行为对我来说很奇怪,我想问题出在我在其他地方做的某件事上,所以我希望如果我把所有的事情都包括在内,也没关系:

我的自定义类别:比索.h

#import <Foundation/Foundation.h>

@interface Peso : NSObject <NSCopying,NSCoding>

@property int pesoChili;
@property int pesoGrammi;
@property float pesoInChiloGrammi;

@property NSDate * dataPesatura;

@property NSString * pesoChilogrammi;
@property NSString * DataPesaturaStringa;

-(id)initWithCoder:(NSCoder *)aDecoder;

-(void)encodeWithCoder:(NSCoder *)aCoder;

@end
#import "FlipsideViewController.h"
#import "SettingsViewController.h"
#import "Peso.h"

@interface MainViewController : UIViewController <FlipsideViewControllerDelegate,UIPickerViewDataSource,UIPickerViewDelegate,SettingsViewControllerDelegate>

@end
MainViewController.h

#import <Foundation/Foundation.h>

@interface Peso : NSObject <NSCopying,NSCoding>

@property int pesoChili;
@property int pesoGrammi;
@property float pesoInChiloGrammi;

@property NSDate * dataPesatura;

@property NSString * pesoChilogrammi;
@property NSString * DataPesaturaStringa;

-(id)initWithCoder:(NSCoder *)aDecoder;

-(void)encodeWithCoder:(NSCoder *)aCoder;

@end
#import "FlipsideViewController.h"
#import "SettingsViewController.h"
#import "Peso.h"

@interface MainViewController : UIViewController <FlipsideViewControllerDelegate,UIPickerViewDataSource,UIPickerViewDelegate,SettingsViewControllerDelegate>

@end
**FlipsideViewController.h**

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

@class FlipsideViewController;

@protocol FlipsideViewControllerDelegate
- (void)flipsideViewControllerDidFinish:(FlipsideViewController *)controller;
@end

@interface FlipsideViewController : UIViewController <UITableViewDataSource,UITableViewDelegate>

@property (weak, nonatomic) id <FlipsideViewControllerDelegate> delegate;

@property NSMutableArray *cronologiaPeso;

- (IBAction)done:(id)sender;

@end
如果这个问题太长,可能不太清楚,如果我包含了所有代码,请原谅;显然,我在保存或恢复阵列时出错了,但我不知道如何以及在何处。。。或者可能是我保存和恢复数据所遵循的整个模式是错误的,我自学成才,大约一个月前开始编写代码,因此我确信我的逻辑存在严重问题。

提前感谢,


Cesare

我不确定是否正确理解了您的问题,但使用NSUserDefaults时的问题之一可能是因为保存所有数据需要一些时间。它基本上在内部使用一个.plist文件,因此如果您的数据很大,更新的信息可能无法立即使用,例如,如果您希望在表视图上以相同的毫秒显示它

我的建议是在您需要的类中使用一些NSMutableDictionary属性(或者更好地在全局单例对象中使用,因此它在任何地方都可用),并且每当数据更新时,首先更新该dictionary属性,这样视图就会显示正确的数据。之后,您还可以将更改保存在NSUserDefaults中。此外,良好的做法是使用[[NSUserDefaults standardUserDefaults]同步]


我希望它能对您有所帮助:)

看起来像是我遇到的问题,为此我发布了这个问题(将一个对象添加到从NSUserDefaults还原的NSMutableArray中会导致一个奇怪的错误
#import "FlipsideViewController.h"

@interface FlipsideViewController ()

@end

@implementation FlipsideViewController{
    NSUserDefaults *defaults;
}


-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    return self.cronologiaPeso.count;
}


-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cella" forIndexPath:indexPath];

    Peso * currentPeso = [self.cronologiaPeso objectAtIndex:indexPath.row];

    cell.textLabel.text = currentPeso.pesoChilogrammi;

    cell.detailTextLabel.text = currentPeso.DataPesaturaStringa;

    return cell;

}

// NOT YET IMPLEMENTED
//-(BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
//    return YES;
//}
//
//
//-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath{
//    if (editingStyle == UITableViewCellEditingStyleDelete) {
//        [self.cronologiaPeso removeObjectAtIndex:indexPath.row];
//        [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
////        [defaults synchronize]
//    }
//}


- (void)viewDidLoad
{
    [super viewDidLoad];        
}


- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
}


#pragma mark - Actions

- (IBAction)done:(id)sender
{
    [self.delegate flipsideViewControllerDidFinish:self];
}

@end
if ([[[NSUserDefaults standardUserDefaults] dictionaryRepresentation].allKeys containsObject:kPercorso]) {

    cronologiaPeso = [[NSMutableArray alloc]initWithArray:[self caricaCronologiaPesoCodificatoConKey:kPercorso]];

/...
//...

cronologiaPeso = [[NSMutableArray alloc]initWithArray:[self caricaCronologiaPesoCodificatoConKey:kPercorso] copyItems:YES];

//...