Insert Array in SQLite database? - arrays

Okay,
I am a noob and want to get a array from my server and insert it into a SQLite database table. My code is below. Please help!
- (void)getAlbums {
// Get Albums
NSString *userId;
userId = #"1";
NSString *post =[NSString stringWithFormat:#"userid=%#", userId];
NSString *hostStr = #"********************************************?";
hostStr = [hostStr stringByAppendingString:post];
NSData *dataURL = [NSData dataWithContentsOfURL: [ NSURL URLWithString: hostStr ]];
NSString *serverOutput = [[NSString alloc] initWithData:dataURL encoding: NSASCIIStringEncoding];
//Create Array
NSArray *myWords = [serverOutput componentsSeparatedByString:#" "];
// Output server response
NSLog(serverOutput);
//Initialize the array.
NSMutableArray *listOfItems = [[NSMutableArray alloc] init];
listOfItems = [[NSArray arrayWithObjects: myWords, nil] retain];
NSString *test;
while (*test in listOfItems) {
[sqlite executeNonQuery:#"INSERT INTO photo_albums VALUES (?, ?);", variableOne, variableTwo];
}
}

there is more than one issue in this code.
NSMutableArray *listOfItems = [[NSMutableArray alloc] init];
this will leak in the next line because you reassign another item to the variable. Change it into:
NSArray *listOfItems;
listOfItems = [[NSArray arrayWithObjects: myWords, nil] retain];
this does not what you think it does. It will initialize an array with the array myWords as a "member", it won't add the objects from myWords.
But why does this line exist anyway? myWords is already an array. And the retain which doesn't get released would be another leak.
NSString *test;
while (*test in listOfItems) {
this is just wrong. use:
for (test in listOfItems) {
[sqlite executeNonQuery:#"INSERT INTO photo_albums VALUES (?, ?);", variableOne, variableTwo];
where the f do you get variableOne and variableTwo from? And why do you loop through your listOfItems if you don't use the NSString named test?
}
no problem with the closing bracket.
Oh and serverOutput doesn't get released too, so there is another leak. And I'm pretty sure that the encoding isn't ascii.
Start over with the iOS 101, learn the basics and ignore sqlite for the next 2 weeks.

Related

How to add null or nil value in "dynamic NSArray" in Objective-C

I am facing a problem regarding to add Null or nil value in NSArray. Actually I am adding Null value because my array count is not same. I am adding three array in Custom TableViewCell two array are from webservice and one array is from database. I am saving IndexPath in core data and then retrieving it.
As shown in Image I am saving indexPath in String and convert it in NSInteger from DidSelectAtIndexPath and show it in cellForRowAtIndexPath. My problem is, it's getting override because it is stored in string. So that I save it in coredataa and retrieve it but I get problem for mismatch count of array in cellforrowatindexpath. My code is like this
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *STI=#"STI";
AuditTableViewCell *cell = (AuditTableViewCell *)[tableView dequeueReusableHeaderFooterViewWithIdentifier:STI];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"AuditTableViewCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
cell.accessoryType=UITableViewCellAccessoryNone;
}
cell.audittitlelbl.text=[NSString stringWithFormat:#"%#",[idarray objectAtIndex:indexPath.row]];
cell.auditdesclbl.text=[NSString stringWithFormat:#"%#",[namearray objectAtIndex:indexPath.row]];
NSManagedObject *device2 = [devices objectAtIndex:indexPath.row];
NSMutableArray *Checkarray=[devices valueForKey:#"Key"]; // Hear in this array I am getting Index count problem
NSLog(#"Device =%#",device2);
NSLog(#"Check Array =%#",Checkarray);
if(indexPath.row == CurrentIndexPath)
{
cell.listlbl.text=GlobalString;
[cell setBackgroundColor:[UIColor greenColor]];
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
CurrentIndexPath=indexPath.row;
NSLog(#"Current Index Path =%ld",(long)CurrentIndexPath);
GlobalIndexPath = [[NSString stringWithFormat: #"%ld", (long)CurrentIndexPath] mutableCopy];
NSManagedObjectContext *context = [self managedObjectContext];
if (self.device) {
// Update existing device
[device setValue:GlobalStringChk forKey:#"Key1"];
[device setValue:GlobalIndexPath forKey:#"Key"];
} else {
// Create a new device
NSManagedObject *newDevice = [NSEntityDescription insertNewObjectForEntityForName:#"Device" inManagedObjectContext:context];
[newDevice setValue:GlobalStringChk forKey:#"Key1"];
[newDevice setValue:GlobalIndexPath forKey:#"Key"];
}
NSError *error = nil;
// Save the object to persistent store
if (![context save:&error]) {
NSLog(#"Can't Save! %# %#", error, [error localizedDescription]);
}
[Audittable reloadData];
NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:#"Device"];
self.devices = [[managedObjectContext executeFetchRequest:fetchRequest error:nil] mutableCopy];
}
This is my code hear I am saving indexpath in coredata and retrieving it in array. I have a problem for count of array in cellforrowatindexpath. How can I add Null or nil value in array so that it count get same. My Array is a dynamic array.The main problem is that I need to change the colour of cell if user click on it.when I store the value in NSInteger and convert it into indexpath I can change the colour But only for one cell at a time.When I click on other cell integer value get override. So for that I save it to core data and retrive but when I fetch core data array in cellforrowatindexpath it crash because of different count .Thanks in Advance!
We cannot add nil directly inside a collection like NSMutableArray as it will raise an exception. If at all it is required to add nil inside collections like NSMutableArray, we can do so by using a singleton class NSNull.
For instance, we have a array of type NSMutableArray, we can add nil using NSNull as-
[array addObject:#"string"];
[array addObject:[NSNull null]];
...
and so on...
The NSNull class defines a singleton object used to represent null values in collection objects (which don’t allow nil values).
First you can't add elemets in NSArray, you must use NSMutableArray instead. Second thing you can not add nil in your NSMutableArray.
So, you should add empty string instead of nil something like,
NSMutableArray *arr = [[NSMutableArray alloc]init];
[arr addObject:#""];
or you can add NSNull Object like,
[arr addObject:[NSNull null]];
And you can check that string is empty or not when want to display in UI something like(if added empty string),
NSString *tempStr = [arr objectAtIndex:0];
if (tempStr.length > 0) {
NSLog(#"string is not empty.");
}
else{
NSLog(#"Sring is empty");
}
Ok I got your problem. You actually wants to merge data from 3 different array into one single cell, but the problem is your array count is different for each array. Yes you can do this but you have to change the way of coding.
Lets assume you have 3 arrays a1, a2 and a3, with counts:
a1.count = 5,
a2.count = 8,
a3.count = 10
Here I'm assuming a1 is array of NSString while a2 & a3 are arrays with numbers (NSIntegers)
Now create one simple class inheriting from NSObject. We call it as AuditTableViewDao. It is simple Data Access Object
#import <UIKit/UIKit.h>
#interface AuditTableViewDao : NSObject
#property (nonatomic) NSString *checkForWhat;
#property (nonatomic) NSString *methodMeasures;
#property (nonatomic) NSString *visualInspections;
- (instancetype)initWithCheckForWhat:(NSString *)checkForWhat methodMeasures:(NSString *)methodMeasures visualInspections:(NSString *)visualInspections;
#end
Then in .m file of this AuditTableViewDao.m, write implementation to initialize.
Then in your ViewComtroller.m file, create one property
#property (nonatomic) NSMutableArray *arrayAuditTableViews;
in viewDidLod, write
self.arrayAuditTableViews = [[NSMutableArray alloc] init];
for (NSInteger index=0; index < a3.count; index++) {
AuditTableViewDao *auditTableViewDao = nil;
if (index < a1.count) {
auditTableViewDao = [[AuditTableViewDao alloc] initWithCheckForWhat:((NSString *)[a1 objectAtIndex:index]) methodMeasures:[NSString stringWithFormat:#"%d", [a2 objectAtIndex:index]] visualInspections:[NSString stringWithFormat:#"%d", [a3 objectAtIndex:index]]];
}
else if (index < a2.count) {
auditTableViewDao = [[AuditTableViewDao alloc] initWithCheckForWhat:"" methodMeasures:[NSString stringWithFormat:#"%d", [a2 objectAtIndex:index]] visualInspections:[NSString stringWithFormat:#"%d", [a3 objectAtIndex:index]]];
}
else if (index < a3.count) {
auditTableViewDao = [[AuditTableViewDao alloc] initWithCheckForWhat:"" methodMeasures:"" visualInspections:[NSString stringWithFormat:#"%d", [a3 objectAtIndex:index]]];
}
[self.arrayAuditTableViews addObject:auditTableViewDao];
}
And finally in your cellForRowAtIndexPath, Use object of arrayAuditTableViews at perticular index path.
You need to add null in your array like this:
[yourArray addObject:[NSNull null]];
Add null
[array addObject:[NSNull null]];
nil is not an object that you can add to an array: An array cannot
contain nil. This is why addObject:nil crashes.
Don't need to save the index Path in core data and don't need to add Null or nill value.
Just alloc NSMutableArray in viewDidLoad method
NSMutableArray *_selectedIndexPath = [[NSMutableArray alloc] init];
Then in didSelectRowatIndexPath addObject in array like this
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (![_selectedIndexPath containsObject:indexPath]) { // Check if array does not contain selecting cell, add this cell to array
[_selectedIndexPath addObject:indexPath];
[tableView reloadData];
}
}
And then in Cellforrowatindexpath
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
if ([_selectedIndexPath containsObject:indexPath]) {
cell.backgroundColor=[UIColor greenColor];
}
else
{
cell.backgroundColor=[UIColor whiteColor];
}
}
And you can change your colour without using core data and null or nil value.

Objective-C - How to write an array to a file?

I have a text file that I can scan (NSScanner) and tag. The results are stored in an array. The structure is two strings, one for english and one for greek.
I want to write an output file that maintains the array structure. I presume I can create a plist file for this purpose.
However, I'm stuck and need help to create this file.
I have a test whether the file was created, but I get this result:
outgoingWords.count: 442
2014-08-12 17:54:17.369 MyScanner[97350:2681695] *** Assertion failure in -[ViewController checkArray], /Users/david/Desktop/Word Scanning/MyScanner/MyScanner/ViewController.m:98
2014-08-12 17:54:17.373 MyScanner[97350:2681695] Failed to set (contentViewController) user defined inspected property on (NSWindow): writeToFile failed
The code I'm using so far is as follows:
-(void)checkArray {
//do stuff to verify the array
long i = outgoingWords.count;
NSString *tempString = [NSString stringWithFormat:#"%li", i];
NSLog(#"outgoingWords.count: %#", tempString); //442
NSArray *tempArray2 = [outgoingWords copy];
NSString *path = [[NSBundle mainBundle] pathForResource:#"/Users/David/Desktop/alfa2" ofType:#"plist"];
BOOL success = [tempArray2 writeToFile:path atomically:YES];
NSAssert(success, #"writeToFile failed");
}
Could someone either identify what I'm missing, or point me to an existing answer I can use (I've looked)..
Many thanks..
edit. I've also tried the approach in this SO question. But get the same result.
NSString *path = [[NSBundle mainBundle] pathForResource:#"/Users/David/Desktop/alfa2" ofType:#"plist"];
NSString *error;
NSData *data = [NSPropertyListSerialization dataFromPropertyList:tempArray2 format:NSPropertyListBinaryFormat_v1_0 errorDescription:&error];
BOOL success = [NSKeyedArchiver archiveRootObject:data toFile:path];
NSAssert(success, #"archiveRootObject failed");
Problem is that you are writing to the bundle, which is not allowed. You should write to a path in your document or other directory, for example:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
filePath = [documentsDirectory stringByAppendingPathComponent:#"FileName.xxx"];
[data writeToFile:filePath atomically:NO];

Coding error prevents NSMutableArray from returning data after ALAssetsLibrary query

I've written the following code (iOS 6) to try to recover the list of photos from an album (albumName) using ALAssetLibrary. The code compiles and according to the static analyzer I don't have memory leaks or other issues, but the NSLog statement. The code successfuly finds the photo album and if I break inside the loop I can see that the data are being written to the Dictionary. But they are not being emplaced as objects in the Array!
I am sure this is an oversight on my part but I am not able to spot it. Any help appreciated, and maybe the correct answer will help someone else. AlAssets has been difficult for me!
Thanks in advance
TF Redfield
(NSMutableArray )retrieveImageNames: (NSString)albumName
{
ALAssetsLibrary* assetsLibrary = [[ALAssetsLibrary alloc] init];
NSMutableArray* assetGroups = [[NSMutableArray alloc] init];
[assetsLibrary enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock:^(ALAssetsGroup *group, BOOL *stop)
{
if (group)
{
[group setAssetsFilter:[ALAssetsFilter allPhotos]];
[group enumerateAssetsUsingBlock:^(ALAsset *asset, NSUInteger index, BOOL *stop)
{
if (asset)
{
//compare the names of the albums
if ([albumName compare: [group valueForProperty:ALAssetsGroupPropertyName]]==NSOrderedSame)
{
NSMutableDictionary *workingDictionary = [[NSMutableDictionary alloc] init] ;
[workingDictionary setObject:[asset valueForProperty:ALAssetPropertyType] forKey:#"UIImagePickerControllerMediaType"];
[workingDictionary setObject:[UIImage imageWithCGImage:[[asset defaultRepresentation] fullScreenImage]] forKey:#"UIImagePickerControllerOriginalImage"];
[workingDictionary setObject:[[asset valueForProperty:ALAssetPropertyURLs] valueForKey:[[[asset valueForProperty:ALAssetPropertyURLs] allKeys] objectAtIndex:0]] forKey:#"UIImagePickerControllerReferenceURL"];
[assetGroups addObject:workingDictionary];
//If I place the log here I get data
//NSString * temp = [NSString stringWithFormat:#"%d", [assetGroups count]];
//NSLog(#"%#",temp);
[workingDictionary release];
}
}
}];
}
} failureBlock:^(NSError *error)
{
NSLog(#"error enumerating AssetLibrary groups %#\n", error);
}];
NSString * temp = [NSString stringWithFormat:#"%d", [assetGroups count]];
NSLog(#"%#",temp);
return assetGroups;
[assetsLibrary release];
[assetGroups release];
}
enumerateGroupsWithTypes is an asynchronous call. You have returned your array before it gets filled.

Best way to populate this array using .txt file?

I'm looking to make SEVERAL arrays populated with words. Eventually I want to be able to just pull a random word from the array and display it (I've mastered that). What I'm wondering is what is the best way to populate this array. Should I just type in:
[NSArray arrayWithObjects:#"word1",#"word2",#"word3",#"word4",#"word5",nil]
or is there a better way where the words are stored in a .txt file and I can just have a loop add each word in the text file to the Array?
I'm looking at filling the arrays with 100's of words. Any and all help is appreciated :D.
UPDATE
After doing some research I found this here. It seems to be exactly what I wanted. The only thing is it gives me a warning
'stringWithContentsOfFile' is deprecated
I know the full NSString method is:
stringWithContentsOfFile:(NSString *) encoding:(NSStringEncoding) error:(NSError **)
But I don't know what to put for encoding (and I'm assuming I can just put 'nil' for NSError). Other than that it works like a charm. I might consider switching from paths to urls. Here is the code that I found:
- (NSArray *) readFile:(NSString *) path {
NSString *file = [NSString stringWithContentsOfFile:path];
NSMutableArray *dict = [[NSMutableArray alloc] init];
NSCharacterSet *cs = [NSCharacterSet newlineCharacterSet];
NSScanner *scanner = [NSScanner scannerWithString:file];
NSString *line;
while(![scanner isAtEnd]) {
if([scanner scanUpToCharactersFromSet:cs intoString:&line]) {
NSString *copy = [NSString stringWithString:line];
[dict addObject:copy];
}
}
NSArray *newArray = [[NSArray alloc] initWithArray:dict];
return newArray;
}
You can probably use NSUTF8StringEncoding for the encoding parameter (depending on how you created the file, but this is the most common).
Instead of using NSScanner, you can also simply split the string into lines with the componentsSeparatedByString: method. This reduces your method to just these two lines:
NSString *file = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:NULL];
return [file componentsSeparatedByString:#"\n"];
Btw, you shouldn't name an array variable "dict", this would imply that it's an NS(Mutable)Dictionary.
The less code way to get in a list of words would be:
NSString *path = [[NSBundle mainBundle] pathForResource:#"Words" ofType:#"plist"];
NSArray *words = [[NSArray alloc] initWithContentsOfFile:path];
Then you just have to create a plist that has all the words in it with the root object as an array.
In the method you have above the encoding you are looking for is NSUTF8StringEncoding and you actually should pass an NSError by reference, if something goes wrong the error could be useful:
NSError *anError = nil;
NSString *file = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:&anError];

Saving files in cocoa

I'm sure this is a really easy to answer question but I'm still new to cocoa. I need to save my applications data. The app has 4 text fields and each field needs to be saved into one file. Then when you open the file it needs to know what goes in what field. I'm really stuck with this. Also, I do know how to use the save panel.
A convenient way would be to use PLists:
NSDictionary *arr = [NSDictionary dictionaryWithObjectsAndKeys:
string1, #"Field1", string2, #"Field2", nil];
NSData *data = [NSPropertyListSerialization dataFromPropertyList:arr
format:NSPropertyListXMLFormat_v1_0 errorDescription:nil];
NSSavePanel *panel = [NSSavePanel savePanel];
NSInteger ret = [panel runModal];
if (ret == NSFileHandlingPanelOKButton) {
[data writeToURL:[panel URL] atomically:YES];
}
For deserialization:
NSData *data = [NSData dataWithContentsOfURL:urlOfFile];
NSDictionary *dict = [NSPropertyListSerialization propertyListFromData:data
mutabilityOption:NSPropertyListImmutable
format:nil errorDescription:nil];
NSString *string1 = [dict objectForKey:#"Field1"];
// ... etc.

Resources