My Home UIView requires current Location coordinates and I wouldn't want it to be called until I have these coordinates. How best can I achieve this?
in this code, the view is called before the update of current location:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
currentLocation = [[CLLocation alloc] init];
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
[locationManager startUpdatingLocation];
TTNavigator *navigator = [TTNavigator navigator];
navigator.persistenceMode = TTNavigatorPersistenceModeAll;
TTURLMap *map = navigator.URLMap;
[map from:#"tt://HomeView" toViewController: viewController];
[navigator openURLAction:[TTURLAction actionWithURLPath:#"tt://HomeView"]];
}
users can have Location service turned off. so I wouldn't do that..
Instead check for the location after the didFinishLaunchingWithOptions, so that your current problem will be solved.
and add one more screen for user to turn on the location service if it's off.
Related
Hello everyone I am trying to get a location update when my app is in background. But the code below does not seems to work. The IF statement is never true. I have also set the necessary keys in the info.plist files. I am running the code in iphone 3GS and ipad 3.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customizatio-n after application launch.
id locationValue = [launchOptions objectForKey:UIApplicationLaunchOptionsLocationKey];
if (locationValue)
{
// create a new manager and start checking for sig changes
locManager = [[CLLocationManager alloc] init];
locManager.delegate = self;
[locManager startMonitoringSignificantLocationChanges];
return YES;
}
I have implemented iOS 6 API for state saving, it works - after I quit the app and launch back in for some milliseconds the restored view controller fly in, but then it's replaced by the main view controller I display at launch.
I'm setting every time the app launch the root view of the main window, so this must be the issue.
Here is my code:
- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[self commonInitializationLaunching:launchOptions];
return YES;
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[self commonInitializationLaunching:launchOptions];
return YES;
}
- (void)commonInitializationLaunching:(NSDictionary *)launchOptions
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
static NSString *const kKeychainItemName = #"OAuthGoogleReader";
self.viewController = [[ViewController alloc] initWithNibName:#"ViewController" bundle:nil];
self.navController = [[UINavigationController alloc] initWithRootViewController:self.viewController];
GTMOAuth2Authentication *auth;
auth = [GTMOAuth2ViewControllerTouch authForGoogleFromKeychainForName:kKeychainItemName
clientID:kClientID
clientSecret:kClientSecret];
self.window.rootViewController = self.navController;
[self.window makeKeyAndVisible];
BOOL isSignedIn = [auth canAuthorize];
if (isSignedIn) {
NSLog(#"Signed");
}else{
NSString *scope = #"https://www.google.com/reader/api/";
GTMOAuth2ViewControllerTouch *viewController;
viewController = [[GTMOAuth2ViewControllerTouch alloc] initWithScope:scope
clientID:kClientID
clientSecret:kClientSecret
keychainItemName:kKeychainItemName
delegate:self
finishedSelector:#selector(viewController:finishedWithAuth:error:)];
[self.navController pushViewController:viewController animated:YES];
// self.window.rootViewController = viewController;
}
});
}
You can see that in -(void)commonInitializationLaunching:(NSDictionary *)launchOptions
I'm setting my window's root view. I don't know what to put in there. Perhaps check if there is saved state and then load this method? But how?
Thanks!
Here is what I've tried following Rob's advice:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
if (!self.isRestored) {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
}
[self commonInitializationLaunching:launchOptions];
[self.window makeKeyAndVisible];
return YES;
}
with nothing in willFinishLaunching...
I also removed by window code from my commonInitializationLaunching method.
Storyboards will do most of the heavy lifting for you, such as restoring the window. Using code, however, will not restore the window. You will need to hold on to your root view controller using the encoder. Your code will look something like this:
NSString * const AppDelegateRootVCKey = #"AppDelegateRootVCKey";
- (void)application:(UIApplication *)application willEncodeRestorableStateWithCoder:(NSCoder *)coder {
[coder encodeObject:self.window.rootViewController forKey:AppDelegateRootVCKey];
}
- (void)application:(UIApplication *)application didDecodeRestorableStateWithCoder:(NSCoder *)coder {
// Grabs the preserved root view controller.
UIViewController * vc = [coder decodeObjectForKey:AppDelegateRootVCKey];
if (vc) {
UIWindow * window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
window.rootViewController = vc;
window.restorationIdentifier = NSStringFromClass([window class]);
// The green color is just to make it obvious if our view didn't load properly.
// It can be removed when you are finished debugging.
window.backgroundColor = [UIColor greenColor];
self.window = window;
}
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
if (!self.window) {
UIWindow *window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// The blue color is just to make it obvious if our view didn't load properly.
// It can be removed when you are finished debugging.
window.backgroundColor = [UIColor blueColor];
UIViewController *root = // However you create your root.
window.rootViewController = root;
window.restorationIdentifier = NSStringFromClass([window class]);
self.window = window;
}
[self commonInitializationLaunching:launchOptions];
[self.window makeKeyAndVisible];
return YES;
}
Another gotcha to watch out for is to make sure that your UINavigationControllers and UITabBarControllers have restoration identifiers.
State restoration is generally integrated with storyboards. If you're using a storyboard, you should not be creating your own window, view controllers, etc. You should let the storyboard do this for you. What's happening is that the storyboard is doing all the state restoration, and then you're creating a new window and laying it on top of all that. If that's the case, you're probably creating two copies of your UI on every launch. You're just not noticing it.
If you are constructing your entire interface in code (not a recommended approach, but it does work), then you need to determine whether state restoration happened before creating your UI. This is fairly simple:
In your commonInitializationLaunching:, initialize only non-UI elements (things that wouldn't ever be in state-preservation). This is the place to handle things that the UI elements might rely on during state restoration. You don't have any of these in your current code.
In application:didDecodeRestorableState:, set an app delegate ivar to indicate that state was restored.
In application:didFinishLaunchingWithOptions:, after running commonInitializationLaunching:, check your ivar. If state wasn't restored, create a UI.
Do remember that the commonInitializationLaunching: pattern only exists for backward compatibility with iOS 5. If you don't need that, then just put non-UI in willFinish and UI in didFinish (if state wasn't restored).
I am having some issues implementing RestKit/CoreData with my application. Using the RKTwitterCoreData example application and pointing it to my web service for the json feed, I get the resulting tableview:
The issues encountered so far:
Refresh generates a new core data entry even though i have primaryKeyAttribute set to the orderID.
cell textLabel displays an odd orderID that doesn't match with my web service
Here is my applicationDidFinishLaunchingWithOptions:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Initialize RestKit
RKObjectManager* objectManager = [RKObjectManager managerWithBaseURLString:#"http://mywebservice.com"];
// Enable automatic network activity indicator management
objectManager.client.requestQueue.showsNetworkActivityIndicatorWhenBusy = YES;
NSString *databaseName = #"RKTwitterData.sqlite";
objectManager.objectStore = [RKManagedObjectStore objectStoreWithStoreFilename:databaseName usingSeedDatabaseName:nil managedObjectModel:nil delegate:self];
RKManagedObjectMapping* statusMapping = [RKManagedObjectMapping mappingForClass:[Order class] inManagedObjectStore:objectManager.objectStore];
statusMapping.primaryKeyAttribute = #"orderID";
[statusMapping mapKeyPath:#"id" toAttribute:#"orderID"];
[statusMapping mapAttributes:#"created_at", nil];
// Register our mappings with the provider
[objectManager.mappingProvider setObjectMapping:orderMapping forResourcePathPattern:#"/orders"];
// Create Window and View Controllers
RKTwitterViewController* viewController = [[[RKTwitterViewController alloc] initWithNibName:nil bundle:nil] autorelease];
UINavigationController* controller = [[UINavigationController alloc] initWithRootViewController:viewController];
UIWindow* window = [[UIWindow alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];
[window addSubview:controller.view];
[window makeKeyAndVisible];
return YES;
}
And the json result at /orders:
Any advice for dealing with this issue? Thanks!
Doh! The reason was because the twitter API isn't key value coding compliant. Once i changed:
[objectManager.mappingProvider setObjectMapping:orderMapping forResourcePathPattern:#"/orders"];
with:
[objectManager.mappingProvider setObjectMapping:orderMapping forKeyPath:#"orders"];
It worked again!
Thanks and hope it helps someone.
The alerts appear for a split-second or did not show when application launches in project with ARC (without using ARC all it's OK). (I add CoreLocation framework and I import it to project).
My code:
#import <CoreLocation/CoreLocation.h>
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
CLLocationCoordinate2D coordinate;
CLLocationManager *locationManager = [[CLLocationManager alloc] init];
NSLog(#"jestem po okienku ");
if (locationManager.locationServicesEnabled == NO)
{
coordinate.latitude = 0.0;
coordinate.longitude = 0.0;
}
else
{
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startUpdatingLocation];
CLLocation *location = [locationManager location];
if (!location) {
coordinate.latitude = 0.0;
coordinate.longitude = 0.0;
}
// Configure the new event with information from the location.
coordinate = [location coordinate];
}
return YES; }
You are storing the location manager pointer in a local variable. So ARC is free to release that location manager before returning from this method.
If you wish to keep that location manager alive for longer you need to keep a longer term strong reference to it. Like an ivar or property.
I converted my app to ARC and removed all the pre-build release errors. It launches, but will crash (EXC_BAD_ACCESS) as soon as I call any method (all of which are attached to UIButtons). I also noticed that it will ask if the user will allow for the app to use the user's location, but the alert will disappear before the user can answer yes or no.
I feel like there's some very basic setting I'm missing causing this.
Here's the first method called, it won't let the user actually say if they'll allow location services. The alert fires then disappears. Does this help anyone's diagnosis?
-(void)startLocation
{
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.desiredAccuracy = kCLLocationAccuracyBest;
[locationManager startUpdatingLocation];
}
Also, here's my didFinishLaunchingWithOptions method
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
UINavigationController *nav = [[UINavigationController alloc] init];
StartPageViewController *start = [[StartPageViewController alloc]init];
NSManagedObjectContext *context = [self managedObjectContext];
if (!context)
{
// Handle the error.
}
start.managedObjectContext = context;
nav.viewControllers = [NSArray arrayWithObjects:start, nil];
[_window addSubview:[nav view]];
[self.window makeKeyAndVisible];
return YES;
}
Try retaining your navigation controller by making it a strong property on your delegate.
At the moment, I don't see any code that would cause ARC not to release nav at the end of the method. That would release start, which would release context.
All I needed to change (so far) was:
self.window.rootViewController = nav;
instead of:
[_window addSubview:[nav view]];