Trying to write coredata to csv using chcsvparser - objective-c

I've done the following to put a fetched request into an array of arrays but now i don't know which methods i need to call from chcsvparser to write this into a csv file
NSArray *objectsForExport = [fetchedResultsController fetchedObjects];
NSArray *exportKeys = [NSArray arrayWithObjects:#"best_checkout", #"darts_thrown", #"high_score", #"score_100", #"score_140", #"score_180",#"three_dart_average",nil];
NSMutableArray *csvObjects = [NSMutableArray arrayWithCapacity:[objectsForExport count]];
for (NSManagedObject *object in objectsForExport) {
NSMutableArray *anObjectArray = [NSMutableArray arrayWithCapacity:[exportKeys count]];
for (NSString *key in exportKeys) {
id value = [object valueForKey:key];
if (!value) {
value = #"";
}
[anObjectArray addObject:[value description]];
}
[csvObjects addObject:anObjectArray];
}

As Johann suggests, you should use the writeToCSVFile:atomically: convenience method. However, be aware that using it as you describe in your comment is not correct.
The NSString you pass in should be the filepath you want the data writing to.

This webpage should give you the necessary information and methods when writing CSV files:
https://github.com/davedelong/CHCSVParser#readme
Hope this helps!

Related

NSDictionary writeToFile fails while objects are valid, permission is 0k

Why NSDictionary cannot be written?? I have checked the content of the dictionary: all the instances are of NSString and NSNumber. I checked permissions: a text file with the same name at the same path is written well. Of course, my dictionary is not empty.
NSString *file = ...
NSDictionary *dict = ...
// check dictionary keys
BOOL wrong = NO;
for (id num in [dict allKeys]) {
if (![num isKindOfClass:[NSNumber class]]) {
wrong = YES;
break;
}
}
if (wrong) {
NSLog(#"First");
}
// check dictionary values
wrong = NO;
for (id num in [dict allValues]) {
if (![num isKindOfClass:[NSString class]]) {
wrong = YES;
break;
}
}
if (wrong) {
NSLog(#"Second");
}
if (![dict writeToFile:file atomically:YES]) {
// 0k, let's try to create a text file
NSLog(#"Names writing error!");
[#"Something here... .. ." writeToFile:file atomically:YES encoding:NSUTF8StringEncoding error:nil];
}
Output: "Names writing error!"
Text file is created successfully.
Writing out a dictionary creates a property list, and according to the documentation all keys in a property list must be strings.
... and although NSDictionary and CFDictionary objects allow their keys to
be objects of any type, if the keys are not string objects, the
collections are not property-list objects.
NSNumber objects as keys are not supported.
As #vadian points out, you cannot write plist with numeric keys. But you can use NSKeyedArchiver:
NSURL *documents = [[NSFileManager defaultManager] URLForDirectory:NSDocumentDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:false error:nil];
NSURL *fileURL = [documents URLByAppendingPathComponent:#"test.plist"];
// this will not work
NSDictionary *dictionary = #{#1: #"foo", #2: #"bar"};
BOOL success = [dictionary writeToFile:fileURL.path atomically:true];
NSLog(#"plist %#", success ? #"success" : #"failure");
// this will
fileURL = [documents URLByAppendingPathComponent:#"test.bplist"];
success = [NSKeyedArchiver archiveRootObject:dictionary toFile:fileURL.path];
NSLog(#"archive %#", success ? #"success" : #"failure");
And you can read it back with NSKeyedUnarchiver:
// to read it back
NSDictionary *dictionary2 = [NSKeyedUnarchiver unarchiveObjectWithFile:fileURL.path];
NSLog(#"dictionary2 = %#", dictionary2);
Note, you can do this with any class that conforms (and properly implements) NSCoding. Fortunately, NSDictionary conforms already. You have to make sure that any objects inside the dictionary, also conform (both NSString and NSNumber do). If you had a custom object in your dictionary, you'd have to make it properly conform yourself.
This is all described in the Archives and Serializations Programming Guide.

Adding multiple values to an NSString from an array

I have an array of items, each with their own unique descriptions. Basically, I want to create a method which takes each item from the array and returns a single descriptive string which shows the description of each item in said array.
- (NSString *) itemList
{
NSString *list = [[NSString alloc] init];
for (Item *i in _items)
{
/**
Unsure :S
*/
[NSString stringWithFormat:#"%#: %#.\n", [i firstId], [i name]];
}
return list;
}
Basically, this is the coded logic that I have so far.
Assume I have two items which are initialised as such:
Item *testItem1 = [[Item alloc] initWithIdentifiers:#[#"shovel", #"spade"] name:#"a shovel" andDesc:#"This is a mighty fine shovel"];
Item *testItem2 = [[Item alloc] initWithIdentifiers:#[#"gem", #"crystal"] name:#"a gem" andDesc:#"This is a shiny gem"];
I then add those items to my Inventory object:
[testInventory put:testItem1];
[testInventory put:testItem2];
By calling the Inventory method itemList
[testInventory itemList];
on my inventory (code listed above), I want the following result:
#"shovel: a shovel.\ngem a gem."
Does anyone have any suggestions or pointers. I'm sure it's simple; it's just that I've only recently picked up Obj - C :)
Thanks
You can just use:
list = [list stringByAppendingFormat:#"%#: %#\n", [i firstId], [i name]];
or try NSMutableString:
NSMutableString *list = [[NSMutableString alloc] init];
[list appendFormat:#"%#: %#\n", [i firstId], [i name]];
You can do it more elegantly by overriding the description method for your Item class like this:
- (NSString *) description {
return [NSString stringWithFormat:"%#: %#.", [self firstId], [self name]];
}
and then to generate the string for all the items in the array:
NSString* itemsString = [itemList componentsJoinedByString:#"\n"];
I like adding the collection of strings to a mutable array and then calling componentsJoinedByString. It works even more cleanly if it is the description method you want on each object because you don't have to do the collecting loop first.
Create nsmutablearray
For each item in list
Nsmutablearray add object item.property
Return nsmutablearray componentsJoinedByString #", "
If you want the item's description though, you can just do, assuming you have an array with the objects already
TheArray componentsJoinedByString #", "

Obtaining an NSArray of Core Data properties

Consider a Core Data database containing Elements where each Element has a property called symbol, and the question is the most succinct method of obtaining an NSArray of each of the symbols. This can be accomplished with something along the lines of
-(NSArray*)symbolsInDatabase {
ENTRY_LOG;
NSError* err;
NSFetchRequest* request = [NSFetchRequest fetchRequestWithEntityName:#"Element"];
request.resultType = NSDictionaryResultType;
request.propertiesToFetch = [NSArray arrayWithObject:#"symbol"];
NSArray* arrayOfDictionaries = [self.database.managedObjectContext executeFetchRequest:request error:&err];
NSMutableArray* symbols = [[NSMutableArray alloc]initWithCapacity:[arrayOfDictionaries count]];
for (NSDictionary* d in arrayOfDictionaries) {
[symbols addObject:[d objectForKey:#"symbol"]];
}
EXIT_LOG;
return symbols;
}
Yet there is a nagging feeling I'm missing something, and that I can be using -(NSArray*)filteredArrayUsingPredicate in some clever manner rather than iterating over the array of dictionaries and extracting the object for the symbol key.
Any thoughts on how to make this cleaner?
Indeed, the valueForKeyPath selector:
NSArray *symbols = [arrayOfDictionaries valueForKeyPath:#"#unionOfObjects.symbol"];

Can someone explain to me what's going on here?

I'm going to paste the code below, then tell you what I've tried to determine from the code.
If you're reading this quickly, start with the text right above the next code-block.
- (void)tableViewDidLoadModel:(UITableView*)tableView {
self.items = [NSMutableArray array];
self.sections = [NSMutableArray array];
NSMutableDictionary *groups = [NSMutableDictionary dictionary];
for (int c = 0;c < [_contacts.people count];c++) {
NSDictionary *person = [_contacts.people objectAtIndex:c];
NSString *name = [person objectForKey:#"fullName"];
NSString *letter = [name substringToIndex:1];
NSMutableArray *section = [groups objectForKey:letter];
NSLog(#"%# - %# - %#", name, [person objectForKey:#"index"], [person objectForKey:#"abId"]);
if (!section) {
section = [NSMutableArray array];
[groups setObject:section forKey:letter];
}
TTTableItem *item = [ttItem itemWithText:name URL:[person objectForKey:#"index"]];
[section addObject:item];
}
Someone else wrote this block of code. From what I can determine, they're trying to take the user's contacts and fill a TableView.
Now my real question has to do with that last line:
TTTableItem *item = [ttItem itemWithText:name URL:[person objectForKey:#"index"]];
[section addObject:item];
This is using the Three20 framework. Apparently what the previous developer did was use TTTableItem to kind of get a pre-formatted UITableViewCell. (Hopefully I'm thinking right?)
I need to replace this line of code with something normal.
I've thought of just using UITableViewCell, but other than that I'm not really sure how to start?
-tableViewDidLoadModel: is a method that comes from the TTTableViewDataSource protocol, so if you're trying to remove Three20 from your project, you've got more to do than just replace the TTTableItem.
TTTableItem is a subclass of NSObject, and the only thing it seems to add is a userInfo property. To get rid of it, you could start by creating your own class with the same property.

JSON marshalling and unmarshalling with SBJSON

I am developing an application for both Android and iPhone and I am having a problem marshalling and unmarshalling on iPhone. With Android it is easy enough, I am using Jackson JSON parser and there are plenty of tutorials online which made it easy to use.
On the iPhone I am using SBJSON parser, however there seems to be a real lack of information online about how to use it effectively.
Take the following piece of JSON
{
"data":{
"name":[
{
"fName":"John",
"lName":"Doe"
},
{
"fName":"Jane",
"lName":"Doe"
}
]
}
}
If I were using Java and using Jackson JSON parser, this would be easy. I would set up a Class like
public class Parse {
private Data data;
//get set data class
Then in the data class
public class Data {
private List<Name> name;
//get set name list
then in the name class
public class Name {
private String fName;
private String lName;
//get setters here
That way I have the data split up into a set of objects so I can retrieve the data I need, I can update the JSON if required from Java, then write it out again into a new JSON file, nice and simple, i.e
ObjectMapper mapper = new ObjectMapper();
Parse test = mapper.readValue(new File("/Users/adam/Documents/JSON/list.json"),
Parse.class);
System.out.println(test.getData().getName().get(0).getfName());
or I could set it doing
test.getData().getName().get(0).setfName("test");
What I want to know, is how do I do this with Xcode using SBJSON. I know how to do parse the data, and print it out, but I want to be able to print it out into a set of objects, make a change, then write it out again as I can with Jackson JSON parser. What I have done is
NSString *file = [[NSBundle mainBundle] pathForResource:#"data" ofType:#"json"];
NSData *Data = [NSData dataWithContentsOfFile:file];
NSString *jsonString = [[NSString alloc] initWithData:Data encoding:NSUTF8StringEncoding];
NSDictionary *dictionary = [jsonString JSONValue];
NSArray *name = [dictionary valueForKeyPath:#"data.name"];
NSLog(#"%#", name);
This will get the array of names, but I want to be able to access the first name and last name of each objects, and then update it if I require. Then Write it out again.
Would anyone be able to point me in the right direction. Is it possible to do the same sort of thing I did with Jackson JSON with SBJSON?
Found out how to do it.
Make a class Called List
#interface List : NSObject{
NSString *fName;
NSString *lName;
}
#property (nonatomic, retain) NSString *fName;
#property (nonatomic, retain) NSString *lName;
#end
Then implementation synthesise
#synthesize fName, lName;
Then code to create object of List and loop through it
NSMutableArray *array = [[NSMutableArray alloc] init];
List * list;
NSArray * listArray = [MainJSON valueForKeyPath:#"data.name"];
for(NSDictionary * listInfo in listArray) {
list = [[List alloc] init];
[list setFName:[listInfo objectForKey:#"fName"]];
[list setLName:[listInfo objectForKey:#"lName"]];
[array addObject:list];
}
for (int i = 0; i < [array count]; i++) {
List* l = [array objectAtIndex: i];
NSLog(#"%#", [l fName]);
NSLog(#"%#", [l lName]);
}
Hope this helps anyone else who was trying to do the same thing I was.
Have you considered using the NSKeyValueCoding protocol? A lot of the hard work can be done for you by setValuesForKeysWithDictionary.