NSUserDefaults and adding void* data in it - iphone

I have data in format
struct CardData
{
void* frontimagedata;
}
I need to hold this data in NSUserDefaults [ Need to use this data after app launch again after exit]. I am not using database in my app.
I need to use this format only as this CardData information is shared between Obj c and c++ code.
can anyone help me on this.
thanks,
Sagar

If you save it into an NSData object you'll be able to store it in NSUserDefaults.
NSData* data = [NSData dataWithBytes:frontimagedata length:datalen];

Related

How to import an .sqlite3/.sqlite file to ios application?

I was having an excel file.
I have converted that file to .csv format and import that file to base and converted it into .sqlite file.
So the question is that:
Is there any way to import it into an ios app and manipulate the data.
Is there any way to use it like core data or import that file into core data.
Kindly refer any good tutorial preferably video tutorial or some other good one.
You can use it directly with FMDB library: https://github.com/ccgus/fmdb
Another option is to import that file into core data, but it is a little tricky. You can do it if you follow these steps:
Create empty SQLite database in your application and run your app in simulator.
Open simulator directory on your computer and locate SQLite database file.
Look inside it with SQLite command line tool or something like "SQLite Data Browser" GUI tool (http://sqlitebrowser.sourceforge.net/).
Import your data to this database file without changing structure and data in core data meta tables.
Finally you have SQLite database file ready to be used with core data. So you put it into your app bundle.
On first application launch you should copy your SQLite database file to appropriate directory (you know where you should put your file - you already found it in simulator app directory) before configuring core data stack.
It sounds a bit complicated but it works ;)
Nice article about shipping pre-populated data for core data: http://www.objc.io/issue-4/importing-large-data-sets-into-core-data.html
Update
Please note the updated response.
Is there any way to import it (SQLite) into an ios app and manipulate the data?
You can import a sqlite file into Xcode, by simply adding it as a resource using Add New File... However you would have limited ability to use it jointly with Core Data (unless it was created with Core Data). One can review the objc.io article referenced earlier that covers how to deal with prepopulated data in an Xcode project. Here is the pertinent section of that article.
NSFileManager* fileManager = [NSFileManager defaultManager];
NSError *error;
if([fileManager fileExistsAtPath:self.storeURL.path]) {
NSURL *storeDirectory = [self.storeURL URLByDeletingLastPathComponent];
NSDirectoryEnumerator *enumerator = [fileManager enumeratorAtURL:storeDirectory
includingPropertiesForKeys:nil
options:0
errorHandler:NULL];
NSString *storeName = [self.storeURL.lastPathComponent stringByDeletingPathExtension];
for (NSURL *url in enumerator) {
if (![url.lastPathComponent hasPrefix:storeName]) continue;
[fileManager removeItemAtURL:url error:&error];
}
// handle error
}
NSString* bundleDbPath = [[NSBundle mainBundle] pathForResource:#"seed" ofType:#"sqlite"];
[fileManager copyItemAtPath:bundleDbPath toPath:self.storeURL.path error:&error];
NSDictionary *infoDictionary = [NSBundle mainBundle].infoDictionary;
NSString* bundleVersion = [infoDictionary objectForKey:(NSString *)kCFBundleVersionKey];
NSString *seedVersion = [[NSUserDefaults standardUserDefaults] objectForKey:#"SeedVersion"];
if (![seedVersion isEqualToString:bundleVersion]) {
// Copy the seed database
}
// ... after the import succeeded
[[NSUserDefaults standardUserDefaults] setObject:bundleVersion forKey:#"SeedVersion"];
Assuming one wanted to import a CSV file rather than an Excel or SQLite... Since this is a common question, here is a simple parser that one can use to incorporate CSV data into an Xcode project.
func parseCSV (contentsOfURL: NSURL, encoding: NSStringEncoding, error: NSErrorPointer) -> [(name:String, detail:String, price: String)]? {
// Load the CSV file and parse it
let delimiter = ","
var items:[(name:String, detail:String, price: String)]?
if let content = String(contentsOfURL: contentsOfURL, encoding: encoding, error: error) {
items = []
let lines:[String] = content.componentsSeparatedByCharactersInSet(NSCharacterSet.newlineCharacterSet()) as [String]
for line in lines {
var values:[String] = []
if line != "" {
// For a line with double quotes
// we use NSScanner to perform the parsing
if line.rangeOfString("\"") != nil {
var textToScan:String = line
var value:NSString?
var textScanner:NSScanner = NSScanner(string: textToScan)
while textScanner.string != "" {
if (textScanner.string as NSString).substringToIndex(1) == "\"" {
textScanner.scanLocation += 1
textScanner.scanUpToString("\"", intoString: &value)
textScanner.scanLocation += 1
} else {
textScanner.scanUpToString(delimiter, intoString: &value)
}
// Store the value into the values array
values.append(value as! String)
// Retrieve the unscanned remainder of the string
if textScanner.scanLocation < count(textScanner.string) {
textToScan = (textScanner.string as NSString).substringFromIndex(textScanner.scanLocation + 1)
} else {
textToScan = ""
}
textScanner = NSScanner(string: textToScan)
}
// For a line without double quotes, we can simply separate the string
// by using the delimiter (e.g. comma)
} else {
values = line.componentsSeparatedByString(delimiter)
}
// Put the values into the tuple and add it to the items array
let item = (name: values[0], detail: values[1], price: values[2])
items?.append(item)
}
}
}
return items
}
(Source article)
Another option is to use the Core Data Editor tool originally mentioned in the Ray W. list of tools. This GUI editor tries to make handling CSV data imports easier.
Is there any way to use it like core data or import that file into core data?
So a SQLite database is not the same as Core Data (which is an object graph persistence...). I was about to go into my diatribe here, but Apple's Core Data FAQ says it better than I could...:
How do I use my existing SQLite database with Core Data?
You don’t. Although Core Data supports SQLite as one of its persistent
store types, the database format is private. You cannot create a
SQLite database using native SQLite API and use it directly with Core
Data (nor should you manipulate an existing Core Data SQLite store
using native SQLite API). If you have an existing SQLite database, you
need to import it into a Core Data store (see Efficiently Importing
Data).
So that's the official answer. Anything else offered is just a way to work around the fact that one is not supposed to do this.
However, given that you also have a CSV file you do have some other options. In the past I've built a file reader to examine the contents of a CSV file using a stream reader. Here is the gist of that, however my file likely had some other formatting so this probably needs tweaking. You can also look at using any object that reads the contents of a file. For example; a much simpler technique comes to mind:
Use the initWithContentsOfFile on the NSString class
Gives you a string with the CSV in memory
Iterate the string for each line
Loop through the line using commas and do something with each piece of data
NSString *fileContents = [NSString stringWithContentsOfFile:#"myfile.txt"];
NSArray *lines = [fileContents componentsSeparatedByString:#"\n"];
//loop and split each line in lines array into useful data
Let's say you really want to use SQLite in iOS, warnings notwithstanding... You can add the sqlite3 library to your project. Full details are available on how to use SQLite instead of Core Data. One of the many online tutorials is at AppCoda
The basics are covered (sample project):
Saving...
- (IBAction)saveInfo:(id)sender {
// Prepare the query string.
NSString *query = [NSString stringWithFormat:#"insert into peopleInfo values(null, '%#', '%#', %d)", self.txtFirstname.text, self.txtLastname.text, [self.txtAge.text intValue]];
// Execute the query.
[self.dbManager executeQuery:query];
// If the query was successfully executed then pop the view controller.
if (self.dbManager.affectedRows != 0) {
NSLog(#"Query was executed successfully. Affected rows = %d", self.dbManager.affectedRows);
// Pop the view controller.
[self.navigationController popViewControllerAnimated:YES];
}
else{
NSLog(#"Could not execute the query.");
}
}
Editing...
-(void)loadInfoToEdit{
// Create the query.
NSString *query = [NSString stringWithFormat:#"select * from peopleInfo where peopleInfoID=%d", self.recordIDToEdit];
// Load the relevant data.
NSArray *results = [[NSArray alloc] initWithArray:[self.dbManager loadDataFromDB:query]];
// Set the loaded data to the textfields.
self.txtFirstname.text = [[results objectAtIndex:0] objectAtIndex:[self.dbManager.arrColumnNames indexOfObject:#"firstname"]];
self.txtLastname.text = [[results objectAtIndex:0] objectAtIndex:[self.dbManager.arrColumnNames indexOfObject:#"lastname"]];
self.txtAge.text = [[results objectAtIndex:0] objectAtIndex:[self.dbManager.arrColumnNames indexOfObject:#"age"]];
}
Deleting...
-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath{
if (editingStyle == UITableViewCellEditingStyleDelete) {
// Delete the selected record.
// Find the record ID.
int recordIDToDelete = [[[self.arrPeopleInfo objectAtIndex:indexPath.row] objectAtIndex:0] intValue];
// Prepare the query.
NSString *query = [NSString stringWithFormat:#"delete from peopleInfo where peopleInfoID=%d", recordIDToDelete];
// Execute the query.
[self.dbManager executeQuery:query];
// Reload the table view.
[self loadData];
}
}
Re: Kindly refer any good tutorial preferably video tutorial or some
other good one.
The following tutorial should fill your need. There are quite a few tutorials on this topic you can check out www.lynda.com for a detailed walk through on building an iOS app with SQLite (some cost involved for full access however search Youtube as they post sample movies covering these topics all the time).
http://www.youtube.com/watch?v=bC3F8a4F_KE (see 1:17 in video)
If you have an .sql file, you just import it to your project by going to File - Add Files.
Also, keep in mind that if you leave your .sql file in your bundle, it will be read only.
So, unless you want it to be read only, you should make new group and put your .sql there.

Get objects from a NSDictionary

I get from an URL this result :
NSString *result = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
it looks like this :
[{"modele":"Audi TT Coup\u00e9 2.0 TFSI","modele_annee":null,"annee":"2007","cilindre":"4 cyl","boite":"BVM","transmision":"Traction","carburant":"ES"},
{"modele":"Audi TT Coup\u00e9 2.0 TFSI","modele_annee":null,"annee":"2007","cilindre":"4 cyl","boite":"BVM","transmision":"Traction","carburant":"ES"}]
So it contains 2 dictionaries. I need to take the objects from all the keys from this result. How can I do this?
I tried this : NSDictionary vehiculesPossedeDictionary=(NSDictionary *)result;
and then this : [vehiculesPossedeDictinary objectForKey:#"modele"]; but this is not working.
Please help me... Thanks in advance
What you have is a JSON string which describes an "array" containing two "objects". This needs to be converted to Objective-C objects using a JSON parser, and when converted will be an NSArray containing two NSDictionarys.
You aren't going to be able to get your dictionary directly from a string of JSON. You are going to have to going to have to run it through a JSON parser first.
At this point, there is not one build into the iOS SDK, so you will have to download a third-party tool and include it in your project.
There are a number of different JSON parser, include TouchJSON, YAJL, etc. that you can find and compare. Personally, I am using JSONKit.
#MatthewGillingham suggests JSONKit. I imagine it does fine, but I've always used its competitor json-framework. No real reason, I just found it first and learned it first. I do think its interface is somewhat simpler, but plenty of people do fine with JSONKit too.
Using json-framework:
require JSON.h
...and then
NSString *myJsonString = #"[{'whatever': 'this contains'}, {'whatever', 'more content'}]";
NSArray *data = [myJsonString JSONValue];
foreach (NSDictionary *item in data) {
NSString *val = [item objectForKey:#"whatever"];
//val will contain "this contains" on the first time through
//this loop, then "more content" the second time.
}
If you have array of dictionary just assign objects in array to dictionary like
NSDictionary *dictionary = [array objectAtIndes:0];
and then use this dictionary to get values.

iPhone/iPad Base64 Image Encoded - Convert to UIImage

I have a base64 encoded image recieved via a web service.
How do I convert that string to a UIImage?
Obj-c or C# answers are fine.
Ian
First you need to convert the base64-encoded data into an NSData. This previous question seems to be a good resource on how to do that.
Then you just pass that NSData object to [UIImage imageWithData:...].
I havent't tried but here there seems to be a working sample code ;)
Hope it helps
In iPhone Monotouch C# this is how it is done:
byte[] encodedDataAsBytes = System.Convert.FromBase64String (Base64String);
string decoded = System.Text.Encoding.Unicode.GetString (encodedDataAsBytes);
NSData data = NSData.FromString (decoded, NSStringEncoding.ASCIIStringEncoding);
return UIImage.LoadFromData (data);
I was not able to get BahaiResearch's MonoTouch code to work -- an exception was thrown in NSData -- but was successful with the following:
byte[] encodedDataAsBytes = Convert.FromBase64String ( base64String );
NSData data = NSData.FromArray ( encodedDataAsBytes );
return UIImage.LoadFromData ( data );

iphone SDK displaying image in uitableview from image data in JSON string

I'm new to this, so here goes..
I'm having a problem with displaying images in uitableview, that are downloaded from a mysql database. Here's what I'm doing:
converting images using UIImagePNGRepresentation.
uploading to MYSQL database via webservice.
So far so good..
The images are downloaded from MYSQL using JSON.
NSDictionary used to create array of image data from JSON String.
[UIImage imageWithData:[imageArray objectAtIndex:indexpath.row]] fails with error: [NSCFString bytes]: unrecongnised selector sent to instance.
I can understand why this is happening, but don't know how to resolve it. The imageWithData is expecting NSData object, but I've converted the string to NSData with no success.
Any help will be greatly appreciated.
Are you converting to and from data properly?
To data:
NSData* theData;
theData = [theNSString dataUsingEncoding:NSASCIIStringEncoding];
To string:
NSString* theNSString;
theNSString = [[NSString alloc] initWithData:theData encoding:NSASCIIStringEncoding];
Thanks for your response.
Yes I was doing the conversion to/from data, as you stated, the only difference being that I was using NSUTF8StringEncoding rather than NSASCIIStringEncoding.
I've tried it with NSASCIIStringEncoding, but the results is the same. It seems that the converted data is different to that stored on the database.
The data from the JSON string (NSData to NSString) is:
<89504e47 0d0a1a0a 0000000d 49484452 00000087 0000005a 08020000 001d25d2 ac000020 00494441 54780174 bd7778dc e775e73b bdf78e19 f40e1004 c002764a ec942cdb b12ccb55 b6e3123b 8e539e44 cecd3ad7 bbc9c6eb f4dc2789 b3297e9c 4d1cc5b1 2dc9b264 4bb22a25 52ec0401 16f45e07 184ceff3 ....
However, the conversion back to NSData gives the following data:
<3c383935 30346534 37203064 30613161 30612030 30303030 30306420 34393438 34343532 20303030 30303038 37203030 30303030 35612030 38303230 30303020 30303164 32356432 20616330 30303032 30203030 34393434 34312035 34373830.....
This may be the same, but [UIImage imageWithData:theData] returns null image.

Compress/Decompress NSString in objective-c (iphone) using GZIP or deflate

I have a web-service running on Windows Azure which returns JSON that I consume in my iPhone app.
Unfortunately, Windows Azure doesn't seem to support the compression of dynamic responses yet (long story) so I decided to get around it by returning an uncompressed JSON package, which contains a compressed (using GZIP) string.
e.g
{"Error":null,"IsCompressed":true,"Success":true,"Value":"vWsAAB+LCAAAAAAAB..etc.."}
... where value is the compressed string of a complex object represented in JSON.
This was really easy to implement on the server, but for the life of me I can't figure out how to decompress a gzipped NSString into an uncompressed NSString, all the examples I can find for zlib etc are dealing with files etc.
Can anyone give me any clues on how to do this? (I'd also be happy for a solution that used deflate as I could change the server-side implementation to use deflate too).
Thanks!!
Steven
Edit 1: Aaah, I see that ASIHTTPRequest is using the following function in it's source code:
//uncompress gzipped data with zlib
+ (NSData *)uncompressZippedData:(NSData*)compressedData;
... and I'm aware that I can convert NSString to NSData, so I'll see if this leads me anywhere!
Edit 2: Unfortunately, the method described in Edit 1 didn't lead me anywhere.
Edit 3: Following the advice below regarding base64 encoding/decoding, I came up with the following code. The encodedGzippedString is as you can guess, a string "Hello, my name is Steven Elliott" which is gzipped and then converted to a base64 string. Unfortunately, the result that prints using NSLog is just blank.
NSString *encodedGzippedString = #"GgAAAB+LCAAAAAAABADtvQdgHEmWJSYvbcp7f0r1StfgdKEIgGATJNiQQBDswYjN5pLsHWlHIymrKoHKZVZlXWYWQMztnbz33nvvvffee++997o7nU4n99//P1xmZAFs9s5K2smeIYCqyB8/fnwfPyK+uE6X2SJPiyZ93eaX+TI9Lcuiatvx/wOwYc0HGgAAAA==";
NSData *decodedGzippedData = [NSData dataFromBase64String:encodedGzippedString];
NSData* unGzippedJsonData = [ASIHTTPRequest uncompressZippedData:decodedGzippedData];
NSString* unGzippedJsonString = [[NSString alloc] initWithData:unGzippedJsonData encoding:NSASCIIStringEncoding];
NSLog(#"Result: %#", unGzippedJsonString);
After all this time, I finally found a solution to this problem!
None of the answers above helped me, as promising as they all looked. In the end, I was able to compress the string on the server with gzip using the chilkat framework for .net ... and then decompress it on the iphone using the chilkat framework for iOS (not yet released, but available if you email the guy directly).
The chilkat framework made this super easy to do so big thumbs up to the developer!
Your "compressed" string is not raw GZIP'd data, it's in some encoding that allows those bytes to be stored in a string-- looks like base-64 or something like it. To get an NSData out of this, you'll need to decode it into the NSData.
If it's really base-64, check out this blog post an accompanying code:
http://cocoawithlove.com/2009/06/base64-encoding-options-on-mac-and.html
which will do what you want.
Once you have an NSData object, the ASIHTTPRequest method will probably do as you like.
This worked for me:
from a string gzipeed, then base64 encoded
to un-gzipped string (all utf8).
#import "base64.h"
#import "NSData+Compression.h"
...
+(NSString *)gunzipBase64StrToStr:(NSString *)stringValue {
//now we decode from Base64
Byte inputData[[stringValue lengthOfBytesUsingEncoding:NSUTF8StringEncoding]];//prepare a Byte[]
[[stringValue dataUsingEncoding:NSUTF8StringEncoding] getBytes:inputData];//get the pointer of the data
size_t inputDataSize = (size_t)[stringValue length];
size_t outputDataSize = EstimateBas64DecodedDataSize(inputDataSize);//calculate the decoded data size
Byte outputData[outputDataSize];//prepare a Byte[] for the decoded data
Base64DecodeData(inputData, inputDataSize, outputData, &outputDataSize);//decode the data
NSData *theData = [[NSData alloc] initWithBytes:outputData length:outputDataSize];//create a NSData object from the decoded data
//NSLog(#"DATA: %# \n",[theData description]);
//And now we gunzip:
theData=[theData gzipInflate];//make bigger==gunzip
return [[NSString alloc] initWithData:theData encoding:NSUTF8StringEncoding];
}
#end
I needed to compress data on the iPhone using Objective-c and decompress on PHP. Here is what I used in XCode 11.5 and iOS 12.4:
iOS Objective-c Compression Decompression Test
Include libcompression.tbd in the Build Phases -> Link Binary With Library. Then include the header.
#include "compression.h"
NSLog(#"START META DATA COMPRESSION");
NSString *testString = #"THIS IS A COMPRESSION TESTTHIS IS A COMPRESSION TESTTHIS IS A COMPRESSION TESTTHIS IS A COMPRESSION TESTTHIS IS A COMPRESSION TESTTHIS IS A COMPRESSION TEST";
NSData *theData = [testString dataUsingEncoding:NSUTF8StringEncoding];
size_t src_size = theData.length;
uint8_t *src_buffer = (uint8_t*)[theData bytes];
size_t dst_size = src_size+4096;
uint8_t *dst_buffer = (uint8_t*)malloc(dst_size);
dst_size = compression_encode_buffer(dst_buffer, dst_size, src_buffer, src_size, NULL, COMPRESSION_ZLIB);
NSLog(#"originalsize:%zu compressed:%zu", src_size, dst_size);
NSData *dataData = [NSData dataWithBytes:dst_buffer length:sizeof(dst_buffer)];
NSString *compressedDataBase64String = [dataData base64EncodedStringWithOptions:0];
NSLog(#"Compressed Data %#", compressedDataBase64String);
NSLog(#"START META DATA DECOMPRESSION");
src_size = compression_decode_buffer(src_buffer, src_size, dst_buffer, dst_size, NULL, COMPRESSION_ZLIB);
NSData *decompressed = [[NSData alloc] initWithBytes:src_buffer length:src_size];
NSString *decTestString;
decTestString = [[NSString alloc] initWithData:decompressed encoding:NSASCIIStringEncoding];
NSLog(#"DECOMPRESSED DATA %#", decTestString);
free(dst_buffer);
On the PHP side I used the following function to decompress the data:
function decompressString($compressed_string) {
//NEED RAW GZINFLATE FOR COMPATIBILITY WITH IOS COMPRESSION_ZLIB WITH IETF RFC 1951
$full_string = gzinflate($compressed_string);
return $full_string;
}