将数据保存到现有plist

时间:2013-05-09 13:47:01

标签: xcode uitableview ios6 plist

我正在开发一个带有详细视图的简单表视图的项目。

数据源是plist 。我试图允许用户输入保存到plist中并显示在tableview中。我创建了一个添加视图控制器,它以模态方式显示和解除,并有两个文本字段,允许用户添加城市名称和状态名称,还有一个文本字段输入描述。

问题:如何将此数据保存到现有的plist并在tableview中显示。这是我的表视图代码:

@implementation TableViewController

@synthesize content, searchResults;



- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
    // Custom initialization
}
return self;
}

- (void)viewDidLoad
{
[super viewDidLoad];

content = [[NSArray alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"Data" ofType:@"plist"]];
}

- (IBAction)add;
{
AddViewController* controller = [[AddViewController alloc] init];
[self presentViewController:controller animated:YES completion:nil];
}

- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{

if (tableView == self.searchDisplayController.searchResultsTableView) {
    return [self.searchResults count];

} else {
    return [self.content count];

}
}

- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{

NSPredicate *resultPredicate = [NSPredicate predicateWithFormat: @"SELF['city'] BEGINSWITH[c] %@ ", searchText];

searchResults = [[content filteredArrayUsingPredicate:resultPredicate] retain];
}

-(BOOL)searchDisplayController:(UISearchDisplayController *)controller shouldReloadTableForSearchString:(NSString *)searchString
{
[self filterContentForSearchText:searchString
                           scope:[[self.searchDisplayController.searchBar scopeButtonTitles]
                                  objectAtIndex:[self.searchDisplayController.searchBar
                                                 selectedScopeButtonIndex]]];

return YES;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
    cell = [[[UITableViewCell alloc] initWithStyle: UITableViewCellStyleDefault reuseIdentifier: CellIdentifier] autorelease];
}

if (tableView == self.searchDisplayController.searchResultsTableView) {
    cell.textLabel.text = [[searchResults objectAtIndex:indexPath.row] valueForKey:@"city"];
    cell.detailTextLabel.text = [[searchResults objectAtIndex:indexPath.row] valueForKey:@"state"];
    cell.imageView.image = [UIImage imageNamed:[[self.searchResults objectAtIndex:indexPath.row] valueForKey:@"cityImage"]];
} else {
    cell.textLabel.text = [[self.content objectAtIndex:indexPath.row] valueForKey:@"city"];
    cell.detailTextLabel.text = [[self.content objectAtIndex:indexPath.row] valueForKey:@"state"];
    cell.imageView.image = [UIImage imageNamed:[[self.content objectAtIndex:indexPath.row] valueForKey:@"cityImage"]];

}

return cell;
}



- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (tableView == self.searchDisplayController.searchResultsTableView) {
    [self performSegueWithIdentifier: @"showDetails" sender: self];
}
}

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender

{

if ([segue.identifier isEqualToString:@"showDetails"]) {

    NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
    DetailViewController *DVC = [segue destinationViewController];

    if ([self.searchDisplayController isActive]) {

        DVC.cityImageString = [[searchResults objectAtIndex:indexPath.row] valueForKey:@"cityImage"];
        DVC.cityTextString = [[searchResults objectAtIndex:indexPath.row] valueForKey:@"cityText"];
        DVC.cityNameString = [[searchResults objectAtIndex:indexPath.row] valueForKey:@"city"];
        DVC.stateNameString = [[searchResults objectAtIndex:indexPath.row] valueForKey:@"state"];
    } else {

        DVC.cityImageString = [[self.content objectAtIndex:indexPath.row] valueForKey:@"cityImage"];
        DVC.cityTextString = [[self.content objectAtIndex:indexPath.row] valueForKey:@"cityText"];
        DVC.cityNameString = [[self.content objectAtIndex:indexPath.row] valueForKey:@"city"];
        DVC.stateNameString = [[self.content objectAtIndex:indexPath.row] valueForKey:@"state"];
    }

}
}

