I have an mutableArray which displays a list of files in a tableView. I have stored those files in a directory.
I am using NSfileManager class and attributesOfItemAtPath method to retrieve some properties of the files like fileSize, fileType..
In the second stage I am trying to have a detailView controller which displays the properties of the particular file when touched in the tableView.
The problem is I dont know how to bind those properties like fileSize and fileType separately to a NSDictionary and make it display in the detailView for that particular file.
Here is my source code for listing the files and to list the properties.
- (void)listFiles {
NSFileManager *fm =[NSFileManager defaultManager];
NSError *error = nil;
NSString *parentDirectory = #"/Users/akilan/Documents";
NSArray *paths = [fm contentsOfDirectoryAtPath:parentDirectory error:&error];
if (error) {
NSLog(#"%#", [error localizedDescription]);
error = nil;
}
directoryContent = [[NSMutableArray alloc] init];
for (NSString *path in paths){
NSString *documentsDirectory = [[path lastPathComponent] stringByDeletingPathExtension];
[directoryContent addObject:documentsDirectory];
}
}
-(void) willProcessPath {
NSString *parentDirectory = #"/Users/akilan/Documents";
NSArray *paths = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:parentDirectory error:nil];
for (NSString *path in paths){
filesPath = [parentDirectory stringByAppendingPathComponent:path];
NSDictionary *attrDir = [[NSFileManager defaultManager]attributesOfItemAtPath:filesPath error:nil];
filesSize = [attrDir objectForKey:NSFileSize];
filesName = (NSString *)directoryContent;
filesType = [path pathExtension];
createdDate = [attrDir objectForKey:NSFileCreationDate];
modifiedDate = [attrDir objectForKey:NSFileModificationDate];
}
}
Please help me to proceed to the next step.. Thanks in advance..
Try something like this:
- (void)viewDidLoad {
[super viewDidLoad];
[self listFiles];
}
- (void)listFiles {
NSFileManager *fm =[NSFileManager defaultManager];
NSError *error = nil;
NSString *parentDirectory = [self getDocumentsPath];
NSArray *paths = [fm contentsOfDirectoryAtPath:parentDirectory error:&error];
if (error) {
NSLog(#"%#", [error localizedDescription]);
error = nil;
}
NSMutableArray *array = [[NSMutableArray alloc] init];
self.directoryContent = array;
[array release];
for (NSString *path in paths){
NSString *fullPath = [self getPathToFileInDocumentsDirectory:path];
NSMutableDictionary *filePropertiesDictionary = [NSMutableDictionary dictionaryWithDictionary:[[NSFileManager defaultManager] attributesOfItemAtPath:fullPath error:nil]];
[filePropertiesDictionary setObject:fullPath forKey:#"fullPath"];
[filePropertiesDictionary setObject:path forKey:#"fileName"];
[directoryContent addObject:filePropertiesDictionary];
}
NSLog(#"%#", directoryContent);
}
- (NSString *)getDocumentsPath {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectoryPath = [paths objectAtIndex:0];
return documentsDirectoryPath;
}
- (NSString *)getPathToFileInDocumentsDirectory:(NSString *)fileName {
return [[self getDocumentsPath] stringByAppendingPathComponent:fileName];
}
Why not create a class "FileDescriptor" with the following properties:
NSString *fileName;
NSString *fileSize;
NSString *fileType;
NSDate *createdDate;
NSDate *modifiedDate;
When iterating over your directory, you create an instance of this class for each file, and store that in an array (or a dictionary, if you like). Then you can use that array to
a) provide data for your UITableViewCells
b) show a detail view for each file when the cell is clicked.
Should you want to use a dictionary instead (which I think is a lot less "clean") you can do so like this:
NSDictionary *fileProperties = [NSDictionary dictionaryWithObjectsAndKeys:
fileSize, #"fileSize",
fileName, #"fileName", nil];
- (void)listFiles {
NSFileManager *fm =[NSFileManager defaultManager];
NSError *error = nil;
NSString *parentDirectory = #"/Users/akilan/Documents";
NSArray *paths = [fm contentsOfDirectoryAtPath:parentDirectory error:&error];
if (error) {
NSLog(#"%#", [error localizedDescription]);
error = nil;
}
directoryContent = [[NSMutableArray alloc] init];
for (NSString *path in paths){
NSString *documentsDirectory = [[path lastPathComponent] stringByDeletingPathExtension];
[directoryContent addObject:documentsDirectory];
}
}
-(void) willProcessPath {
NSString *parentDirectory = #"/Users/akilan/Documents";
NSArray *paths = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:parentDirectory error:nil];
for (NSString *path in paths){
filesPath = [parentDirectory stringByAppendingPathComponent:path];
NSDictionary *attrDir = [[NSFileManager defaultManager]attributesOfItemAtPath:filesPath error:nil];
filesDirectory = [NSDictionary dictionaryWithObjectsAndKeys:filesSize, [attrDir objectForKey:NSFileSize],
filesName, (NSString *)directoryContent, filesType, [path pathExtension],
createdDate, [attrDir objectForKey:NSFileCreationDate],
modifiedDate, [attrDir objectForKey:NSFileModificationDate], nil];
NSLog(#"%#", filesDirectory);
}
}
#import <UIKit/UIKit.h>
#interface MyFilesList : UIViewController <UITableViewDelegate, UITableViewDataSource> {
NSMutableArray *directoryContent;
IBOutlet UITableView *filesTable;
IBOutlet NSNumber *filesSize;
IBOutlet NSString *filesName;
IBOutlet NSString *filesType;
IBOutlet NSString *filesPath;
IBOutlet NSDate *createdDate;
IBOutlet NSDate *modifiedDate;
NSMutableDictionary *filesDirectory;
}
#property (nonatomic, retain) NSMutableArray *directoryContent;
#property (nonatomic, retain) IBOutlet UITableView *filesTable;
#property (nonatomic, retain) IBOutlet NSNumber *filesSize;
#property (nonatomic, retain) IBOutlet NSString *filesName;
#property (nonatomic, retain) IBOutlet NSString *filesType;
#property (nonatomic, retain) IBOutlet NSString *filesPath;
#property (nonatomic, retain) IBOutlet NSDate *createdDate;
#property (nonatomic, retain) IBOutlet NSDate *modifiedDate;
#property (nonatomic, retain) NSMutableDictionary *filesDirectory;
- (void)listFiles;
- (void) willProcessPath;
#end
Related
An app i'm making has several views, each view has a record, stop and play button. The idea is that the user can record to a different sound file for each view.
I can record and playback a sound on each view but when i navigate away from the view and then navigate back the sound is gone.
I'm sorry to include so much code below but it's something i need to get to the bottom of.
Delegate.h
#import <UIKit/UIKit.h>
#import <AudioToolbox/AudioServices.h>
#import <AVFoundation/AVFoundation.h>
#interface humptyDumptyAppDelegate : UIResponder <UIApplicationDelegate>
{
NSArray *dirPaths;
NSString *docsDir;
NSString *soundFilePathPage1;
NSString *soundFilePathPage2;
NSString *soundFilePathPage3;
NSString *soundFilePathPage4;
NSString *soundFilePathPage5;
NSString *soundFilePathPage6;
}
#property (strong, nonatomic) UIWindow *window;
#property (strong, nonatomic) AVAudioRecorder *audioRecorder;
#property (strong, nonatomic) AVAudioPlayer *audioPlayer;
//example getter and setter functions
- (NSArray*) getDirPaths;
- (void) setDirPaths:(NSArray*)myDirPath;
- (NSString*) getDocsDir;
- (NSString*) soundFilePathForPageNumber:(int)pageNumber;
#end
Delegate.m
#import "humptyDumptyAppDelegate.h"
#implementation humptyDumptyAppDelegate
#synthesize window = _window;
#synthesize audioPlayer;
#synthesize audioRecorder;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
docsDir = [dirPaths objectAtIndex:0];
soundFilePathPage1 = [docsDir
stringByAppendingPathComponent:#"audiopage1.caf"];
soundFilePathPage2 = [docsDir
stringByAppendingPathComponent:#"page2.caf"];
soundFilePathPage3 = [docsDir
stringByAppendingPathComponent:#"page3.caf"];
soundFilePathPage4 = [docsDir
stringByAppendingPathComponent:#"page4.caf"];
soundFilePathPage5 = [docsDir
stringByAppendingPathComponent:#"page5.caf"];
soundFilePathPage6 = [docsDir
stringByAppendingPathComponent:#"page6.caf"];
return YES;
}
//getter function
- (NSArray*) getDirPaths{
return dirPaths;
}
//setter function
- (void) setDirPaths:(NSArray*)myDirPath{
dirPaths = myDirPath;
}
// get docs directory
-(NSString*) getDocsDir{
return docsDir;
}
// get sound file for page, passing the page number as an argument
-(NSString*) soundFilePathForPageNumber:(int)pageNumber{
switch (pageNumber) {
case 1:
return soundFilePathPage1;
break;
case 2:
return soundFilePathPage2;
break;
case 3:
return soundFilePathPage3;
break;
case 4:
return soundFilePathPage4;
break;
case 5:
return soundFilePathPage5;
break;
case 6:
return soundFilePathPage6;
break;
}
return nil;
}
page1.m
//this is called in viewDidLoad
-(void) prepareForAudioRecording
{
btnPlay.enabled = NO;
btnStop.enabled = NO;
int page = 1;
NSString *audioFilePath = [appDelegate soundFilePathForPageNumber:page];
NSURL *soundFileURL = [NSURL fileURLWithPath:audioFilePath];
NSError *error;
NSDictionary *recordSettings = [NSDictionary
dictionaryWithObjectsAndKeys:
[NSNumber numberWithInt:AVAudioQualityMin],
AVEncoderAudioQualityKey,
[NSNumber numberWithInt:16],
AVEncoderBitRateKey,
[NSNumber numberWithInt: 2],
AVNumberOfChannelsKey,
[NSNumber numberWithFloat:44100.0],
AVSampleRateKey,
nil];
appDelegate.audioRecorder = [[AVAudioRecorder alloc]
initWithURL:soundFileURL
settings:recordSettings
error:&error];
if (error)
{
NSLog(#"error: %#", [error localizedDescription]);
} else {
[appDelegate.audioRecorder prepareToRecord];
}
}
- (IBAction)recordAudio:(id)sender {
if (!appDelegate.audioRecorder.recording)
{
btnPlay.enabled = NO;
btnStop.enabled = YES;
[appDelegate.audioRecorder record];
}
}
- (IBAction)stopAudio:(id)sender {
btnStop.enabled = NO;
btnPlay.enabled = YES;
btnRecord.enabled = YES;
if (appDelegate.audioRecorder.recording)
{
[appDelegate.audioRecorder stop];
[self audioRecorderDidFinishRecording:appDelegate.audioRecorder successfully:YES];
} else if (appDelegate.audioPlayer.playing) {
[appDelegate.audioPlayer stop];
}
}
-(void)audioRecorderDidFinishRecording:(AVAudioRecorder *)recorder successfully:(BOOL)flag
{
if (flag == YES){
NSLog(#"finished recording");
[appDelegate.audioPlayer.data writeToFile:[appDelegate soundFilePathForPageNumber:1] atomically:YES];
}
}
Like i said, i'm sorry for the amount of code included, but i'm unsure where the problem is. I'm calling the writeToFile method in the audioRecorderDidFinishRecording: method. I don't know if this is correct but i have a feeling that this is not the root of the problem.
Please help!!
this code saves to an audio file
what about copping the file to the documents directory
BOOL success;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *writableDBPath = [documentsDirectory stringByAppendingPathComponent:#" sound.caf"];
success = [fileManager fileExistsAtPath:writableDBPath];
if (!success){
// The writable database does not exist, so copy the default to the appropriate location.
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"sound.caf"];
success = [fileManager copyItemAtPath:defaultDBPath toPath:writableDBPath error:&error];
NSError *attributesError;
NSDictionary *fileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:writableDBPath error:&attributesError];
NSNumber *fileSizeNumber = [fileAttributes objectForKey:NSFileSize];
long long fileSize = [fileSizeNumber longLongValue];
NSLog(#"file size: %lld",fileSize);
if (!success) {
NSLog(#"Failed to create writable database file with message: %#", [error localizedDescription]);
}
}
It turns out the problem was that in one of my pages i had my prepareForAudioRecording in viewDidAppear which was automatically overwriting the saved audio. Moving it to viewDidLoad did the trick
I have a plist which I read from my bundle into a new plist object that I put in the root directory for reading and writing. My question is what do I do with this or what dose the application do when its quit, and better yet what happens when the app is killed from the "multi task" menu from ios.
Also is there a way to save this plist to memory/the bundle for future use when the application is used again.
My code is as follows for refrence.
Here is my .h
#import <Foundation/Foundation.h>
#interface EngineProperties : NSObject {
NSString *signature;
NSNumber *version;
NSNumber *request;
NSNumber *dataVersion;
NSMutableDictionary *cacheValue;
//cachevalue Items
NSNumber *man;
NSNumber *mod;
NSNumber *sub;
}
#property (copy, nonatomic) NSString *signature;
#property (copy, nonatomic) NSNumber *version;
#property (copy, nonatomic) NSNumber *request;
#property (copy, nonatomic) NSNumber *dataVersion;
#property (copy, nonatomic) NSMutableDictionary *cacheValue;
//cachevalue Items
#property (copy, nonatomic) NSNumber *man;
#property (copy, nonatomic) NSNumber *mod;
#property (copy, nonatomic) NSNumber *sub;
//Singletton
+ (id)sharedManager;
- (void) saveData:(NSString *)methodName signature:(NSString *)pSignature Version:(NSNumber *)pVersion request:(NSNumber *)rNumber dataVersion:(NSNumber *)dvReturned cacheValue:(NSNumber *)cValue;
#end
and Here is my .m
#import "EngineProperties.h"
static EnginePropertiesController *sharedMyManager = nil;
#implementation EngineProperties
#synthesize signature;
#synthesize version;
#synthesize request;
#synthesize dataVersion;
#synthesize cacheValue;
#synthesize man;
#synthesize mod;
#synthesize sub;
#pragma mark Singleton Methods
+ (id)sharedManager {
#synchronized(self) {
if (sharedMyManager == nil)
sharedMyManager = [[self alloc] init];
}
return sharedMyManager;
}
- (id)init {
if (self = [super init]) {
// Data.plist code
// get paths from root direcory
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:#"EngineProperties.plist"];
// check to see if Data.plist exists in documents
if (![[NSFileManager defaultManager] fileExistsAtPath:plistPath])
{
// if not in documents, get property list from main bundle
plistPath = [[NSBundle mainBundle] pathForResource:#"EngineProperties" ofType:#"plist"];
}
// read property list into memory as an NSData object
NSData *plistXML = [[NSFileManager defaultManager] contentsAtPath:plistPath];
NSString *errorDesc = nil;
NSPropertyListFormat format;
// convert static property liost into dictionary object
NSDictionary *tempRoot = (NSMutableDictionary *)[NSPropertyListSerialization propertyListFromData:plistXML mutabilityOption:NSPropertyListMutableContainersAndLeaves format:&format errorDescription:&errorDesc];
if (!tempRoot)
{
NSLog(#"Error reading plist: %#, format: %d", errorDesc, format);
}
// assign values
self.signature = [tempRoot objectForKey:#"Signature"];
self.version = [tempRoot objectForKey:#"Version"];
self.request = [tempRoot objectForKey:#"Request"];
self.dataVersion = [tempRoot objectForKey:#"Data Version"];
man = [cacheValue objectForKey:#"Man"];
mod = [cacheValue objectForKey:#"Mod"];
sub = [cacheValue objectForKey:#"SubMod"];
cacheValue = [tempRoot objectForKey:#"Cache Value"];
}
- (void) saveData:(NSString *)methodName signature:(NSString *)pSignature Version:(NSNumber *)pVersion request:(NSNumber *)rNumber dataVersion:(NSNumber *)dvReturned cacheValue:(NSNumber *)cValue;
{
// get paths from root direcory
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:#"EngineProperties.plist"];
// set the variables to the values in the text fields
self.signature = pSignature;
self.version = pVersion;
self.request = rNumber;
self.dataVersion = dvReturned;
//do some if statment stuff here to put the cache in the right place or what have you.
if (methodName == #"manufacturers")
{
self.man = cValue;
}
else if (methodName == #"models")
{
self.mod = cValue;
}
else if (methodName == #"subMod")
{
self.sub = cValue;
}
self.cacheValue = [NSDictionary dictionaryWithObjectsAndKeys:
man, #"Manufacturers",
mod, #"Models",
sub, #"SubModels", nil];
NSDictionary *plistDict = [NSDictionary dictionaryWithObjectsAndKeys:
signature, #"Signature",
version, #"Version",
request, #"Request",
dataVersion, #"Data Version",
cacheValue, #"Cache Value", 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];
NSString *myString = [[NSString alloc] initWithData:plistData encoding:NSUTF8StringEncoding];
// NSLog(#"%#", myString);
}
else
{
NSLog(#"Error in saveData: %#", error);
// [error release];
}
}
#end
It honestly depends on how frequently you'll be asking for and changing the plist's values. For instance, my app only needed to retrieve it once, then write it a few times (nothing much), so all of my saving code was at the end of said particular method.
However, if your plist is live (constant value changes), keeping a reference to the data you wish to save that is accessible from the AppDelegate is recommended. That way, you can simply call: beginBackgroundTaskWithExpirationHandler: on -applicationDidResignActive and save your plist data.
(Note, if the user is fast enough to kill your app before it saves completely (big if), there are no guarantees as to the integrity of your plist).
follow the blow link in that link they provided the code also. How to Write/Read data to .plist file.
Plist
You can quickly and easily save plists to NSUserDefaults
Check out this quick tutorial:
http://www.cocoadev.com/index.pl?NSUserDefaults
I am writing a controller class for my plist, which gets called from another class. the controller class has a read and save method, the read method opens up the plist and saves it to the documents file for reading and writing too. In this read class I put all of the values that have been saved previously into their own variables.
Then in the Save method call, which is called from another class, all the values are passed in as parameters then from there I pass the new values into the correct variables and pass that into the plist.. however I have a dictionary inside my plist and its only saving one value and the resetting the others to null.. I am wondering how do I make sure these variables keep their values?
Here is my .h
#import <Foundation/Foundation.h>
#interface EngineProperties : NSObject {
NSString *signature;
NSNumber *version;
NSNumber *request;
NSNumber *dataVersion;
NSMutableDictionary *cacheValue;
//cachevalue Items
NSNumber *man;
NSNumber *mod;
NSNumber *sub;
}
#property (copy, nonatomic) NSString *signature;
#property (copy, nonatomic) NSNumber *version;
#property (copy, nonatomic) NSNumber *request;
#property (copy, nonatomic) NSNumber *dataVersion;
#property (copy, nonatomic) NSMutableDictionary *cacheValue;
//cachevalue Items
#property (copy, nonatomic) NSNumber *man;
#property (copy, nonatomic) NSNumber *mod;
#property (copy, nonatomic) NSNumber *sub;
- (void) readPlistData;
- (void) saveData:(NSString *)methodName signature:(NSString *)pSignature Version:(NSNumber *)pVersion request:(NSNumber *)rNumber dataVersion:(NSNumber *)dvReturned cacheValue:(NSNumber *)cValue;
#end
and Here is my .m
#import "EngineProperties.h"
#implementation EngineProperties
#synthesize signature;
#synthesize version;
#synthesize request;
#synthesize dataVersion;
#synthesize cacheValue;
#synthesize man;
#synthesize mod;
#synthesize sub;
//This opens up and reads the current plist ready to be used
-(void) readPlistData
{
// Data.plist code
// get paths from root direcory
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:#"EngineProperties.plist"];
// check to see if Data.plist exists in documents
if (![[NSFileManager defaultManager] fileExistsAtPath:plistPath])
{
// if not in documents, get property list from main bundle
plistPath = [[NSBundle mainBundle] pathForResource:#"EngineProperties" ofType:#"plist"];
}
// read property list into memory as an NSData object
NSData *plistXML = [[NSFileManager defaultManager] contentsAtPath:plistPath];
NSString *errorDesc = nil;
NSPropertyListFormat format;
// convert static property liost into dictionary object
NSDictionary *tempRoot = (NSMutableDictionary *)[NSPropertyListSerialization propertyListFromData:plistXML mutabilityOption:NSPropertyListMutableContainersAndLeaves format:&format errorDescription:&errorDesc];
if (!tempRoot)
{
NSLog(#"Error reading plist: %#, format: %d", errorDesc, format);
}
// assign values
self.signature = [tempRoot objectForKey:#"Signature"];
self.version = [tempRoot objectForKey:#"Version"];
self.request = [tempRoot objectForKey:#"Request"];
self.dataVersion = [tempRoot objectForKey:#"Data Version"];
man = [cacheValue objectForKey:#"Man"];
mod = [cacheValue objectForKey:#"Mod"];
sub = [cacheValue objectForKey:#"SubMod"];
cacheValue = [tempRoot objectForKey:#"Cache Value"];
}
- (void) saveData:(NSString *)methodName signature:(NSString *)pSignature Version:(NSNumber *)pVersion request:(NSNumber *)rNumber dataVersion:(NSNumber *)dvReturned cacheValue:(NSNumber *)cValue;
{
// get paths from root direcory
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:#"EngineProperties.plist"];
// set the variables to the values in the text fields
self.signature = pSignature;
self.version = pVersion;
self.request = rNumber;
self.dataVersion = dvReturned;
//do some if statment stuff here to put the cache in the right place or what have you.
if (methodName == #"manufacturers")
{
self.man = cValue;
}
else if (methodName == #"models")
{
self.mod = cValue;
}
else if (methodName == #"subMod")
{
self.sub = cValue;
}
self.cacheValue = [NSDictionary dictionaryWithObjectsAndKeys:
man, #"Manufacturers",
mod, #"Models",
sub, #"SubModels", nil];
NSDictionary *plistDict = [NSDictionary dictionaryWithObjectsAndKeys:
signature, #"Signature",
version, #"Version",
request, #"Request",
dataVersion, #"Data Version",
cacheValue, #"Cache Value", 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];
NSString *myString = [[NSString alloc] initWithData:plistData encoding:NSUTF8StringEncoding];
// NSLog(#"%#", myString);
}
else
{
NSLog(#"Error in saveData: %#", error);
// [error release];
}
}
#end
I am trying to find out how to keep the correct values in these three vars, man, mod, sub so I can put them into my cache value dictionary..
The problem is when you are getting your data ready to create the dictionary, here:
if (methodName == #"manufacturers")
{
self.man = cValue;
}
else if (methodName == #"models")
{
self.mod = cValue;
}
else if (methodName == #"subMod")
{
self.sub = cValue;
}
This is not the correct way to compare strings (you are actually comparing the addresses of the strings so they will probably never be the same), instead you should use this:
if ([methodName isEqualToString:#"manufacturers"])
{
self.man = cValue;
}
else if ([methodName isEqualToString:#"models"])
{
self.mod = cValue;
}
else if ([methodName isEqualToString:#"subMod"])
{
self.sub = cValue;
}
Another issue is that in readPlistData you are reading the keys "Man", "Mod", and "SubMod" but they should be the same as what you write into the dictionary: "Manufacturers", "Models", and "SubModels". (Either one could be correct, but they need to match so that you are reading and writing the same keys!)
Lastly, are you using the same instance of EngineProperties each time that you call saveData or are you creating a new object each time? If you aren't using the same object, then the iVars will be reset to nil each time that you call it.
First of all when you are calling
- (void) saveData:(NSString *)methodName signature:(NSString *)pSignature Version:(NSNumber *)pVersion request:(NSNumber *)rNumber dataVersion:(NSNumber *)dvReturned cacheValue:(NSNumber *)cValue;
Refer this to compare the string value
//This opens up and reads the current plist ready to be used
-(void) readPlistData
{
// Data.plist code
// get paths from root direcory
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:#"EngineProperties.plist"];
// check to see if Data.plist exists in documents
if (![[NSFileManager defaultManager] fileExistsAtPath:plistPath])
{
// if not in documents, get property list from main bundle
plistPath = [[NSBundle mainBundle] pathForResource:#"EngineProperties" ofType:#"plist"];
}
// read property list into memory as an NSData object
NSData *plistXML = [[NSFileManager defaultManager] contentsAtPath:plistPath];
NSString *errorDesc = nil;
NSPropertyListFormat format;
// convert static property liost into dictionary object
NSDictionary *tempRoot = (NSMutableDictionary *)[NSPropertyListSerialization propertyListFromData:plistXML mutabilityOption:NSPropertyListMutableContainersAndLeaves format:&format errorDescription:&errorDesc];
man = [cacheValue objectForKey:#"Man"];
mod = [cacheValue objectForKey:#"Mod"];
sub = [cacheValue objectForKey:#"SubMod"];
if (tempRoot && [tempRoot count]){
// assign values
self.signature = [tempRoot objectForKey:#"Signature"];
self.version = [tempRoot objectForKey:#"Version"];
self.request = [tempRoot objectForKey:#"Request"];
self.dataVersion = [tempRoot objectForKey:#"Data Version"];
cacheValue = [tempRoot objectForKey:#"Cache Value"];
}
}
- (void) saveData:(NSString *)methodName signature:(NSString *)pSignature Version:(NSNumber *)pVersion request:(NSNumber *)rNumber dataVersion:(NSNumber *)dvReturned cacheValue:(NSNumber *)cValue
{
// get paths from root direcory
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:#"EngineProperties.plist"];
// set the variables to the values in the text fields
self.signature = pSignature;
self.version = pVersion;
self.request = rNumber;
self.dataVersion = dvReturned;
//do some if statment stuff here to put the cache in the right place or what have you.
if (methodName isEqualToString:#"manufacturers") {
self.man = cValue;
} else if (methodName isEqualToString:#"models") {
self.mod = cValue;
} else if (methodName isEqualToString:#"subMod") {
self.sub = cValue;
}
self.cacheValue = [NSDictionary dictionaryWithObjectsAndKeys:
man, #"Manufacturers",
mod, #"Models",
sub, #"SubModels", nil];
NSDictionary *plistDict = [NSDictionary dictionaryWithObjectsAndKeys:
signature, #"Signature",
version, #"Version",
request, #"Request",
dataVersion, #"Data Version",
cacheValue, #"Cache Value", 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];
NSString *myString = [[NSString alloc] initWithData:plistData encoding:NSUTF8StringEncoding];
// NSLog(#"%#", myString);
} else {
NSLog(#"Error in saveData: %#", error);
// [error release];
}
}
#end
Basically, I have a JSON response from the Twitter API containing a timeline. I am trying to fill and array with Tweet objects in a loop but the alert window tells me that after the loop the array is empty:
NSError *error;
NSArray *tweetJsonObjects = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
for (int i = 0; i < [tweetJsonObjects count]; i++) {
Tweet *tweet = [[Tweet alloc] init];
tweet.userName = [[[tweetJsonObjects objectAtIndex:i] objectForKey:#"user"] objectForKey:#"name"];
tweet.text = [[tweetJsonObjects objectAtIndex:i] objectForKey:#"text"];
//[tweet.text gtm_stringByUnescapingFromHTML];
tweet.userProfileImageUrl = [[[tweetJsonObjects objectAtIndex:i] objectForKey:#"user"] objectForKey:#"profile_image_url"];
[tweets addObject:tweet];
}
NSString *x = [NSString stringWithFormat:#"%d", [tweets count]];
UIAlertView *message = [[UIAlertView alloc] initWithTitle:#"Hello World!"
message:x
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[message show];
The Tweet object is very simple:
#interface Tweet : NSObject
{
NSString *userName;
NSString *text;
NSString *userProfileImageUrl;
UIImage *userProfileImage;
}
#property (nonatomic, retain) NSString *userName;
#property (nonatomic, retain) NSString *text;
#property (nonatomic, retain) NSString *userProfileImageUrl;
#property (nonatomic, retain) UIImage *userProfileImage;
#end
I think this is because you call indexOfObject: instead of addObject: - an innocent autocompletion bug.
Try to change last line in for loop to:
[tweets addObject:tweet];
P.S. If tweets is your array
Of course it does, because you are not adding the objects to any array...
Obviously you meant [tweets addObject:tweet] instead of [tweets indexOfObject:tweet]
I would like to persist an object of a class (not just NSStringĀ“s). For instance, I have this class:
** News.h:**
#import <Foundation/Foundation.h>
#interface News : NSObject
#property (nonatomic, retain) NSString * atrib1;
#property (nonatomic, retain) NSString * atrib2;
#end
** News.m:**
#import "News.h"
#implementation News
#synthesize atrib1;
#synthesize atrib2;
#end
Should I have to use a plist to storage it? How should I do it?
Using NSCoding:
In News.m, I have added:
- (void) encodeWithCoder:(NSCoder *)encoder {
[encoder encodeObject:atrib1 forKey:#"key1"];
[encoder encodeObject:atrib2 forKey:#"key2"];
}
- (id)initWithCoder:(NSCoder *)decoder {
self = [super init];
atrib1 = [[decoder decodeObjectForKey:#"key1"] retain];
atrib2 = [[decoder decodeObjectForKey:#"key2"] retain];
return self;
}
-(void)dealloc{
[super dealloc];
[atrib1 release];
[atrib2 release];
}
In News.h:
#interface News : NSObject<NSCoding>{
NSCoder *coder;
}
#property (nonatomic, retain) NSString * atrib1;
#property (nonatomic, retain) NSString * atrib2;
#end
To read update and persist a new object in the plist:
- (IBAction)addANewNews:(id)sender {
//Plist File
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *plistPath = [[paths objectAtIndex:0] stringByAppendingPathComponent:#"myplist.plist"];
//Reading current news
NSData *oldNews = [NSData dataWithContentsOfFile:plistPath];
NSMutableArray *news = (NSMutableArray *)[NSKeyedUnarchiver unarchiveObjectWithData:oldNews];
if (news == nil)
news = [[NSMutableArray alloc] init];
//Adding a new news
[news addObject:aNewNews];
NSError *error;
NSData* newData = [NSKeyedArchiver archivedDataWithRootObject:news];
//persisting the updated news
BOOL success =[newData writeToFile:plistPath options:NSDataWritingAtomic error:&error];
if (!success) {
NSLog(#"Could not write file.");
}else{
NSLog(#"Success");
}
}