I need to make an offline browser on my iOS application, which allows the following:
When you have an internet connection (wifi, 3g, 4g, ...) you can download all the web pages you need to read during the day, then you can browse the content also when you have no internet connection.
I import the data from JSON file.
How can I do this?
If you have the data downloaded, save it to the documents directory and check if no internet connection, then load the content from the documents directory.
Get Documentpath
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentPath = [paths objectAtIndex:0];
If you have an NSDictionary:
NSString *path = [NSString stringWithFormat:#"%#",[paths objectAtIndex:0]];
NSDictionary *dict = [[NSDictionary alloc] init];
[dict writeToFile:[path stringByAppendingPathComponent:#"myOfflineData"] atomically:NO];
And to get it:
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:[path stringByAppendingPathComponent:#"myOfflineData"]];
Or save it with a NSString etc.
To catch up your Example:
NSData *jsonData = [NSData dataWithContentsOfURL:[NSURL URLWithString:#"http:......."]];
id jsonObjects = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:nil]; jsonResults = [jsonObjects objectForKey:#"nodes"];
[jsonData writeToFile:[path stringByAppendingPathComponent:#"myOfflineData"] atomically:NO];
And if you are offline:
NSData *jsonData = [[NSData alloc] initWithContentsOfFile:[path stringByAppendingPathComponent:#"myOfflineData"]];
Related
I created a method that first save the json data to the file
and then I am reading the data from the file.
I am able to save and read data when I run on simulator but when I try to run the application on iPhone and debug thru, it does not save or retrieve the data.
- (void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
NSMutableData *retrievedData = [NSMutableData data];
[retrievedData appendData:data];
NSMutableString *allInfo = [[NSMutableString alloc] initWithData:retrievedData encoding:NSASCIIStringEncoding];
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"credentials" ofType:#"json"];
NSData *userCredentials = allInfo;
[userCredentials writeToFile:filePath atomically:YES];
NSError *error;
NSData* JSONData = [NSData dataWithContentsOfFile:filePath];
NSDictionary *JSONDictionary = [NSJSONSerialization JSONObjectWithData:JSONData options:kNilOptions error:&error];
//get the log in information from the credentials file
NSDictionary *login = [JSONDictionary objectForKey:#"login"];
//get the auth_token
NSDictionary *loginInfo = login;
if(loginInfo == NULL)
{
errorMessage.text = #"Invalid username or password";
errorMessage.hidden = NO;
}
else
{
NSString *authCode = [loginInfo objectForKey:#"auth_token"];
[self saveUserCredentials:authCode];
}
}
You should never write file to NSBundle. For the simulator, it seems a bug. Simulator have a lot more bugs than device. It's better to test your app on device instead of on the device if it's possible. Other guys also have seen this problem. See Apple's doc:
Application_Home /AppName.app
This is the bundle directory containing the app itself. Do not write
anything to this directory. To prevent tampering, the bundle directory
is signed at installation time. Writing to this directory changes the
signature and prevents your app from launching again.
I basically did this
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *directory = [paths objectAtIndex:0];
NSString *filepath = [NSString stringWithFormat:#"%#/%#", directory,#"credentials.json"];
And now my code is able to retrieve data on iPhone and as well as on simulator.
I am new to iOS development, and I would like to know how .plist files work in iOS. Can any one help me by giving me an example of how to read an write data to and from a .plist?
Yup:
NSString *rootPath = [[NSBundle mainBundle] bundlePath];
NSString *pListPath = [rootPath stringByAppendingPathComponent:#"Settings.bundle/Root.plist"];
NSDictionary *pList = [NSDictionary dictionaryWithContentsOfFile:pListPath];
Writing to a file isn't too hard either:
NSDictionary *dict;
NSData *data = [NSPropertyListSerialization dataWithPropertyList:dict format:NSPropertyListXMLFormat_v1_0 options:0 error:&error];
[data writeToFile:self.saveToPath atomically:YES];
I am having trouble writing my file into the plist after going through many tutorials, other people's problems and attempting it for myself. I can read the plist with no problems but I cant update it. Below are my codes on how I am writing my data into the plist. Correct me if I made any mistake.
NSString *path = [[NSBundle mainBundle] pathForResource:#"EventAddress" ofType:#"plist"];
NSMutableDictionary *myDictionary = [[NSMutableDictionary alloc] initWithContentsOfFile:path];
NSArray* allmyData = [myDictionary allValues];
// creates and array to store only the event details
NSMutableArray *data = [[NSMutableArray alloc] initWithArray:allmyData];
[data addObject:[[NSMutableDictionary alloc] initWithObjectsAndKeys:tfAddress.text, #"Address", tvEvents.text, #"Events", nil]];
[myDictionary setValue:data forKey:#"Whampo"];
BOOL flag = [myDictionary writeToFile:path atomically:YES];
if (flag){
NSLog(#"write to plist success");
}
NSLog(#"%#", myDictionary);
[myDictionary release];
The path is correct, the file exists, my values in the textView and textField are in the array, but when it comes to the writeToFile, it does not reflect on the file located at the document directory.
EDIT 01:
I found this online, very similar to Nekto's suggestion. But I am thinking on how to implement my code with his. I think its pretty simple, but I cant seem to figure out how to.
NSArray *paths= NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentDirectory = [paths objectAtIndex:0];
NSString *plistDirectory = [NSString stringWithFormat:#"%#/Enterprise",documentDirectory];
NSString *mPath = [plistDirectory stringByAppendingPathComponent:#"Downloads.plist"];
[mDownloadsArray writeToFile:mPath atomically:YES];
iphonesdk.blogspot taken from that site.
EDIT 02:
I used Nekto's suggestion and it worked well. But I am curious why it is returning DocumentsEventAddress.plist rather than EventAddress.plist. My assumption is because of the
NSString *rootPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *plistPath = [rootPath stringByAppendingString:#"EventAddress.plist"];
Where rootPath is returning Document is that right?
I'm writing to file in such way:
NSString *errorDesc = nil;
NSString *rootPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *plistPath = [rootPath stringByAppendingString:TEMPLATES_PATH];
NSDictionary *dict = [NSDictionary dictionaryWithObject:templates forKey:#"templates"];
NSData *plistData = [NSPropertyListSerialization dataFromPropertyList:dict format:NSPropertyListXMLFormat_v1_0 errorDescription:&errorDesc];
if (plistData)
{
[plistData writeToFile:plistPath atomically:YES];
}else
{
NSLog(#"[Error] Application Did Enter Background {saving file error}: %#", errorDesc);
[errorDesc release];
}
Be sure to save file in app documents directory.
I don't believe you can write to a resource. Only files in the documents directory can be written to.
You can't write to files that are located in you Bundle.
The app bundle is read only.
I want to create "UrlPaths.plist" file in my Application and also a dictionary with 4 or 5 objects. Please help me create a plist file and dictionary. And also read data from that plist file.
I want the plist to add the file to resources folder and i want to add Dictionary at that time also.i dont want pragmatical creation of plist but i want reading the data is pragmatically.
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"plist.plist"];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSMutableDictionary *data;
if ([fileManager fileExistsAtPath: path]) {
data = [[NSMutableDictionary alloc] initWithContentsOfFile:path];
}
else {
// If the file doesn’t exist, create an empty dictionary
data = [[NSMutableDictionary alloc] init];
}
//To insert the data into the plist
data[#"value"] = #(5);
[data writeToFile: path atomically:YES];
[data release];
//To retrieve the data from the plist
NSMutableDictionary *savedStock = [[NSMutableDictionary alloc] initWithContentsOfFile:path];
int value1;
value1 = [savedStock[#"value"] intValue];
NSLog(#"%i",value1);
[savedStock release];
If you are about to create Plist without programmatically then follow these steps :
1. Right Click on Files in Left Pane and Select 'New File...' option.
2. Choose Resources from OS X tab.
3. An option for Property List is available.
4. Select an give an appropriate name.
This gets added to your project.
We can get simple understanding about plist as below
Now you can read this data as below
NSString *path = [[NSBundle mainBundle] pathForResource:#"Priority" ofType:#"plist"];
NSDictionary *dictPri = [NSDictionary dictionaryWithContentsOfFile:path];//mm
NSMutableArray *arrMarkets=[[NSMutableArray alloc] initWithArray:[dictPri valueForKey:#"List"]];
NSMutableArray *arrForTable=[[NSMutableArray alloc] init];
NSMutableArray *arrForTable1=[[NSMutableArray alloc] init];
for (NSDictionary *dict in arrMarkets)
{
NSString *strS1=nil;
strS1= [NSString stringWithFormat:#"%#",[dict valueForKey:#"Description"] ];
[arrForTable addObject:strS1];
}
NSLog(#"%#----------------- ",[arrForTable description]);
for (NSDictionary *dict in arrMarkets)
{
NSString *strS2=nil;
strS2= [NSString stringWithFormat:#"%#",[dict valueForKey:#"Name"] ];
[arrForTable1 addObject:strS2];
}
NSLog(#"%#----------------- ",[arrForTable1 description]);
create new plist file -
NSArray *Arr = [NSArray arrayWithObjects:obj1,obj2,nil];
NSData *data = [NSPropertyListSerialization dataFromPropertyList:Arr format:NSPropertyListXMLFormat_v1_0 errorDescription:nil];
[data writeToFile:PlistDataFilePath atomically:YES];
Read data from this plist file -
NSData *data = [NSData dataWithContentsOfFile:PlistDataFilePath];
NSPropertyListFormat format;
NSArray *array = [NSPropertyListSerialization propertyListFromData:data mutabilityOption:NSPropertyListImmutable format:&format errorDescription:nil];
you should read this great tut on plist files - http://www.edumobile.org/iphone/iphone-programming-tutorials/how-to-use-plist-in-iphone/
Now I try to build iPhone application, like magazine online, that can download new magazine form web and store in app (can play offline).
I no idea for implement feature download new magazine form online source and store in the app.
Please help me.
Here's an example how you can download a file to your iPhone and reuse it later (in this case it's stores an HTML document that is then loaded to UIWebView from local store).
// downloading file
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
NSString *dataPath = [paths objectAtIndex:0];
NSString *fileName = [[url path] lastPathComponent];
NSString *filePath = [dataPath stringByAppendingPathComponent:fileName];
if ([[NSFileManager defaultManager] fileExistsAtPath:filePath] == NO) {
NSString *fileString = [NSString stringWithContentsOfURL:url
encoding:NSUTF8StringEncoding
error:nil];
[fileString writeToFile:filePath
atomically:YES
encoding:NSUTF8StringEncoding
error:nil];
}
// use local file
NSURL *loadUrl = [[NSURL alloc] initFileURLWithPath: filePath];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL: loadUrl];
[webView loadRequest: request];
[request release];
[loadUrl release];