以下是addViewController.h的代码:

@interface AddViewController : UIViewController <UINavigationControllerDelegate,UIImagePickerControllerDelegate>{

IBOutlet UITextField *cityTextField;
IBOutlet UITextField *stateTextField;
IBOutlet UITextView *cityDescription;

UIImagePickerController* imagePicker;
}
@property (nonatomic, copy) NSString* name;
@property (nonatomic, copy) NSString* description;
@property (nonatomic, strong) UIImage* image;
@property (nonatomic, retain) IBOutlet UINavigationBar* navigationBar;

@property (nonatomic, strong) UITextField *cityTextField;
@property (nonatomic, strong) UITextField *stateTextField;
@property (nonatomic, strong) UITextView *cityDescription;

@property (nonatomic, strong) IBOutlet UIButton* choosePhotoButton;
@property (nonatomic, strong) IBOutlet UIButton* takePhotoButton;



- (IBAction)save;
- (IBAction)cancel;

- (IBAction)choosePhoto;
- (IBAction)takePhoto;

@end

最后添加视图控制器.m

@implementation AddViewController
@synthesize cityTextField, stateTextField, cityDescription;

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
    // Custom initialization
}
return self;
}

- (IBAction)save
{
// Make sure the user has entered at least a recipe name
if (self.cityTextField.text.length == 0)
{
    UIAlertView* alertView = [[UIAlertView alloc]
                              initWithTitle:@"Whoops..."
                              message:@"Please enter a city name"
                              delegate:nil
                              cancelButtonTitle:@"OK"
                              otherButtonTitles:nil];

    [alertView show];
    [alertView release];
    return;
}

if (self.stateTextField.text.length == 0)
{
    UIAlertView* alertView = [[UIAlertView alloc]
                              initWithTitle:@"Whoops..."
                              message:@"Please enter a city name"
                              delegate:nil
                              cancelButtonTitle:@"OK"
                              otherButtonTitles:nil];

    [alertView show];
    [alertView release];
    return;
}
// Make sure the user has entered at least a recipe name
if (self.cityDescription.text.length == 0)
{
    UIAlertView* alertView = [[UIAlertView alloc]
                              initWithTitle:@"Whoops..."
                              message:@"Please enter city description"
                              delegate:nil
                              cancelButtonTitle:@"OK"
                              otherButtonTitles:nil];

    [alertView show];
    [alertView release];
    return;
}

self.name = self.cityTextField.text;
self.name = self.stateTextField.text;
self.description = self.cityDescription.text;


if ([[self parentViewController] respondsToSelector:@selector(dismissViewControllerAnimated:)]){

    [[self parentViewController] dismissViewControllerAnimated:YES completion:nil];

} else {

    [[self presentingViewController] dismissViewControllerAnimated:YES completion:nil];
}
}

- (IBAction)cancel {
{

    if ([[self parentViewController] respondsToSelector:@selector(dismissModalViewControllerAnimated:)]){

        [[self parentViewController] dismissViewControllerAnimated:YES completion:nil];

    } else {

        [[self presentingViewController] dismissViewControllerAnimated:YES completion:nil];
    }
}
}

- (IBAction)choosePhoto
{
// Show the image picker with the photo library
imagePicker = [[UIImagePickerController alloc] init];
imagePicker.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
imagePicker.delegate = self;
imagePicker.allowsEditing = YES;
[self presentViewController:imagePicker animated:YES completion:nil];
}

- (IBAction)takePhoto {

UIImagePickerController *picker = [[UIImagePickerController alloc] init];
//picker.delegate = self;
picker.allowsEditing = YES;
picker.sourceType = UIImagePickerControllerSourceTypeCamera;

[self presentViewController:picker animated:YES completion:NULL];

}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {

UITouch *touch = [touches anyObject];
if ([cityDescription isFirstResponder] && [touch view] != cityDescription) {

    [cityDescription resignFirstResponder];
}
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

[cityTextField resignFirstResponder];
[stateTextField resignFirstResponder];
}

