unable to write the textfile? - iphone

i am new to iphone,i can read the txtfile using this code
-(NSString *)readfile:(NSString *)filename{
NSString *path=[[NSBundle mainbundle] PathForResource:filename ofType:"txt"];
NSData *mydata=[NSData dataWithContentsOfFile:path];
NSString *str;
if(mydata){
str=[[NSString alloc] initWithData:mydata encoding:NSASCIIStringEncoding];
}
return str;
}
Method Call::
ownservices *readtxt=[[ownservices alloc] init];
[readtxt readfile:#"textfile"];
By using this code i can read data from txtfile. By using these code i want to write add text to textfile
-(NSString *)writefile:(NSString *)filename:(NSString *)text{
NSString *path=[[NSBundle mainbundle] PathForResource:filename ofType:"txt"];
//NSData *mydata=[NSData dataWithContentsOfFile:path];
[text writeToFile:path dataUsingEncoding:NSTUF8StringEncoding error:nil];
return text;
}
Method call:
ownservices *write=[[ownservices alloc] init];
[write writefile:#"txtfile":#"Hello"];
but text is not adding to txtfile save in resource folder
anyone have an idea please help me,Thanks in advance

You can not save anything in resource folder at run time. You can save the file in documents folder.

Change the function prototype
-(NSString *) writefile:(NSString *)filename withText:(NSString *)text;
Definition :
-(NSString *)writefile:(NSString *)filename withText:(NSString *)text
{
//Put your code here
}
Calling place:
[write writefile:#"txtfile" withText:#"Hello"];

Related

NSMutableDictionary not working in voids and IBActions

I created an NSMutableDictionary called *temp in my .h file of the main viewController, and added this code to bring in the information from my .plist file.
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *path = [[NSBundle mainBundle] pathForResource:#"Data" ofType:#"plist"];
temp=[NSMutableDictionary dictionaryWithContentsOfFile:path];
}
In the same view controller, I added a button action and added the following code:
-(IBAction)mathButton:(UIButton *)_sender
{
label1.text = [temp objectForKey:#"m1name"];
}
Where "label1 is a text field in the .xib, and m1name is one of the keys in the .plist
But when I run it, it doesn't work, and highlights label1.text = [temp objectForKey:#"m1name"]; and calls it bad access.
I've been stuck on this for a couple of days, and tried lots of things. An answer would be really helpful.
Thanks
temp=[NSMutableDictionary dictionaryWithContentsOfFile:path];
You're not retaining the dictionary created via dictionaryWithContentsOfFile:path. You should either change that line to:
temp = [[NSMutableDictionary dictionaryWithContentsOfFile:path] retain];
(and make sure it's released in dealloc), or, if temp is a property, set it via
self.temp = [NSMutableDictionary dictionaryWithContentsOfFile:path];
In .h:
#interface ...
{
NSMutableDictionary* temp;
}
In .m:
- (void)viewDidLoad
{
[super viewDidLoad];
NSString* path = [[NSBundle mainBundle] pathForResource: #"Data"
ofType: #"plist"];
BOOL exists = [[NSFileManager defaultManager] fileExistsAtPath: path];
if (exists)
{
temp = [[NSMutableDictionary alloc] initWithContentsOfFile: path];
NSLog(#"%#", [temp description]);
}
}
- (IBAction) mathButton: (UIButton *)_sender
{
label1.text = [temp objectForKey: #"m1name"];
}
If MRC:
- (void) dealloc
{
[temp release];
[super dealloc];
}

Why is my NSMutableDictionary null?

Here's my delegate method for UIAlertView. I have no idea why myWordsDictionary is null when running the app. (Note: _dailyWords is an NSDictionary object and bookmarked is an NSString object.)
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex != [alertView cancelButtonIndex]) {
NSLog(#"Clicked button index !=0");
// Add the action here
NSString *documentPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *myWordsPath = [documentPath stringByAppendingPathComponent:#"MyWords.plist"];
NSMutableDictionary *myWordsDictionary = [[NSMutableDictionary alloc] initWithContentsOfFile:myWordsPath];
[myWordsDictionary setValue:[_dailyWords objectForKey:bookmarked] forKey:bookmarked];
[myWordsDictionary writeToFile:myWordsPath atomically:YES];
NSLog(#"%#", [myWordsDictionary description]);
[myWordsDictionary release];
} else {
NSLog(#"Clicked button index = 0");
// Add another action here
}
}
Thanks in advance.
myWordsPath may not contain any valid file, and you are initializing your NSMutableDictionary from content of the the file present at that path. That's why you are getting a null dictionary.
First, try check myWordsPath, if it returns null, you should look and find correct path.
Second, how you generate your plist? MyWords.plist must contain valid format. If you unsure, you should create from within XCode, there is plist object.
NSBundle *bundle = [NSBundle mainBundle];
NSString *plistPath = [bundle pathForResource:
#"MyWords" ofType:#"plist"];
NSDictionary *dictionary = [[NSDictionary alloc]
initWithContentsOfFile:plistPath];
please try this code..
NSString *documentPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
documentPath = [documentPath stringByAppendingPathComponent:#"MyWords.plist"];
NSMutableDictionary *myWordsDictionary = [[NSMutableDictionary alloc] initWithContentsOfFile:documentPath];

Creating NSMutableArray from xml file

I have an xml file with the following information.
<?xml version="1.0"?>
-<Party>
-<Player>
<Name>Butch</Name>
<Level>1</Level>
<Class>Fighter</Class>
</Player>
-<Player>
<Name>Shadow</Name>
<Level>2</Level>
<Class>Rogue</Class>
</Player>
-<Player>
<Name>Crak</Name>
<Level>3</Level>
<Class>Wizard</Class>
</Player>
</Party>
I try to add this to an NSMutableArray by doing the following.
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"Party" ofType:#"xml"];
NSData *xmlData = [[NSMutableArray alloc] initWithContentsOfFile:filePAth];
When I run this, my array object has no data in it.
If I replace the line with;
NSdata *xmlData = [NSdata dataWithContentsOfFole:filePath];
it will load my data but it is not in the format I require.
I'm very new to Objective-c and iPhone development and any help will be greatly appreciated.
If anymore info is needed I'll be happy to provide it.
edit - I'm using GDataXML to parse my xml
edit - My Parser class is as follows
#implementation PartyParser
+(NSString *)dataFilePath:(BOOL)forSave{
return [[NSBundle mainBundle] pathForResource:#"Party" ofType:#"xml"];
}
+(Party *)loadParty{
NSString *filePath = [self dataFilePath:FALSE];
//NSData *xmlData = [NSData dataWithContentsOfFile:filePath];
NSData *xmlData = [[NSMutableArray alloc] initWithContentsOfFile:filePath];
NSError *error;
GDataXMLDocument *doc = [[GDataXMLDocument alloc] initWithData:xmlData options:0 error:&error];
if(doc ==nil){return nil;}
NSLog(#"%#", doc.rootElement);
Party *party = [[[Party alloc] init] autorelease];
NSArray *partyMembers = [doc.rootElement elementsForName:#"Player"];
for (GDataXMLElement *partyMember in partyMembers)
{
NSString *name;
int level;
RPGClass rpgClass;
//Name
NSArray *names = [partyMember elementsForName:#"name"];
if(names.count > 0)
{
GDataXMLElement *firstName = (GDataXMLElement *) [names objectAtIndex:0];
name = firstName.stringValue;
}else continue;
//Level
NSArray *levels = [partyMember elementsForName:#"level"];
if(levels.count > 0)
{
GDataXMLElement *firstLevel = (GDataXMLElement *) [levels objectAtIndex:0];
level = firstLevel.stringValue.intValue;
}else continue;
//Class
NSArray *classes = [partyMember elementsForName:#"class"];
if(classes.count > 0)
{
GDataXMLElement *firstClass = (GDataXMLElement *) [classes objectAtIndex:0];
if([firstClass.stringValue caseInsensitiveCompare:#"fighter"] == NSOrderedSame)
{
rpgClass = RPGClassFighter;
}
else if([firstClass.stringValue caseInsensitiveCompare:#"rogue"] == NSOrderedSame)
{
rpgClass = RPGClassRogue;
}
else if([firstClass.stringValue caseInsensitiveCompare:#"wizard"] == NSOrderedSame)
{
rpgClass = RPGClassWizard;
}
else
{
continue;
}
}else continue;
Player *player = [[[Player alloc] initWithName:name level:level rpgClass:rpgClass] autorelease];
[party.players addObject:player];
}
//NSLog(#"%#", doc.rootElement);
//
[doc release];
[xmlData release];
return party;
}
#end
The XML file can not be any type of XML. It needs to be in the "property list" format.
Take a look at some Apple docs or some of the .plist files that will be in your project. That will show you how to create such a file.
Alternatively, create one using the "PList Editor" application that comes with the developer tools. It has a good UI for creating these files.
Lastly, your line "NSData* xmlData = ..." is very wrong - you're assigning a mutable array object to an NSData* variable. The types are not interchangeable by a long shot.
If you want to do full-blown XML parsing, there are various options that deserve a topic of their own. The XML used for plists is limited to Cocoa collections and simple data types.
Take a look to this XML Parser. It is called "TBXML", I have used that for a while and I'm quite happy with the result.
http://www.tbxml.co.uk/TBXML/TBXML_Free.html
Just place your XML file (e.g. "myFileName.xml") anywhere in your project.
Read the xml file contents to NSData using:
NSString *myBundleString = [[NSBundle mainBundle] pathForResource:#"myFileName" ofType:#"xml"];
NSData *myData = [NSData dataWithContentsOfFile:myBundleString];
And parse your data using NSXMLParser:
NSXMLParser *myParser = [[NSXMLParser alloc] initWithData:myData];
[myParser setDelegate:self];
[myParser parse];
Happy parsing using the delegate methods!

How to write a plist on a device? Objective C iphone

I have this code:
#define ALERT(X) {UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Info" message:X delegate:self cancelButtonTitle:#"OK" otherButtonTitles: nil];[alert show];[alert release];}
- (id)readPlist:(NSString *)fileName {
NSData *plistData;
NSString *error;
NSPropertyListFormat format;
id plist;
NSString *localizedPath = [[NSBundle mainBundle] pathForResource:fileName ofType:#"plist"];
plistData = [NSData dataWithContentsOfFile:localizedPath];
plist = [NSPropertyListSerialization propertyListFromData:plistData mutabilityOption:NSPropertyListImmutable format:&format errorDescription:&error];
if (!plist) {
NSLog(#"Error reading plist from file '%s', error = '%s'", [localizedPath UTF8String], [error UTF8String]);
[error release];
}
return plist;
}
- (void)writeToPlist: (NSString*)a
{
NSString *path = [[NSBundle mainBundle] bundlePath];
NSString *finalPath = [path stringByAppendingPathComponent:#"data.plist"];
NSMutableArray* pArray = [[NSMutableArray alloc] initWithContentsOfFile:finalPath];
[pArray addObject:a];
[pArray writeToFile:finalPath atomically: YES];
ALERT(#"finished");
/* This would change the firmware version in the plist to 1.1.1 by initing the NSDictionary with the plist, then changing the value of the string in the key "ProductVersion" to what you specified */
}
- (void)viewDidLoad {
[super viewDidLoad];
[self writeToPlist:#"this is a test"];
NSArray* the = (NSArray*)[self readPlist:#"data"];
NSString* s = [NSString stringWithFormat:#"%#",the];
ALERT(s);
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
}
On the simulator the second alert shows the content of the file correctly but on the device it shows nothing?? What's i'm doing wrong? Please show a code/snippet....
The problem is that you could not write a file into mainBundle folder, only Documents folder is accessable on your Device.
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];

Saving data to a plist file

I am having a little trouble saving to a plist file, when i am reading the data i am using:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return amounts.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//Create Cell
UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:#"cell"];
//Fill cell
NSDictionary *budgetItem = [amounts objectAtIndex:indexPath.row];
cell.textLabel.text = [budgetItem objectForKey:#"value"];
cell.detailTextLabel.text = [budgetItem objectForKey:#"description"];
//Return it
return cell;
}
- (void) loadData{
// Load items
NSString *error;
NSPropertyListFormat format;
NSString *localizedPath = [[NSBundle mainBundle] pathForResource:#"savebudget" ofType:#"plist"];
NSData *plistData = [NSData dataWithContentsOfFile:localizedPath];
NSArray *amountData = [NSPropertyListSerialization propertyListFromData:plistData
mutabilityOption:NSPropertyListImmutable
format:&format
errorDescription:&error];
if (amountData) {
self.amounts = [[NSMutableArray alloc] initWithCapacity:[amountData count]];
for (NSDictionary *amountsDictionary in amountData) {
[self.amounts addObject:amountsDictionary];
}
}
Which works fine from a static plist file with-in my resources folder, but when i try and create my own, nothing seems to happen:
-(void) addData {
NSString *path = [[NSBundle mainBundle] pathForResource:#"saveBudget" ofType:#"plist"];
NSMutableDictionary* plist = [[NSMutableDictionary alloc] initWithContentsOfFile:path];
[plist setValue:amountTxt.text forKey:#"value"];
[plist writeToFile:path atomically:YES];
[plist release];
}
- (IBAction)add:(id)sender {
[self addData];
[self.delegate budgetEnterMinusViewControllerDidFinish:self];
}
Any help more than welcome...
Ugh. Terrible and confusing code. First: use this to load instead:
NSString* path = [[NSBundle mainBundle] pathForResource:#"savebudget" ofType:#"plist"];
NSDictionary* amountData = [NSDictionary dictionaryWithContentsOfFile: path error: NULL];
if (amountData) {
self.amounts = [NSMutableArray arrayWithArray: amountData];
}
Note, no retain or alloc/init here because you are assigning to a retaining property.
So the real problem:
You are reading a plist that that you say contains an array of dictionaries. But then when you add data, you try to write back one single dictionary to that same plist.
Also, in your addData method you do not actually add any data.
And ... If you load your initial data from your app's bundle, then you should write it back to your ~/Documents directory after changing it. And of course read it back from there the next time your app starts.