How to display data if the device has no network connection? - iphone

I have a situation where I'm presenting data in a UITableView using NSJSONSerialization from an external source. I also have to show this data if the device is in offline mode. What is the best approach to doing this? Do I need an internal db to store the data, check for wifi and if it's unavailable present the local data?
thanks for any help or tutorials you may know of.

I have a similar requirement for an app I am working on. I am pulling the data from parse.com (remote objects) and put the data into core data (local objects). When presenting a table view, I run the parse.com query in the background, which pulls the data and puts it into core data. The table views use NSFetchedResultsController so when changes occur to the core data (local) objects, the table view is updated as the data is retrieved. If off line, nothing is retrieved, so the table view does not update, but is presenting the last update of the objects.

Yes . You can make local database to do that thing.
You can check the wifi status. If net connection is available than display data from the external source and if net connection is not available than display data from the local database.

When you retrieve data from external source when you are online store it locally.
Next time when your app is launched:
Check for network connection
If network connection is available retrieve data and re-write the old content
If network connection is not available use the locally stored data
Data can be stored in plist, database file or as an text file.

You can use a CoreData database i.e. and update the data every time you connect. If you cannot connect, just show the old data.
How to use and how to check WiFi connection SO is offering more than enought content ;)

you can store the data in plist if it is not too much.
-(void)Writetoplist:(NSMutableDictionary*)LoginDetails
{
{
//////// This is used to delete the plist file if exist //////
paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
documentsDirectory = [paths objectAtIndex:0];
plistPath = [documentsDirectory stringByAppendingPathComponent:#"LoginDetails.plist"];
NSError *error;
if(![[NSFileManager defaultManager] removeItemAtPath:plistPath error:&error])
{
//TODO: Handle/Log error
}
/// to write the SP Details in plist file
paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
documentsDirectory = [paths objectAtIndex:0];
// get the path to our plist ("Documents/foo.plist")
plistPath = [documentsDirectory stringByAppendingPathComponent:#"LoginDetails.plist"];
[LoginDetails writeToFile:plistPath atomically:YES];
}
}

Related

How to set iCloud Root in iPhone?

here i created local root for document storage but i want to implement iCloud.so i need to create iCloud Root and also i will check if iCloud available or not. if it is possible to create like Method. here i added my local root method code
- (NSURL *)localRoot {
if (_localRoot != nil) {
return _localRoot;
}
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *artdirectoryPath = [documentsDirectory stringByAppendingPathComponent:#"/Me"];
_localRoot=[[NSURL alloc]initFileURLWithPath:artdirectoryPath];
return _localRoot;
}
You find the iCloud "root" directory using:
NSURL *url = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];
If you have only one ubiquity container for your app, you can pass nil for the argument, otherwise you must pass the container identifier.
You can also use this to check if iCloud is available to your app-- if it returns nil, you can't use iCloud. It's not the best way to check for availability though, because it can block for a while. For a quick, non-blocking check, use this:
id token = [[NSFileManager defaultManager] ubiquityIdentityToken];
And then be sure to observe NSUbiquityIdentityDidChangeNotification in case the availability changes.
However: this is nowhere near enough to start using iCloud for documents. You can't just read/write files in that directory and have iCloud do the right thing. At an absolute minimum you'll need:
NSMetadataQuery to find documents that exist on the cloud server but are not downloaded locally.
-[NSFileManager startDownloadingUbiquitousItemAtURL:error:] to tell iCloud to begin downloading documents you've found with the metadata query.
Coordinated access via NSFileCoordinator, and notifications of changes via NSFilePresenter.
Apple has a lot of documentation, and videos from WWDC that will help with this.

how to rename image captured in objective c?

In my application I need to capture image as well as save it on local library and on server using FTP. Now I need to follow a format for image name while saving it on the server. I am able to capture and save the image on local library. But I am unable to find any method to change the name of the Image. Suppose I need to rename it as Productname-UserId.png Is there any way? Kindly help.
Thank you.
UIImagePNGRepresentation(UIImage*) is likely what you're looking for. You can save a UIImage as a PNG file in the Application Documents folder, then upload that to a server. The code to do this is quite trivial, so if you could post the code you're trying to use, that would be helpful to understanding, and recommending a solution for you.
Here's a short clipping from my code that does exactly this:
UIImage * image; // Some image you want to send
NSString * docDirWithSlash = [[self applicationDocumentsDirectory] stringByAppendingString:#"/"];
NSString * pngFile = [docDirWithSlash stringByAppendingString:file]; // <-- Change the string "file" to reflect the name you want.
[UIImagePNGRepresentation(image) writeToFile:pngFile atomically:YES];
// Send pngFile to the server here
Where applicationDocumentsDirectory looks like this:
- (NSString *) applicationDocumentsDirectory
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectoryPath = [paths objectAtIndex:0];
return documentsDirectoryPath;
}
The real question here is where do you want the file name to be specific? On the device or on the server. In case of device use Charles answer, otherwise you should look at http protocol(file upload part). Actually it doesn't matter what name the file have on you local device, as when you send it to the server over http, you can provide any name. The tricky part here is that the server you are uploading to should take that parameter into account when saving that file. So if you are uploading to a server that you don't have hand on and it does some self naming convention - you probably stuck. If it's yours - look at how you're saving files on the server side and if you are taking in account that "filename" parameter...P.S. And don't forget to pass that argument to the upload request :)

How to cache or store parsed xml file?

My app parses an xml file from my server, but I want to store parsed xml file and next start of my app, controller initially should load stored xml file, then controller should parse it again to check that there may be an update I did on xml file, if there is, new elements parsed should also be stored again.
I am referring to those app such as magazines, newspaper apps. When you open those kind of apps, it loads stored data that was downloaded previous session. Yet, after it loads, it starts to update the data, and it stores new update again.
Where do I start? What do you guys suggest?
Thanks in advance...
You can use CoreData or SQLite (use Objective-C wrapper FMDB https://github.com/ccgus/fmdb) to persist your XML. Then update the database everytime you see a unique id. Depends on how your XML data is.
It's actually quite easy to store to the documents directory. For example:
NSData *data; //this is your xml file
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docs = [paths objectAtIndex:0];
NSString *filename = [NSString stringWithFormat:#"test.xml"];
NSString *path = [docs stringByAppendingPathComponent:filename];
[data writeToFile:path atomically:YES];
Then to retrieve it later, you can get the path like above, but retrieve the file instead of writing it:
NSData *data = [NSData dataWithContentsOfFile:path];
either CoreData or SQLite can do the trick

How do I find the size of my Core Data persistent store and the free space on the file system?

I am working on a database application using the Core Data framework. In this application I need to display how much data the application currently is using on the iPhone. Is there any way to do this?
I found this answer on the Apple Dev Forums to be useful for finding disk space available on the apps' home directory partition (note there are currently two partitions on each device).
Use NSPersistentStoreCoordinator to get your store collection.
Use NSFileManager to get each stores' size in bytes (unsigned long long)
NSArray *allStores = [self.persistentStoreCoordinator persistentStores];
unsigned long long totalBytes = 0;
NSFileManager *fileManager = [NSFileManager defaultManager];
for (NSPersistentStore *store in allStores) {
if (![store.URL isFileURL]) continue; // only file URLs are compatible with NSFileManager
NSString *path = [[store URL] path];
DebugLog(#"persistent store path: %#",path);
// NSDictionary has a category to assist with NSFileManager attributes
totalBytes += [[fileManager attributesOfItemAtPath:path error:NULL] fileSize];
}
Note that the code above is in a method of my app delegate, and it has a property persistentStoreCoordinator.
Your persistent store in Core Data is just a file on the file system. You access and possibly create this file when you create your Core Data stack. The following code will print the size of a persistent store and the free space of the file system, in bytes:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *persistentStorePath = [documentsDirectory stringByAppendingPathComponent:#"persistentstore.sqlite"];
NSError *error = nil;
NSDictionary *fileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:persistentStorePath error:&error];
NSLog(#"Persistent store size: %# bytes", [fileAttributes objectForKey:NSFileSize]);
NSDictionary *fileSystemAttributes = [[NSFileManager defaultManager] attributesOfFileSystemForPath:persistentStorePath error:&error];
NSLog(#"Free space on file system: %# bytes", [fileSystemAttributes objectForKey:NSFileSystemFreeSize]);
This assumes that your persistent store is named persistentstore.sqlite and is stored in the documents directory for your application. If you are uncertain as to the name of your persistent store, look for where you alloc and init your NSPersistentStoreCoordinator. The name of the store should be specified somewhere in the code around there.
Note that the values you get back from the file and file system attributes dictionaries are NSNumbers, so you'll need to convert them to scalar types if you want to work with the file sizes in that manner. One thing to be careful of is that these values are in bytes, so for multi-gigabyte filesystems you might run into number size limitations with 32-bit integer data types.
Not sure where I saw it, but I believe that removing entries from the database will not necessarily shrink the database file. SQLite reclaims the storage internally and re-uses it. (This is typical of RDBMSs.) I believe there's a command-line utility somewhere that will compact it, but that's not going to help you if your app wants shrink the file to the dataset (to reclaim space for the OS, for example).
So while the file size method will give you a sense of the high-water-mark size of the database, it's not necessarily going to tell you the amount of storage used by your dataset.

Sqlite3 gives "no such table" error on iPhone

I created a sqlite3 database, created tables and insert some data. I can retrieve using select query by using terminal application.
But when i add this database to my iPhone application resources and try to access data programatically I get error as "no such table: table name"
Why does this happen?
sqlite3_open() creates an empty database for you if the database path does not exist. So, it is possible that the path you gave it does not lead you to the intended file. With an empty database, you get "no such table" a lot.
The DB file is probably not reachable by the iPhone. Try creating the DB from the iPhone app itself.
NSArray *paths = NSSearchPathForDirectoriesInDomains(
NSDocumentDirectory, NSUserDomainMask, YES
);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [
documentsDirectory stringByAppendingPathComponent:#"yourdbname.sql"
];
// Open the database. The database was prepared outside the application.
if (sqlite3_open([path UTF8String], &db_handle) != SQLITE_OK) {
// Even though the open failed,
// call close to properly clean up resources.
sqlite3_close(db_handle);
NSAssert1(0,
#"Failed to open database with message '%s'.",
sqlite3_errmsg(db_handle)
);
}
And the perform your query again. Also, it helps if you check for potential errors on every step of your DB access code.
I had the same error with sqlite3X C++ wrapper.
I use this library in my IE-plugin.
The problem was in unavailability .sqlite base.
Current directory for IE(not plugin) is "C:\Documents and Settings\UserName\desktop\".
When I put my base in this location - problem was solved.