Ios NSMutableArray中的奇数自定义对象行为(复制一个对象,删除另一个对象);从NSUserDefaults恢复的
我对Objective-C(以及一般的编码)非常陌生,我正在开发一个iOS项目来熟悉定制对象的持久存储 在开发的第一阶段,一切都进行得很顺利(也要感谢我在StackOverflow上找到的许多答案),直到几天前,当我遇到一个奇怪的行为时,我无法理解也无法解决。我将尽我所能描述这个应用程序并解释我遇到的问题(对不起,英语不是我的主要语言) 应用程序的结构已具有:Ios NSMutableArray中的奇数自定义对象行为(复制一个对象,删除另一个对象);从NSUserDefaults恢复的,ios,objective-c,nsmutablearray,nsuserdefaults,Ios,Objective C,Nsmutablearray,Nsuserdefaults,我对Objective-C(以及一般的编码)非常陌生,我正在开发一个iOS项目来熟悉定制对象的持久存储 在开发的第一阶段,一切都进行得很顺利(也要感谢我在StackOverflow上找到的许多答案),直到几天前,当我遇到一个奇怪的行为时,我无法理解也无法解决。我将尽我所能描述这个应用程序并解释我遇到的问题(对不起,英语不是我的主要语言) 应用程序的结构已具有: 权重对象的自定义类(每个对象都有几个属性:NSDate,int表示千克,int表示克,float表示千克,等等) 一个MainView
- 权重对象的自定义类(每个对象都有几个属性:
,int表示千克,int表示克,float表示千克,等等)李>NSDate
- 一个MainViewController,包含一个UIPickerView和两个组件(千克和克),一个“保存选定重量”按钮,用于将当前重量对象(实际上是它的精确副本-我实现了NSCoping协议)添加到
在索引0处插入它,即“历史记录”按钮,该按钮触发FlipSideViewController的序列和两个标签,显示上次记录的重量及其值的日期李>NSMutableArray
- 一个
,它包含一个表视图,我在其中加载NSMutableArray的值FlipSideViewController
- 还有一个setingsviewcontroller,但它还没有做任何事情,它与这个问题无关(我之所以提到它,是因为我在后面的代码中有一些引用)
NSUserDefaults
实现了数据持久化,并在我的自定义权重类中添加了NSCoding
方法(initWithCoder和encodeWithCoder):我对包含自定义权重对象的数组进行编码和解码(nsKeyedArchivedDataWithRootObject:obj
),因为如果我得到正确的结果,NSUserDefaults不允许存储未在NSData
中编码的自定义对象
基本的交互已经起作用了:
- 如果我开始清理,而不恢复以前存储的数据,我可以创建许多新的权重对象,这些对象将添加到NSMutableArray中,并显示在FlipSideViewController的TableView中
- 即使我恢复了以前记录的数据,一切看起来都很好(但不是,我将在后面解释):
中的标签显示了以前记录的最后一个对象的值,PickerView的行与最后选择的值相匹配,MainViewController
中的TableView显示阵列的还原值FlipSideViewController
#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];
//...