Problems saving files

Discussion in 'iOS Programming' started by iphonedude2008, Dec 11, 2012.

  1. iphonedude2008, Dec 11, 2012
    Last edited: Dec 12, 2012

    macrumors regular

    iphonedude2008

    Joined:
    Nov 7, 2009
    Location:
    Irvine, CA
    #1
    I am trying to save files to the sandbox. I have an object with an array, which has many arrays, which in turn contains arrays that contain nsstrings, nsurls, uiimages, and other media objects. All the objects implement nscoding or nssecurecoding. It will archive the objects to nsdata and i can unarchive it right there, but i can not save it to the disk. What is going on and how can i get it to save to the disk. I prefer to use archives, but if i absolutely have to, i can use core data.

    heres the code for the model
    Code:
    
    //
    //  CQStorageModel.h
    //  White Nova
    //
    //  Created by Mark Hill on 12/4/12.
    //  Copyright (c) 2012 Mark Hill. All rights reserved.
    //
    
    #import <Foundation/Foundation.h>
    
    @interface CQStorageModel : NSObject<NSCoding>
    
    @property (strong, nonatomic) NSMutableArray *dataSource;
    @property (strong, nonatomic) NSURL *savingUrl;
    
    
    //methods for saving and retreaving the datasource
    - (id) initWithDataSource;
    - (void) saveDataSource;
    - (id) refreshData;
    
    
    //methods for adding projects to the datasource
    - (void) addProject: (NSMutableArray *) arry withName: (NSString *) string;
    - (void) removeProjectAtIndex: (NSUInteger) index;
    - (NSString *) loadProjectNameAtIndex: (NSUInteger) index;
    
    
    //methods for adding objects to the datasource
    - (void) addObject: (id<NSCoding>) object withName: (NSString *)name toProjectAtIndex: (NSUInteger) index;
    - (void) removeObjectAtIndex: (NSUInteger) index1 inProjectAtIndex: (NSUInteger) index2;
    - (id) loadObjectAtIndex: (NSUInteger) index1 inProjectAtIndex: (NSUInteger) index2;
    - (NSString *) loadNameAtIndex: (NSUInteger) index1 inProjectAtIndex: (NSUInteger) index2;
    
    
    //methods for giving counts
    - (NSUInteger) projectCount;
    - (NSUInteger) objectCountInProject: (NSUInteger) projectNumber;
    
    
    //refreshers
    - (void) changeNotify;
    
    @end
    
    Code:
    
    //
    //  CQStorageModel.m
    //  White Nova
    //
    //  Created by Mark Hill on 12/4/12.
    //  Copyright (c) 2012 Mark Hill. All rights reserved.
    //
    
    #import "CQStorageModel.h"
    
    @implementation CQStorageModel
    
    @synthesize dataSource;
    
    
    //compling with nscoding to save and retreave this object
    - (void) encodeWithCoder:(NSCoder *)aCoder {
        [aCoder encodeObject:self.dataSource forKey:@"dataSource"];
        [aCoder encodeObject:self.savingUrl forKey:@"savingUrl"];
    }
    
    - (id) initWithCoder:(NSCoder *)aDecoder {
        self = [super init];
        self.dataSource = [aDecoder decodeObjectForKey:@"dataSource"];
        self.savingUrl = [aDecoder decodeObjectForKey:@"savingUrl"];
        return self;
    }
    
    
    
    //methods for saving and retreaving the datasource
    - (id) initWithDataSource {
        self = [super init];
        if (self) {
            NSFileManager *fm = [[NSFileManager alloc]init];
            NSURL *appSupportUrl = [fm URLForDirectory:NSApplicationSupportDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil];
            
            if (appSupportUrl == nil)
                appSupportUrl = [fm URLForDirectory:NSApplicationSupportDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:YES error:nil];
            
            self.savingUrl = [appSupportUrl URLByAppendingPathComponent:@"CQStorageModel.cqstm"];
            [fm createDirectoryAtPath:self.savingUrl.path withIntermediateDirectories:YES attributes:nil error:nil];
            NSLog(@"%@", self.savingUrl.path);
            NSData *data = [[NSData alloc]initWithContentsOfURL:self.savingUrl];
            
            if (data)
            {
            self = [NSKeyedUnarchiver unarchiveObjectWithData:data];
            }
        
            self.dataSource = [NSMutableArray array];
            [self saveDataSource];
            NSLog(@"%@", self.savingUrl);
        }
        
        return self;
    }
    
    - (void) saveDataSource {
        BOOL ok = [NSKeyedArchiver archiveRootObject:self toFile:self.savingUrl.path];
        BOOL no = NO;
        //NSData *data = [NSKeyedArchiver archivedDataWithRootObject:self];
        //[data writeToURL:self.savingUrl atomically:NO];
    }
    
    - (id) refreshData {
        id Data;
        NSFileManager *fm = [[NSFileManager alloc]init];
        NSURL *appSupportUrl = [fm URLForDirectory:NSApplicationSupportDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:NO error:nil];
        
        if (!appSupportUrl)
            appSupportUrl = [fm URLForDirectory:NSApplicationSupportDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:YES error:nil];
        
        self.savingUrl = [appSupportUrl URLByAppendingPathComponent:@"CQStorageModel.cqstm"];
        NSData *data = [[NSData alloc]initWithContentsOfURL:self.savingUrl];
        
        if (data)
        {
            Data = [NSKeyedUnarchiver unarchiveObjectWithData:data];
        }
        
        [self saveDataSource];
        return Data;
    }
    
    
    
    
    //methods for adding projects to the datasource
    - (void) addProject: (NSMutableArray *) arry withName: (NSString *) string {
        [arry insertObject:string atIndex:0];
        [self.dataSource addObject:arry];
        [self saveDataSource];
        [self changeNotify];
    }
    
    - (void) removeProjectAtIndex:(NSUInteger)index {
        if (self.dataSource != nil) {
        [self.dataSource removeObjectAtIndex:index];
        [self saveDataSource];
        }
        [self changeNotify];
    }
    
    
    //methods for adding objects to the datasource
    - (void) addObject:(id<NSCoding>)object withName:(NSString *)name toProjectAtIndex:(NSUInteger)index {
        NSMutableArray *marray = [NSMutableArray array];
        
        if (name.length == 0)
            [marray insertObject:[NSString stringWithFormat:@"file %i", [[self.dataSource objectAtIndex:index] count]] atIndex:0];
        else
            [marray insertObject:name atIndex:0];
        
        [marray insertObject:object atIndex:1];
        [[self.dataSource objectAtIndex:index] addObject:marray];
        [self saveDataSource];
        [self changeNotify];
    }
    
    - (void) removeObjectAtIndex:(NSUInteger)index1 inProjectAtIndex:(NSUInteger)index2 {
        if (index1 != 0)
            [[self.dataSource objectAtIndex:index2] removeObjectAtIndex:index1];
        [self saveDataSource];
        [self changeNotify];
    }
    
    - (id) loadObjectAtIndex:(NSUInteger)index1 inProjectAtIndex:(NSUInteger)index2 {
        if (self.dataSource != nil) {
        id object = [[[self.dataSource objectAtIndex:index2] objectAtIndex:(index1 + 1)] objectAtIndex:1];
        return object;
        }
        else
            return nil;
    }
    
    
    
    //methods for getting names
    - (NSString *) loadNameAtIndex:(NSUInteger)index1 inProjectAtIndex:(NSUInteger)index2 {
        if (self.dataSource != nil) {
                NSString *string = [[[self.dataSource objectAtIndex:index2] objectAtIndex:(index1 + 1)]objectAtIndex:0];
                return string;
        }
            return nil;
    }
    
    - (NSString *) loadProjectNameAtIndex:(NSUInteger)index {
        if (self.dataSource != nil && [self.dataSource count] > (index)) {
            NSString *strg = [[self.dataSource objectAtIndex:index] objectAtIndex:0];
            return strg;
        }
        else return @"";
    }
    
    
    //methods for giving counts
    
    - (NSUInteger) projectCount {
        if (self.dataSource != nil) 
        return [self.dataSource count];
        else
            return 0;
    }
    
    - (NSUInteger) objectCountInProject:(NSUInteger)projectNumber {
        if (self.dataSource != nil && [self.dataSource count] != 0) {
            if ([self.dataSource objectAtIndex:projectNumber] != nil) {
                return ([[self.dataSource objectAtIndex:projectNumber] count] - 1);
            }
            }
            return 0;
    }
    
    
    
    
    //refresher
    
    - (void) changeNotify {
        [[NSNotificationCenter defaultCenter]postNotificationName:@"data changed" object:self];
    }
    
    
    @end
    
     
  2. Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
  3. thread starter macrumors regular

    iphonedude2008

    Joined:
    Nov 7, 2009
    Location:
    Irvine, CA
  4. Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #4

    This looks sketchy to say the least. You set the savingURL. Then you create a directory at that path. That means you now have a directory called "CQStorageModel.cqstm" within the application support directory. This will prevent you writing a file with the same name...
     
  5. thread starter macrumors regular

    iphonedude2008

    Joined:
    Nov 7, 2009
    Location:
    Irvine, CA
    #5
    How should I fix it then? I don't quite understand what you said. I was trying to make a file inside the app support directory to save my model object to. Is that what I am doing and is there a better way?
     
  6. Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #6
    Break the following lines down, one at a time, explaining for each what you think it is doing (the lines numbered like (1)). Include where appropriate what the paths are, the log output and the expected change in the file system. You should see where the issue is (or you have not understood what the documentation says each method does):

     
  7. thread starter macrumors regular

    iphonedude2008

    Joined:
    Nov 7, 2009
    Location:
    Irvine, CA
    #7
    I figured out it is a problem with this line in saveDataSource.

    Code:
    - (void) saveDataSource {
        NSData *data = [NSKeyedArchiver archivedDataWithRootObject:self];
        NSError *err = nil;
        [data writeToFile:self.savingUrl.path options:NSDataWritingAtomic error:&err];
        NSLog(@"%@", [err localizedDescription]);
    }
    
    it prints out this

    The operation couldn’t be completed. (Cocoa error 512.)
     
  8. Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #8
    No, the error is where I've 1) told you and 2) guided you to work you for your self. This is just a symptom of the earlier error. If you worked through the lines I suggested you would see the issue.
     

Share This Page