Adding nil to NSMutableArray - objective-c

I am trying to create a NSMutableArray by reading in a .txt file and am having trouble setting the last element of the array to nil.
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"namelist" ofType:#"txt"];
NSString *data = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
NSArray *list = [data componentsSeparatedByString:#"\n"];
NSMutableArray *mutableList = [[NSMutableArray alloc] initWithArray:list];
I wanted to use NSMutableArray's function addObject, but that will not allow me to add nil. I also tried:
[mutableList addObject:[NSNull null]];
but that does not seem to work either. Is there a way around this problem?

Use
NSMutableArray *mutableList = [[NSMutableArray alloc] init];
[mutableList addObjectsFromArray:list];
Hope this helps
jrtc27

Per Apple's documentation on NSMutableArray.
addObject:
Inserts a given object at the end of the receiver.
- (void)addObject:(id)anObject
Parameters
anObject
The object to add to the end of the receiver's content. **This value must not be nil.**
Reference
http://developer.apple.com/mac/library/documentation/Cocoa/Reference/Foundation/Classes/NSMutableArray_Class/Reference/Reference.html

Related

How to write and read data from plist to tableview

Hi I am trying to make bookmarks for my browser.
Title of Page, Url of Page, any Comments related to page.
I tried to save it in plist, but unsuccessful. Can anyone can help me to save these thing to plist and retrive in table view. So, when user tap on title it will open url in UIWebView.
Here is the code I have tried, so far:
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"bookmarks.plist"];
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath: path])
{
NSString *bundle = [[NSBundle mainBundle] pathForResource:#"bookmarks" ofType:#"plist"];
[fileManager copyItemAtPath:bundle toPath: path error:&error]; //6
}
NSMutableDictionary *data = [[NSMutableDictionary alloc] initWithContentsOfFile: path];
NSString *writeUrl = #"Page URL One";
NSString *writeTitle = #"Page Title One";
NSString *writeComment = #"Page comments";
[data setObject:[NSString stringWithString:writeUrl] forKey:#"url"];
[data setObject:[NSString stringWithString:writeTitle] forKey:#"title"];
[data setObject:[NSString stringWithString:writeComment] forKey:#"comment"];
[data writeToFile: path atomically:YES];
NSMutableDictionary *savedUrl = [[NSMutableDictionary alloc] initWithContentsOfFile: path];
NSString *value;
value = [[savedUrl objectForKey:#"url"] stringValue];
NSLog(#"%#", value);
UPDATE: I successfully saved and retrieved data to and from plist. Issue is comming in this line
value = [[savedUrl objectForKey:#"url"] stringValue];
By removing stringValue solve the problem.
value = [savedUrl objectForKey:#"url"];
Now My second issue. I make three items named url, title, comment, types String in plist file.
How can i store different urls. Like
name website: inforains
url: inforains.com
title: Info Rains
comment: good website articles
name website: hitechnology
url: hitechnology.com
title: Hitechnology
comment: hmmm
ans soo on..
how can I store data like this.. so all name website will show on tableview and when user click on anyone, data related to that website will show. I hope i clear my question.
To store multiple records as three items named url, title, comment, types String in plist file
change types from string to dictionary and store data in each dictionary individually for key as 1,2,3 ...
OR
Use three mutable array for each url,title and comment and add object at index 0 at the time of saving it.
and access them when required as nsmutable array.
Change this line
value = [[savedStock objectForKey:#"url"] stringValue];
to
value = [savedUrl objectForKey:#"url"];
because you are saving NSString in dictionary... not NSNumber.
Second issue:
//create mutable array to save all objects
NSMutableArray *objectsArray = [data objectForKey:#"objectsArray"];
if(!objectsArray) {
objectsArray = [[NSMutableArray alloc] init];
}
//create and add dictionary into array
NSDictionary *dictionary = [[NSDictionary alloc] initWithObjects:[NSArray arrayWithObjects:#"url1", #"title1", #"comment2",nil] forKeys:[NSArray arrayWithObjects:#"url", #"title", #"comment",nil]];
[objectsArray addObject:dictionary];
[data setObject:objectsArray forKey:#"objectsArray"];
[data writeToFile: path atomically:YES];
// to read data
NSMutableDictionary *savedUrl = [[NSMutableDictionary alloc] initWithContentsOfFile: path];
NSMutableArray *objectsArraySAved = [savedUrl objectForKey:#"objectsArray"];
for (NSMutableDictionary *dic in objectsArraySAved) {
NSLog(#"URL %#", [dic valueForKey:#"url"]);
}
Are you sure [data writeToFile: path atomically:YES]; works? It returns a BOOL, you should check it.
Are you sure savedURL != nil?
For your new problem, you should put all your dictionaries in a mutable array.
NSMutableArray *bookmarkArray = [[NSMutableArray alloc]init];
[bookmarkArray addObject:data];

How can I read supporting files by line in Xcode?

I'm currently making a web browsing program in Xcode 4.5.1 for OS X and I am trying to work on a list of bookmarks. What I hope to do is to have a supporting file called Bookmarks.txt in which I would list bookmarks like this:
Google
http://www.google.com/
Apple
http://www.apple.com/
Microsoft
http://www.microsoft.com/
I have already looked at a lot of pages discussing this, but none of them apply to what I'm doing. What I have now is
NSMutableArray *list;
NSString *contents;
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"Bookmarks" ofType:#"txt"];
if (filePath) {
content = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
for (NSString *line in [contents componentsSeparatedByString:#"\n"]) {
[list addObject:line];
}
}
as well as Dave DeLong's method, but I get all kinds of errors with Dave DeLong's and with this one nothing happens. Any help would be great, but I am just starting out at Xcode and know very little.
Thanks!
Your objects aren't initialized.
NSMutableArray *list = [[NSMutableArray alloc] init];
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"Bookmarks" ofType:#"txt"];
if (filePath) {
NSString * content = [NSString initWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];
for (NSString *line in [contents componentsSeparatedByString:#"\n"]) {
[list addObject:line];
}
}

What is the different between NSArray Parsing?

What is the difference between of Parsing in the following code segments.
which codes segments is faster in Parsing?
NSArray *arr = [[NSArray alloc] initWithObjects:#"Apple",#"Macbook", nil];
NSMutableArray *data = (NSMutableArray *)arr;
(and)
NSArray *arr = [[NSArray alloc] initWithObjects:#"Apple",#"Macbook", nil];
NSMutableArray *data = [NSMutableArray arrayWithArray:arr];
You have the same mistake in both snippets, you allocate memory for the object, and then assign something else to data, which makes you lose the previous (and have memory leak), e.g. this:
NSMutableArray *data = [[NSMutableArray alloc] init];
data = [NSMutableArray arrayWithArray:arr];
should be
NSMutableArray *data = [NSMutableArray arrayWithArray:arr];
Now for the question itself:
The first case is a bad idea, you cast the NSArray, but you canot modify it, as you didn't really changed its type, only assigned it to NSMutaleArray pointer.
The second case will create a new NSMutableArray which is mutable, with the contents of the NSArray, and this is cool, you may alter this array now.
It looks like what you want is either:
NSArray *arr = [[NSArray alloc] initWithObjects:#"Apple",#"Macbook", nil];
NSMutableArray *data = [arr mutableCopy];
or:
NSMutableArray *data = [[NSMutableArray alloc] initWithObjects:#"Apple",#"Macbook", nil];

Memory leak in NSMutableArray, can't autorelease

I am having trouble releasing tempArray below... tempArray is a leak and I have tried return [tempArray autorelease] and it causes a crash. Does anyone know how to get rid of the memory leak in tempArray?
+(NSMutableArray*) returnTheArray:(NSString*)thePath forTheKey:(NSString*)theKey {
NSString *errorDesc = nil;
NSPropertyListFormat format;
NSString *plistPath;
NSString *rootPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES) objectAtIndex:0];
NSString *testString = [thePath stringByAppendingString:#".plist"];
plistPath = [rootPath stringByAppendingPathComponent:testString];
if (![[NSFileManager defaultManager] fileExistsAtPath:plistPath]) {
plistPath = [[NSBundle mainBundle] pathForResource:thePath ofType:#"plist"];
}
NSData *plistXML = [[NSFileManager defaultManager] contentsAtPath:plistPath];
NSDictionary *temp = (NSDictionary *)[NSPropertyListSerialization
propertyListFromData:plistXML
mutabilityOption:NSPropertyListMutableContainersAndLeaves
format:&format
errorDescription:&errorDesc];
if (!temp) {
CCLOG(#"Error reading plist: %#, format: %d", errorDesc, format);
}
NSMutableArray *tempArray = [[NSMutableArray alloc] initWithArray:[temp objectForKey:theKey]];
return tempArray;
}
Well, the problem is that returnTheArray is not a name that the Analyzer will recognize as returning a retained value -- this is why it complains. So either you rename the method or return an autoreleased value. But if the latter you need to make sure that the "consumer" of the returned value appropriately deals with it -- retaining it if the value must persist beyond the next autorelease pool drain operation.
try:
NSMutableArray *tempArray = [NSMutableArray arrayWithArray:[temp objectForKey:theKey]];

NSArray writeToFile returning "is deprecated" - iPhone SDK

I'm trying to save some settings from my app to a plist file when it closes, then load them when the app launches. I have 4 numbers saved in an NSArray called array. The loading works fine because if I change the file, the app starts the way the file was changed.
This code works fine:
- (void)LoadSettings {
NSString *path = [[NSBundle mainBundle] bundlePath];
NSString *finalPath = [path stringByAppendingPathComponent:kSaveFileLocation];
NSArray *array = [[NSArray alloc] initWithContentsOfFile:finalPath];
clockFaceImageSlider.value = [[array objectAtIndex:0] integerValue];
HourTypeSwitch.on = [[array objectAtIndex:1] integerValue];
touchRotationSwitch.on = [[array objectAtIndex:2] integerValue];
accelerometerRotationSwitch.on = [[array objectAtIndex:3] integerValue];
}
This code works up to the save line:
- (void)SaveSettings {
NSString *path = [[NSBundle mainBundle] bundlePath];
NSString *finalPath = [path stringByAppendingPathComponent:kSaveFileLocation];
NSArray *array = [[NSArray alloc] initWithObjects:[NSNumber numberWithInt:clockFaceImageSlider.value], [NSNumber numberWithInt:HourTypeSwitch.on], [NSNumber numberWithInt:touchRotationSwitch.on], [NSNumber numberWithInt:accelerometerRotationSwitch.on], nil];
if (![array writeToFile:finalPath atomically:YES]) {
NSLog(#"error");
}
//The log does print error
}
Does anybody know how I can make it save to the plist?
~thanks
Dont write array's description NSString, just write the array instead:
[array writeToFile:finalPath atomically:YES];
Or if you want the strings you should use en encoding type
NSError *error;
[[array description] writeToFile:finalPath atomically:YES encoding:NSUTF8StringEncodingerror:&error];
but this will not write a plist.
Instead of taking the description (which is an NSString) of an NSArray and write it to a file, just use writeToFile:atomically of NSArray itself, as in
[array writeToFile:finalPath atomically:YES];
The reason writeToFile:atomically: of an NSString is deprecated is that it doesn't correctly account for the character encodings. Who told you to use description? That person/book should be punished...
That said, if you want to save just a few entries, it would be easier to just use NSUserDefaults, see here. Then all you have to do is
[[NSUserDefaults standardUserDefaults] setObject: ... forKey:#"..."]
and the framework does everything from preparing a plist path behind the scenes to saving it to the disk.