Macros not recognized in ios - objective-c

I have set PaidApp =1 in my preprocessor macro.
But when i am trying to implement it in my appdelegate file like below:-
- (void) applicationDidFinishLaunching:(UIApplication*)application
{
m_bootup = 1;
m_showhint = 1; // show hand hint on bootload level 1 only
#ifdef PaidApp
[[NSUserDefaults standardUserDefaults] setInteger:1 forKey:#"adDisabled"];
#endif
}
the compiler just skips it... it does not go into the ifdef condition
i am not getting why this is happening
The below link show how i have defined my macro :-
http://i.imgur.com/wA0X2gw.png?1
And this shows how i have used it :-
http://i.imgur.com/9d2PYup.png?1

Related

Unsupported action method signature. Must return MPRemoteCommandHandlerStatus

I'm getting this error whenever I'm running simulator on iOS 13+. Everything works for iOS 12 and below so I'm not sure what to do here. Is there anything I can change/edit on my end to make react-native-music-control work for iOS 13?
Exception 'Unsupported action method signature. Must return MPRemoteCommandHandlerStatus or take a completion handler as the second argument.' was thrown while invoking enableControl on target MusicControlManager with params ( pause, 1, { } )
This react-native-music-control probably hasn't updated its iOS MediaPlayer methods.
One common method is MediaPlayer's addTarget. Starting iOS 13, this method must return a MPRemoteCommandHandlerStatus. It used to return nothing in previous iOS versions.
For example, if you have a play method that gets called when the Play button is tapped:
- (void) play {
/* start playing */
}
You are probably registering this play to be called when the Media Player's play command is trigged:
[[MPRemoteCommandCenter sharedCommandCenter].playCommand addTarget:self action:#selector(play)];
Then, all you need is to simply change your play method to return a MPRemoteCommandHandlerStatus like this:
- (MPRemoteCommandHandlerStatus) play
{
// if successfully played
return MPRemoteCommandHandlerStatusSuccess;
// else if there's an issue
// return MPRemoteCommandHandlerStatusCommandFailed;
}
This is in Objective-C. Changing the return value in Swift will be simple too.
Reference: https://developer.apple.com/documentation/mediaplayer/mpremotecommand/1622895-addtarget?language=objc
So this plugin is not being maintained anymore I don't know why, so for those using this plugin the solution is really Simple, based on what #CSawy. I was able to fix it.
1 - Change the method signature to MPRemoteCommandHandlerStatus
All the methods that interact with the control are defined as void so change them to MPRemoteCommandHandlerStatus. They are defined in the file MusicControls and I guess you would find it in your plugins folder. For me it was in myProject/plugins/MusiControls.h
These are the methods that require the change
playEvent
pauseEvent
nextTrackEvent
prevTrackEvent
skipForwardEvent
skipBackwardEvent
After changing all the methods signature u should have
(MPRemoteCommandHandlerStatus) playEvent:(MPRemoteCommandEvent *) event;
(MPRemoteCommandHandlerStatus) pauseEvent:(MPRemoteCommandEvent *) event;
(MPRemoteCommandHandlerStatus) nextTrackEvent:(MPRemoteCommandEvent *) event;
(MPRemoteCommandHandlerStatus) prevTrackEvent:(MPRemoteCommandEvent *) event;
(MPRemoteCommandHandlerStatus) skipForwardEvent: (MPSkipIntervalCommandEvent *) event;
(MPRemoteCommandHandlerStatus) skipBackwardEvent: (MPSkipIntervalCommandEvent *) event;
2-Add return to the implementations
Now you should change the implementation of these methods otherwise your app would still be crushing.
Simply open the file MusicControls.m. If you are using Xcode it will highlight the methods for you ... If it's no highlighted then just search for them
For all these functions you will need to add a return ;
For your play event do:
-(MPRemoteCommandHandlerStatus) playEvent:(MPRemoteCommandEvent *)event {
NSString * action = #"music-controls-play";
NSString * jsonAction = [NSString stringWithFormat:#"{\"message\":\"%#\"}", action];
CDVPluginResult * pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsString:jsonAction];
[self.commandDelegate sendPluginResult:pluginResult callbackId:[self latestEventCallbackId]];
return MPRemoteCommandHandlerStatusSuccess;
}
Do this for all the methods and I hope it works.

What is the proper way to detect if unit tests are running at runtime in Xcode?

When I'm running unit tests, I'd like to skip some code (e.g. I don't want [[UIApplication sharedApplication] openURL:..] to run). I'm looking for a runtime check if I'm currently running units tests or not.
I know I have seen code that checks the Objective-C runtime if unit tests are running but am not able to find it anymore.
You can use this method from google-toolbox-for-mac
// Returns YES if we are currently being unittested.
+ (BOOL)areWeBeingUnitTested {
BOOL answer = NO;
Class testProbeClass;
#if GTM_USING_XCTEST // you may need to change this to reflect which framework are you using
testProbeClass = NSClassFromString(#"XCTestProbe");
#else
testProbeClass = NSClassFromString(#"SenTestProbe");
#endif
if (testProbeClass != Nil) {
// Doing this little dance so we don't actually have to link
// SenTestingKit in
SEL selector = NSSelectorFromString(#"isTesting");
NSMethodSignature *sig = [testProbeClass methodSignatureForSelector:selector];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:sig];
[invocation setSelector:selector];
[invocation invokeWithTarget:testProbeClass];
[invocation getReturnValue:&answer];
}
return answer;
}
The reason that NSClassFromString and NSInvocation are used is to allow code compile without linking to xctest or ocunit
Rather that sprinkling "am I testing?" conditionals throughout production code, I isolate the check to one place: main. There, I check for an alternate application delegate for testing. If it's available, I use it instead of the the regular application delegate. This completely bypasses the regular launch sequence:
int main(int argc, char *argv[])
{
#autoreleasepool {
Class appDelegateClass = NSClassFromString(#"TestingAppDelegate");
if (!appDelegateClass)
appDelegateClass = [AppDelegate class];
return UIApplicationMain(argc, argv, nil, NSStringFromClass(appDelegateClass));
}
}
You can read more about this technique here: How to Easily Switch Your iOS App Delegate for Testing
Select the project, and then the test target:
Select Build Settings and choose All and Combined. Type 'preproc' in the search box - you're after Preprocessor Macros.
Add a macro to the Debug configuration called TEST and set it equal to 1:
Then in your code, you can do this:
#ifndef TEST
[[UIApplication sharedApplication] doEvilThingForTesting];
#endif
Or if you have code that you want to only run in a test environment:
#ifdef TEST
[[UIApplication sharedApplication] doAwesomeTestOnlyThing];
#endif
It's not exactly runtime, but the unit tester compiles the code before it runs the tests IIRC, so it should be the same effect - you're essentially modifying the code right before running the tests.
I'm not sure how long this will continue to work, but it works for me right now with Version 9.0 beta 6 (9M214v).
let isTesting = { () -> Bool in
if let _ = ProcessInfo.processInfo.environment["XCTestConfigurationFilePath"] {
return true
} else if let testingEnv = ProcessInfo.processInfo.environment["DYLD_INSERT_LIBRARIES"] {
return testingEnv.contains("libXCTTargetBootstrapInject.dylib")
} else {
return false
}
}()
No build environment or scheme changes are necessary.
It appears that there are two different environment variables in play depending on whether you are running a single test case or the entire test suite. Also, the variable value also differs depending whether or not you are running in simulator or on a real device.
I think you can check like this for Xcode 7.3
-(BOOL) isRunningUnitTests
{
NSDictionary* environment = [ [ NSProcessInfo processInfo ] environment ];
NSString* theTestConfigPath = environment[ #"XCTestConfigurationFilePath" ];
return theTestConfigPath != nil;
}
The easiest (and working in Xcode 7 with XCTest!) way to check is to have a look at the process info for a matching xctest bundle:
static BOOL isRunningTests(void)
{
NSDictionary* environment = [[NSProcessInfo processInfo] environment];
NSString* injectBundle = environment[#"XCInjectBundle"];
return [[injectBundle pathExtension] isEqualToString:#"xctest"];
}
Source: https://www.objc.io/issues/1-view-controllers/testing-view-controllers/#integration-with-xcode
Just use this:
+ (BOOL)isUnitTestRunning
{
Class testProbeClass;
testProbeClass = NSClassFromString(#"XCTestProbe");
return (testProbeClass != nil);
}

Parse Issue: Expected Expression (Objective C)

For what ever reason my xcode has decided it doesn't like me... I'm getting the error stated in the title on this line
- (void)tableViewSelectionDidChange:(NSNotification *)notification
{
NSInteger row = [_tableView selectedRow];
if (row == –1) //<---- this line
{
return;
}
NSString *selectedVoice = [_voices objectAtIndex:row];
[_speechSynth setVoice:selectedVoice];
NSLog(#"new voice = %#", selectedVoice);
}
I do believe that it has something to do with _tableView being befuddled because when I attempted to get the IDE to help me to type (you know when it guesses what you might what to finish your word with by doing an API lookup of available functions) it doesn't show selectedRow as a possibility :(
incase it's needed i've put the .m and .h in a pastebin to save some space on your screens... FYI I'm following the Coca Programming for Mac OSX fourth Edition chapter 6.10
In your line
if (row == –1)
the minus-sign is not the real minus-sign, but an "EN DASH" (Unicode U+2013). Perhaps you accidentally pressed the option-key together with the minus-key when typing that code.
Replacing that character with a minus-sign fixes the problem.
UITableView doesn't have a method called selectedRow.
Perhaps you should be using:
- (NSIndexPath *)indexPathForSelectedRow

conditional compilation warning for constant

QUESTION
I would like to trigger a warning only if my TESTING is YES. Is this possible? What I have now doesn't work. What should I do?
BOOL const TESTING = NO;
#if TESTING == YES
#warning don't forget to turn testing to NO before upload
#endif
ANSWER
Based on the answer below, here is what worked for me:
#define _TESTING // COMMENT THIS OUT TO DISABLE TESTING MODE
#ifdef _TESTING
BOOL const TESTING = YES;
#warning don't forget to turn testing to NO for production
#else
BOOL const TESTING = NO;
#endif
Try replacing what you have with
#ifdef TESTING
#warning //... warning here
BOOL const testingBool = YES;
#else
BOOL const testingBool = NO;
#endif
Then, you need to add TESTING as a "Preprocessor Macro" in your Target's Build Settings (see this question for more details on how to do that).

How do I temporary disable warnings in my objective c source file?

One project I work on has a build system that enforces no warnings.
But I have some code that needs warnings to work. Here is an example
NSString* title = #"";
if ([view respondsToSelector:#selector(title)]) {
title = [view title];
}
After some googling I tried disable warnings for the code block by wrapping that code area with
#pragma warning disable
// my code
#pragma warning restore
Didn't work :(
Anyone know how to do this in Xcode?
Any help is appreciated.
-CV
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wshadow-ivar"
// your code
#pragma GCC diagnostic pop
You can learn about GCC pragma here and to get the warning code of a warning go to the Log Navigator (Command+7), select the topmost build, expand the log (the '=' button on the right), and scroll to the bottom and there your warning code is within square brackets like this [-Wshadow-ivar]
Edit
For clang you can use
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wshadow-ivar"
// your code
#pragma clang diagnostic pop
There are a number of things you could do here, but the simplest would probably to rewrite your code just a tad.
NSString* title = #"";
if ([view respondsToSelector:#selector(title)]) {
title = [(id)view title];
}
Casting the view variable to id before sending the message should ensure that so long as a method named -title exists anywhere, it'll stay silent.
Another option:
NSString* title = #"";
if ([view respondsToSelector:#selector(title)]) {
title = [view performSelector:#selector(title)];
}
This is a little different from the above, in that it doesn't require the file to "see" any method named title; but it's a bit more wordy.
Edit: I'm aware that neither of these approaches actually turn of warnings for any amount of time, but rather suppress them.
Suppression, when done correctly, at least, is usually better than simply ignoring.
The closest way to do what you want is to use the GCC diagnostic pragma. See this question for details.