How can I persist an HTML file in my iOS application? - ios

I have registered my app to be able to open HTML files. I would like the app to keep the last HTML file it opened... If I open a new HTML file, I would like it to overwrite the last one opened.
I have attempted to user the Documents directory and its not working for me. I have also tried using NSUserDefaultsto no avail. Here is what i currently have:
-(BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url
{
ViewController *vc = (ViewController *)self.window.rootViewController;
[vc loadFileWithUrl:url];
[[NSUserDefaults standardUserDefaults] setURL:[url fileReferenceURL] forKey:#"amd"];
return YES;
}
I kill the application entirely, then - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions is called. Here is how that method looks:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSURL *url = [[NSUserDefaults standardUserDefaults] URLForKey:#"amd"];
if (url)
{
ViewController *vc = (ViewController *)self.window.rootViewController;
[vc loadFileWithUrl:url];
}
return YES;
}
url is always nil :(
PS: I have also tried storing the HTML file in its string representation, and I am able to get that to persist in the Documents folder, but when I try to load that string using:
[webView loadHTMLString:htmlString]; the page never loads. I think that has something to do with the Javascript but I'm not too sure.

The user defaults are saved when the app goes to the background, or when you call -synchronize on the user defaults. When developing, you often don't put the app into background, but just kill it through XCode, in which case nothing gets saved. You can save the user defaults by pressing the home button on your iPhone/iPad, and killing the app in XCode 1second later.
Also, you should put a log statement into your first method, like NSLog(#"saving amd to %#", [url fileReferenceURL]); to be sure that it really gets saved!

It seems that you forgot to call
[[NSUserDefaults standardUserDefaults] synchronize];
Docs:
Writes any modifications to the persistent domains to disk and updates
all unmodified persistent domains to what is on disk.

Related

How to manage state in ios objective c

I’m new in iOS development. My question is, I’ve two view controllers.
viewController - A viewController - B
Now, if i killed the app from the viewController - A and than relaunch the app. than app must be open the viewController - A. and if i killed the app from the viewController - B and than relaunch the app. than app must be open the viewController - B.
Can anyone help me, I’ve done the RND but can not find the proper solution.
Thanks
Create a sharedDelegate in AppDelegate.m file
+(AppDelegate *)sharedDelegate {
return (AppDelegate *) [UIApplication sharedApplication].delegate;
}
in AppDelegate.h
+ (AppDelegate *)sharedDelegate;
#property (nonatomic, strong) NSString *currentViewContoller;
when push to any contoller then set AppDelegate's currentViewContoller to new VC
YourViewController *vc=[[YourViewController alloc] init];
[self.navigationController pushViewController:vc animated:YES];
[AppDelegate sharedDelegate].currentViewContoller = NSStringFromClass([YourViewController class]);
now when app is terminated
- (void)applicationWillTerminate:(UIApplication *)application {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
[[NSUserDefaults standardUserDefaults]setObject:[AppDelegate sharedDelegate].currentViewContoller forKey:#"currentVC"];
}
now when app launched first time check previous controller when app terminated
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSString *string=[[NSUserDefaults standardUserDefaults] valueForKey:#"currentVC"];
and push this class
UIViewController *object = [[NSClassFromString(string) alloc] init...];
}
applicationWillTerminate you can use but it will only get called if user quit app from forground If your app is in background and then user quit app then applicationWillTerminate will not get called.
So, you have to take care of applicationDidEnterBackground.
So, when app enter in background (i.e call applicationDidEnterBackground ) or call applicationWillTerminate save state(your current VC) in your user defaults.
Now in your didFinishLaunchingWithOptions set that view controller as rootviewcontroller or whatever way that you want to manage it.
reference : Apple documentation for applicationWillTerminate
PS : You should not manage app like this. It is horrible way!! If possible then run your app as normal flow!
If you're using Storyboards you can use the Restoration Identifier to communicate the App which controller to launch as first
https://developer.apple.com/library/ios/featuredarticles/ViewControllerPGforiPhoneOS/PreservingandRestoringState.html

Custom URL schemes ios 9

Alright I think I am close to a solution here. I think I must be missing something small. Hope you guy can help.'
I am trying to have another app open another custom app and run a method from that app that is being called through the URL scheme. I understand that in ios 9 they made it manitory to define in the info.plist the key
<key>LSApplicationQueriesSchemes</key>
<array>
<string>URLScheme0</string>
<string>URLScheme1</string>
<string>URLScheme2</string>
ect....
</array>
And I think I have done that properly. Though I want a confirm on this and other thing. Firstly, do I add this to the info.plist of the "calling" app, or the "receiving" app, or BOTH? As, I have it now it is with both. When I remove it from the calling apps plist I get the error.
"This app is not allowed to query for scheme xxx”
Keep in mind I have also included in the plist for the receiving app the URL types and URL schemes array with the same scheme names.
The the calling app I have a button mapped with this methods code:
- (IBAction)killMethod:(id)sender {
NSString *customURL = #"TurnOffRelay://";
if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:customURL]]) {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:customURL]];
} else {
UIAlertController* alert = [UIAlertController alertControllerWithTitle:#"URL error" message:#"No custom URL defined for Kill Relay" preferredStyle:UIAlertControllerStyleAlert];
[self presentViewController:alert animated:YES completion:nil];
}
}
and for the receiving app I have in the appDelegate.m :
- (BOOL)application:(UIApplication *)application OpenURL:(NSURL *)url sourceApplication:(NSString *) sourceApplication annotation:(id)annotation {
NSLog(#" Calling application: %#", sourceApplication);
NSLog(#"URL scheme: %#", [url scheme]);
if ([sourceApplication isEqualToString:#"net.ble.relay"]) {
if ([[url scheme] isEqualToString:#"TurnOffRelay://"]) {
ViewController *viewController = [[ViewController alloc] init];
[viewController killSwitch];
NSLog(#"Running killSwitch");
}
return YES;
}
else
return NO;
}
With what I have right now running I am able to actually press the button in the "calling" app and from there the "receiving" app opens, but alas, the method I want to run doesn't run inside of the if statements. I am wondering what I am doing wrong. I will gladly answer any questions about things I may have missed. This has been bothering me all day. Would like some sort of guidance. Thanks in advance.
pay attention to if ([[url scheme] isEqualToString:#"TurnOffRelay://"]) 。 url scheme is TurnOffRelay rather than TurnOffRelay://.
So, after changing the OpenURL to openURL and then noticing that the sourceApplication name was wrong. I am guessing that if I had typed in the correct application to use, as in, the actual name of the application that was "calling" the If block would have proceeded correctly. But I am sure, also, that if I had not changed the openURL I would have been stuck again.
Thanks for the help. Its now working as intended.

Facing issue in Document sharing

I am on some document sharing issue. My iPhone has two applications. One app "SharingApp" shares a file from its bundle to another app "ViewerApp" using Document Interaction Controller. By default, the shared file will be saved to the document directory of "ViewerApp" under folder named "Inbox". I can get the url in didFinishLaunchingWithOptions: of "ViewerApp" as
NSURL *url = (NSURL*)[launchOptions valueForKey: UIApplicationLaunchOptionsURLKey];
This scenario works perfectly if the "ViewerApp" is not been launched.
The problem I have is, incase, if the "ViewerApp" is in background state(or not killed) and if the file is shared from "SharingApp", applicationDidBecomeActive: is called in appDelegate of "ViewerApp". So, I couldn't able to get the url as the didFinishLaunchingWithOptions: method is not called(ViewerApp is already launched). "ViewerApp" just opens with the last shared url before entering to the background state.
How can I handle to get the url in applicationDidBecomeActive:? Please, share some ideas if you have come across this kind of issue.
Thanks for your ideas.
You should implement the following UIApplicationDelegate method
- (BOOL)application:(UIApplication *)application
openURL:(NSURL *)url
sourceApplication:(NSString *)sourceApplication
annotation:(id)annotation
This should solve your problem since this method will be called when your viewer app is in background
I ran into this exact same issue. The problem is that didFinishLaunchingWithOptions is not called when an application is already open but brought to the foreground. I took my code out of didFinishLaunchingWithOptions and instead put it inside handleOpenURL (also on the app delegate page)
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url{
if (url != nil && [url isFileURL])
{
MainViewController *frontViewController = [[MainViewController alloc] init];
[frontViewController handleOpenURL:url]; //function on my main view controller class to do the necessary action
return YES;
}
else
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error" message:#"Cannot Handle Opening This File." delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil];
[alert performSelectorOnMainThread:#selector(show) withObject:nil waitUntilDone:YES];
return NO;
}
}

How to retrive the value from NSUserDefault before my app loads...?

Im having a ViewController on which on clicking a button, label gets updated. I want is, each time the app opens it should retain its old value. Im able to write every value in NSUserDefault but not getting how to write the value on label before the app loads.
Example:
In first run the label is having the value 5.
In second run the label should contain the same value 5, and if i made any changes that change should be there in third run.
Thanx...
In your AppDelegate, the very first method gets called after launching an App is,
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
return YES;
}
and for other cases such as from inactive to active state of your application use,
- (void)applicationDidBecomeActive:(UIApplication *)application
{
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
I recommend Reading, Apple's iOS application lifecycle documentation.
Here's how to retrieve a stored value from NSUserDefaults and set the value for your label when your ViewController loads:
- (void)viewDidLoad
{
[super viewDidLoad];
self.myLabel.text = [[NSUserDefaults standardUserDefaults] objectForKey:#"mySavedValue"];
}
I'm assuming your button is already hooked up to an action something like this that will save the value to the standardUserDefaults when clicked:
- (IBAction)buttonPressed:(id)sender
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:self.myLabel.text forKey:#"mySavedValue"];
[defaults synchronize];
}

Implementing SSO return a Blank view

I'm trying to implement SSO following the Tutorial:
https://developers.facebook.com/docs/mobile/ios/build/
At the end of Step 3, I'm supposed to Test my App running it on Simulator. The Run succeeded but all I see is a Blank View (screen). I'm not sure if I need to create the view called "authorization dialog" including the FB logo, buttons, etc or if it's automatically created by code I've implemented using Facebook SDK.
Also, I'm using a storyboard and wonder if that's the problem.
I think that it's because you have once signed in and now you haven't logged out so it is already authorized and hence you cannot see anything :)
Is your initial ViewController blankView ? Because the SSO only validates/autorize the session, you need to implement the UI in your ViewController.
If you implement it in Storyboard I suggest you to do most of the code in your controller file, since I was stucked there for quite long time. But make sure to put this code in the app delegate file.
#pragma mark Facebook
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
return [self.facebook handleOpenURL:url];
}
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication: (NSString *)sourceApplication annotation:(id)annotation {
return [self.facebook handleOpenURL:url];
}
Also in the delegate file you should instantiate the Facebook object before you use the in the above methods.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
viewController *controller = [[viewController alloc] init];
// Initialize Facebook
facebook = [[Facebook alloc] initWithAppId:#"Your app ID in string" andDelegate:controller];
// Override point for customization after application launch.
return YES;
}

Resources