#pragma mark -
#pragma mark UIImagePickerControllerDelegate

- (void)imagePickerController:(UIImagePickerController*)picker     didFinishPickingMediaWithInfo:(NSDictionary*)info
{
// We get here when the user has successfully picked an image.
// Put the image in our property and set it on the button.

if (imagePicker) {
    self.image = [info objectForKey:UIImagePickerControllerEditedImage];
    [self.choosePhotoButton setImage:self.image forState:UIControlStateNormal];
} else {

    if (picker) {
        self.image = [info objectForKey:UIImagePickerControllerEditedImage];
        [self.takePhotoButton setImage:self.image forState:UIControlStateNormal];
    }
}

[self dismissViewControllerAnimated:YES completion:nil];
[imagePicker release];
imagePicker = nil;
}

- (void)imagePickerControllerDidCancel:(UIImagePickerController*)picker
{
[self dismissViewControllerAnimated:YES completion:nil];
[imagePicker release];
imagePicker = nil;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
}

- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}

@end

我知道有很多几乎相似的问题,并且相信我,我已经看了很多这样的问题,而且我认为我正在与这个问题碰壁,我想不出一个正确的方法来做到这一点。它可能是如此简单,但对于我的生活,我无法弄清楚这一点,这就是为什么我想寻求帮助。我真的很感激我能得到的任何帮助。如果需要,我可以将示例项目放在git hub上以方便访问。该项目也是在ios 6和最新的Xcode中构建的。

P.S。这是git hub上项目的链接:https://github.com/AdrianPhillips/TableSearch

3 个答案:

答案 0 :(得分:1)

我找不到执行“保存”工作的代码。我想它应该在UIAlertView代表中,对吧?你没有告诉我们你的问题是什么。以下代码也许你在寻找什么。

[content writeToFile:filePath atomically:YES]

另一个提示是:您不应将plist保存回主包,将其保存到Documents或Cache或其他文件夹。

答案 1 :(得分:0)

您必须先将plist复制到Documents文件夹。您无法将其编辑到原始应用程序文件夹中。您可以使用此类执行此操作:

- (void) CreatePlistCopyInDocuments:(NSString *)plistName {
    // First, test for existence.
    BOOL success;

    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSError *error;
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString *documentsDirectory = [paths objectAtIndex:0];
    NSString *writablePath = [documentsDirectory stringByAppendingPathComponent:plistName];
    success = [fileManager fileExistsAtPath:writablePath];

    if (success) {
        return;
    }

    // The writable file does not exist, so copy from the bundle to the appropriate location.
    NSString *defaultPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:plistName];
    success = [fileManager copyItemAtPath:defaultPath toPath:writablePath error:&error];
    if (!success) {
        NSAssert1(0, @"Failed to create writable file with message '%@'.", [error localizedDescription]);
    }
}

您只需将plist名称传递给它即可。 然后你必须将它加载到某个NSMutableDictionary中,如下所示:

NSString *documents = [NSHomeDirectory() stringByAppendingString:@"/Documents"];
            NSString *plistInDocuments = [documents stringByAppendingPathComponent:@"UserData.plist"];
            NSMutableDictionary *plistData = [[NSMutableDictionary alloc]initWithContentsOfFile:plistInDocuments];

更新字典的值后,您必须将文件写回文档,如下所示:

[plistData writeToFile:plistInDocuments atomically:YES];

答案 2 :(得分:0)

正如每个人都指出的那样,你无法写入主要包中的plist。您需要将其从捆绑包复制到应用程序文档目录。然后,您只需从文档目录中启动并写入路径即可。您遇到的另一个问题是,没有任何东西将AddViewController中的新数据传递回TableViewController。您应该为AddViewController创建一个协议和委托。

对于所有血腥细节,请参阅我在GitHub上的拉取请求 https://github.com/GayleDDS/TableSearch.git