Handling MKDirectionsRequest with iOS6 even when your app is compatible with iOS5 - iphone

I want to make our app compatible with iOS6's MKDirectionsRequest (Transit Directions method). Apple states the best way to do this is:
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
if ([MKDirectionsRequest isDirectionsRequestURL:url]){
}
}
However, what is the best way to ensure this code is only run when the app is running in iOS6, and not iOS5? The app HAS to be compatible with iOS5 as well, but I MKDirectionsRequest is an iOS6.
I can't use compiler directives like:
#ifdefine iOS5
or anything.
Is this the best way?
BOOL atLeastIOS6 = [[[UIDevice currentDevice] systemVersion] floatValue] >= 6.0;
and then:
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
if (atLeastIOS6)
{
if ([MKDirectionsRequest isDirectionsRequestURL:url]){
}
}
}
I just want to make sure I don't crash on iOS5 when checking for openURLs

Don't rely on iOS version. Check if the class exists by using NSClassFromString:
Class directionsRequestClass = NSClassFromString(#"MKDirectionsRequest");
if (directionsRequestClass)
// it exists, so you can use it
else
// doesn't exist, do something else

You can test if the class MKDirectionsRequest is available:
if ([MKDirectionsRequest class]) {
...
}

I have seen numerous posts that discouraged using the system version string. It might have to do with trickiness converting 6.0.1 to a float, but not sure.
The preferred method seems to be to test a selector that appeared in a specific version. As such, I use these two methods to test for iOS 5 or 6 respectively.
+ (BOOL)isOS5Capable {
return ( [UINavigationBar respondsToSelector:#selector(appearance)] );
}
+ (BOOL)isOS6Capable {
return ( [UIView respondsToSelector:#selector(requiresConstraintBasedLayout)] );
}
If you look through the headers in the Apple frameworks, you will see that there are quite a few NS_AVAILABLE macros that specify what version the selector appeared. To create this function for iOS 6, I hunted around for a few minutes to find a static method to simplify the check (so I wouldn't have to allocate a class). By following this practice, you should be able to ensure that your app is version safe for future updates.

Related

Duplicate declaration of method 'application:didRegisterUserNotificationSettings:'

I am working on "react-native-firebase": "^5.5.6", and "react-native-push-notification": "^3.1.9", using react native and I am stuck with error Duplicate declaration of method 'application:didRegisterUserNotificationSettings:' on appDelegate.m
I have tried various solutions found over web and If I comment one of the method, I got error "native module cannot be null"
- (void)application:(UIApplication *)application
didRegisterUserNotificationSettings:(UIUserNotificationSettings
*)notificationSettings {
[[RNFirebaseMessaging instance]
didRegisterUserNotificationSettings:notificationSettings];
}
// Required to register for notifications
- (void)application:(UIApplication *)application
didRegisterUserNotificationSettings:(UIUserNotificationSettings
*)notificationSettings
{
[RCTPushNotificationManager
didRegisterUserNotificationSettings:notificationSettings];
}
I need both the methods in my code without any error. I can use if else or other solutions as well but as I am new to this technology, therefore any help will be appreciated.
Thanks in advance!
I would not recommend mixing features however try this:
- (void)application:(UIApplication *)application
didRegisterUserNotificationSettings:(UIUserNotificationSettings
*)notificationSettings {
[[RNFirebaseMessaging instance]
didRegisterUserNotificationSettings:notificationSettings];
[RCTPushNotificationManager
didRegisterUserNotificationSettings:notificationSettings];
}
So you initialize both, in the same method. Again, not sure why you need both and you should try to keep only one.

background app in iOS that detects incoming phone calls

I need to write a background application in iOS which listens to incoming phone calls on the iPhone.
Is it possible? Can anyone suggest some good pointers ?
Thankyou
This would be very much against Apple's privacy policy and there's no chance an app like this would be approved.
There are call recording apps that sneak around this restriction, though, but they use third party services and no actual built-in iPhone API's.
You can do it in applicationWillEnterForeground using CTCallCenter's CTCallState properties. Don't forget to import the CoreTelephony framework. Here's an example:
#import <CoreTelephony/CTCall.h>
#import <CoreTelephony/CTCallCenter.h>
#import <CoreTelephony/CTCarrier.h>
#import <CoreTelephony/CTTelephonyNetworkInfo.h>
- (void)applicationWillEnterForeground:(UIApplication *)application
{
[callCenter setCallEventHandler:^(CTCall *call) {
if ([[call callState] isEqual:CTCallStateIncoming] || [[call callState] isEqual:CTCallStateDialing]) {
if ([viewController isPlaying])
{
NSLog(#"Call was started.");
}
} else if ([[call callState] isEqual:CTCallStateDisconnected]) {
if (callWasStarted)
{
NSLog(#"Call was ended.");
}
}
}];
}

Facebook - problems with "august_2012" platform migration

I am getting this warning message in an iOS app using FB auth:
ERROR:This endpoint has been deprecated.To temporarily reenable it,you may disable the "august_2012" platform migration. It will be disable permanently on August 1,2012.
The issue is to disable that migration for now. But, it was already disabled, so not sure how to fix this quickly - as opposed to updating the app and pushing it back out to the store which we will do.
I solved it by using the newest ShareKit Version (0.2.1), which I downloaded from GitHut but the same version is also avaliable on getsharekit.com/install.
Next i added the folder "ShareKit" located in "Classes" by drag&dropping in my XCode project (as usual).
For safety reasons, the previouse configuration file has been changed into a class. Set the configuration data for the sharingservices (FB, Twitter,...) in the class "DefaultSHKConfigurator.m". (Btw. I subclassed the DefaultSHKConfigurator so i still have the original structure)
To setup FB, change the settings:
- (NSString*)facebookAppId {
return #"..."; //app-id from facebook (create fb-app first, if not already done)
}
- (NSString*)facebookLocalAppId {
return #"";
}
Than in the application:didFinishLaunchingWithOptions: Method, set the ShareKonfiguration.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
DefaultSHKConfigurator *configurator = [[DefaultSHKConfigurator alloc] init];
[SHKConfiguration sharedInstanceWithConfigurator:configurator];
[configurator release];
//init the rest
..
}
After that, add an URL Scheme (in XCode 4.x select your project, select one target, click "Add"->"Add URL Type") and set the URL Scheme to "fb+your fb-app id" (mine looked like "fb35486..").
To let FB open your app and the user is immeditly able to post content, add
- (void) openFBWithURL:(NSURL*) URL {
if (URL != nil) {
NSString* scheme = [URL scheme];
NSString* prefix = [NSString stringWithFormat:#"fb%#", SHKCONFIG(facebookAppId)];
if ([scheme hasPrefix:prefix]) {
[SHKFacebook handleOpenURL:URL];
}
}
}
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
[self openFBWithURL:url];
return YES;
}
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
[self openFBWithURL:url];
return YES;
}
Than it should be setup and ready for use.

Implementing Testflight.com and Flurry.com exception handling

We are using both testflight.com sdk and flurry.com sdk to track unhandled exceptions. The issue is that no exceptions are picked up by flurry after we added the testflight.com sdk.
The method triggered when an unhandled exception occur looks like this:
void uncaughtExceptionHandler(NSException *exception)
{
[FlurryAnalytics logError:#"ERROR_NAME" message:#"ERROR_MESSAGE" exception:exception];
}
- (BOOL) application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
#if !TARGET_IPHONE_SIMULATOR
NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler);
struct sigaction newSignalAction;
memset(&newSignalAction, 0, sizeof(newSignalAction));
newSignalAction.sa_handler = &signalHandler;
sigaction(SIGABRT, &newSignalAction, NULL);
sigaction(SIGILL, &newSignalAction, NULL);
sigaction(SIGBUS, &newSignalAction, NULL);
[FlurryAnalytics startSession:kFlurryKey];
[TestFlight takeOff:kTestflightKey];
[[UIApplication sharedApplication]
registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge |
UIRemoteNotificationTypeSound |
UIRemoteNotificationTypeAlert)];
[UIApplication sharedApplication].applicationIconBadgeNumber = 0;
#endif
.
.
.
I'm not sure how testflight.com does it, but it seems like they intercept the exception and register the data for themselves without letting the registered method be run?
Are there any way for both of these to coexist?
I got confirmation from the Testflightapp.com team that this is a known issue. They hope to fix in in the next version they said.
I'm not able to test this directly, but the TestFlight documentation seems to say this:
If you do use uncaught exception or signal handlers install your handlers before calling takeOff. Our SDK will then call your handler while ours is running.
They even give some example code which might help you get this working.
I have found a solution on a blog, not sure if it works for Flurry as well, what it says is to call UninstallCrashHandlers method (declared in TestFlight.h) twice after [TestFlight takeOff:#"KEY"] method, and then register other service for which you want to use for crash reporting. See example code for TestFlight vs Crashlytics
Disabling TestFlight’s crash reporting is quite simple. Add the following code your includes in AppDelegate.m:
...
#import TestFlight.h
// Function prototype for UninstallCrashHandler
extern void UninstallCrashHandlers(BOOL restore);
In didFinishLaunchingWithOptions call this method first with NO and then with YES, like:
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[TestFlight takeOff:#"<TestFlightKey>"];
UninstallCrashHandlers(NO);
UninstallCrashHandlers(YES);
[Crashlytics startWithAPIKey:#"<CrashlyticsKey>"];
return YES;
}
ref: http://www.grahamdennis.me/blog/2012/10/21/how-to-disable-testflights-crash-handlers/

applicationWillEnterForeground never called

Hey there, I'm trying Multitasking in the Simulator (I only have a 2nd gen iPod and an iPad) and I'm still having some problems. My testing methods look like this:
- (void)applicationDidBecomeActive:(UIApplication *)application {
NSLog(#"Entering %s",__FUNCTION__);
if (enteredFromBackground) {
NSLog(#"Entering from Background");
enteredFromBackground = NO;
}
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
NSLog(#"Entering %s",__FUNCTION__);
enteredFromBackground = YES;
}
Unforntunately, I'm not seeing the NSLog from applicationWillEnterForeground, that's why I added the line to show me something in applicationDidBecomeActive.
All I get is the
2010-11-20 15:58:12.796 iBeat[45997:207] Entering -[AppDelegate_Shared applicationDidEnterBackground:]
2010-11-20 15:58:18.160 iBeat[45997:207] Entering -[AppDelegate_Shared applicationDidBecomeActive:]
After having this problem in iOS 13, I found out that I was waiting for applicationWillEnterForeground(_ application: UIApplication) to be called instead of sceneWillEnterForeground(_ scene: UIScene).
For more information, read this answer:
enter link description here
Finally I found my problem!
Since I have a universal Application, I have an Appdelegate_Shared, an Appdelegate_iPhone, and an Appdelegate_iPad.
I had an empty implementation of "applicationWillEnterForeground" in the two subclasses but didn't call super!
And then I wondered why the method in Appdelegate_Shared never got called o.O