Disable "show live issues" in conditionally compiled code (Swift + Xcode 11)? - swift

I'm guessing this is a bug of sorts (and if so I'll file a report)...
If you have "show live issues" enabled in Xcode's Preferences, issues can be flagged even in code that won't be compiled because of a conditional compilation block.
Here's a trivial example. When using Xcode 11.5 or earlier the "!!!" causes a syntax error to be flagged even though that code is never compiled:
#if swift(>=5.3)
print("Swift >= 5.3")
!!! // <-- causes "show live issues" to complain
#else
print("Swift < 5.3")
#endif
Is there any workaround for this that people are aware of?
A "real" example might use syntax that is only available with Swift 5.3+ within the first section and < 5.3 syntax in the second section.
Note that the code will actually compile and run but "show live issues" is getting tripped up by the presence of "invalid" code and ideally it wouldn't check code that won't be compiled.
Note that Objective-C doesn't have this issue, the following doesn't result in any "show live issues" warning if XCODE12 isn't defined:
#if defined(XCODE12)
NSLog(#"XCODE12");
!!!
#else
NSLog(#"XCODE11");
#endif

Related

Swift macros not detected

After reading this stackoverflow post, I tried to introduce macros in my project.
I have the following code in a sample macOS CommandLine tool.
#if ELDIABLO
NSLog ("ELDIABLO macro detected!")
#else
NSLog ("ELDIABLO macro not detected!")
#endif
The ELDIABLO macro is declared in Target->BuildSettings->SwiftCompiler/OtherSwiftFlags (prefixed with -D).
This works.
SwiftMacros[73110:12048088] Detected ELDIABLO macro!!
Now, when I transferred the same concept to my original project it doesn't work. I always get
ELDIABLO macro not detected!
According to another stackoverflow post, the macros should be defined in Target->BuildSettings->SwiftCompiler/ActiveCompilationConditions (without -D prefix).
I tried that too, but didn't work.
What's wrong here? What am I missing?
I'm using Xcode 13.4.
My project structure: One target (the app) dependent on many other targets (static libs). All macro settings are applied to the app target (not to the static libs).
I was setting the macro in the app target, but the code which uses macro is one of the other targets i.e static libs, though the static libs targets are added as a dependency for the app target.
After adding the macro to the static lib target, it works.
That means the macro didn't find your "Condition setting", ex: ELDIABLO
So now you need to open your Project/[Your in-use target]/Build Settings.
Then, search the setting with the keyword: "active compilation". And, put your CONDITION_CONFIG here. One line for one CONDITION_CONFIG.
Check image below:

Xcode 9.1 upgrade to Swift 4 breaks #ifdef

I've got a project written in Swift 3 that has a number of #if ... #elses scattered throughout; they just check for a certain variable (defined with the -D compiler flag) which is set by my xcode project to know if the project is being built in xcode or with the package manager and does some imports accordingly. For example,
#if XCODE_BUILD
// do some imports that work when built with xcode
#else
// do some imports that won't work when built with xcode
#endif
The code builds just fine via either method.
But, when I select the option to upgrade to Swift 4 (either of the options offered -- "Minimize inference" or "Match Swift 3 behavior"), the code fails to compile so the migration fails. It appears that the #ifs are not being respected or the XCODE_BUILD variable isn't being defined, since the failures occur in the imports that shouldn't happen when being built from Xcode.
Does Swift 4 do something different with #ifs? Does Xcode somehow not define the compiler flags while doing the migration?
You can use #if, #else and #endif, resulting in:
#if XCODE_BUILD
// do some imports that work when built with xcode
#else
// do some imports that won't work when built with xcode
#endif
Apple docs here.
Another answer with some additional details can be found here: https://stackoverflow.com/a/24152730/118091
Previously, I was using the 'Other Swift Flags' build setting in Xcode to pass '-DXCODE_BUILD'. Apparently that setting doesn't work for Swift 4. The new setting that does work is 'Active Compilation Conditions' (it should be set to include XCODE_BUILD, no need for the -D flag).

What does this mean? #if !(arch(x86_64) || arch(arm64))

I came across this unusual code in a tutorial I was using.
#if !(arch(x86_64) || arch(arm64))
func sqrt(a: CGFloat) -> CGFloat {
return CGFloat(sqrtf(Float(a)))
}
#endif
It looks nothing like the code I've been learning so far. I know it's a square root function but the hashtag? Something about my computer architecture?
Please explain it to me in simple terms.
#if condition
// Code in here
#endif
This is a conditional compilation directive - it is used to hide blocks of code from the compiler. The code in the block is only compiled if the condition is true.
It's supported in many languages, notably C and C++. It is often used to account for processor architecture and operating system differences - allowing one code-base to compile on many different platforms.
It can also be used to remove debugging/tracing code in a release build.
The condition is evaluated once at compile time, normally in an initial pass over the source code before the main compiler.
You can set those kind of conditional compilation directive for various purpose.
For example you might have an environnement for DEBUG and one for RELEASE, depending on which you wan't to compile your might not use the same functions / values.
In you case, #if !(arch(x86_64) || arch(arm64)) is to determine the architecture of your device (or simulator).
Indeed, some iDevice run 32bits and others 64bits (5S and newer). Float aren't represented the same way.
As #Martin wrote, you might not have to use this code anymore :)

How to include code into the build only when a flag is set?

I have added some debugging code to my app which I want to call only when needed. I remember there is some kind of IFDEF that can be used to conditionally include code into a source file.
For example I might have something like this:
IFDEF kDebugEnabled == YES {
// some debugging code here
}
And then this piece of code is only compiled into the binary if that kDebugEnabled is YES.
How can I do something like this?
Please note: I don't want to use the project compiler flag settings. I just want to define a BOOL (or something that serves the purpose just as well) which is true or false and then just easily set it in my App Delegate for example. I find it hard to navigate to the project compiler settings, searching for a flag and then setting it. I know there is a Debug flag which might be of use.
What you are looking for is:
#ifdef __YOURSYMBOL__
<conditional code>
#endif
You can programmatically define __YOURSYMBOL__ like this:
#define __YOURSYMBOL__
__YOURSYMBOL__ can be any string that makes sense to you to remember why you are including/excluding that code snippet.
The DEBUG constant is a special preprocessor constant that the compiler defines specifically for you when the code is built for debugging, so you can simply use it:
#ifdef DEBUG
<conditional code>
#endif
Take into account that this is the C-preprocessor, not C, nor Objective-C that you are using, so a test like kDebugEnabled == YES (where kDebugEnabled is an Objective-C variable) is simply not possible. You can define integer values for your constants, like this:
#define __LOG_LEVEL__ 3
and then test for it:
#if __LOG_LEVEL__ == 3
...
Endif
As far as I know, you can't have code in your classes that is not compiled into the final product without using compiler flags. However, using the DEBUG flag is a lot easier than you think. If you are using Xcode 4, it's set up for you by default.
#ifdef DEBUG
// Your debug-only code goes here
#endif // DEBUG
Xcode has, by default, two configurations, Debug and Release. When you use the debug build configuration, among other things, it sets the DEBUG compiler flag, which you can then use to conditionally compile code. No need to mess with compilation settings at all.

Error because of size of function in Objective-C

I am having a weird error message when i try to build my application for device:
{standard input}:3884:invalid offset, value too big (0x00000408)
Command /Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/gcc-4.2 failed with exit code 1
the class that issued this error message contains a function that has a huge switch statement with contains other switch statements in its cases. It is almost 1200 lines long!!
When i commented this function out the compilations was complete. So i predict this is whats meant by " value too big" in the error message above, correct me if am wrong.
Now how do i get over this limitation? I am thinking of a way to break my function into different parts and implement them in categories of the class in different files. But am not sure it is gonna be that easy as the function only contains switch statements within a huge statement. I will look at this further but does any one else have any other suggestion?
Cheers
AF
Firstly, if you're using xcodebuild directly try building via the IDE as some reports seem to suggest this can help, unlikely though that may sound.
Secondly, if this is a compiler bug (it sounds like it is and there are quite a few similar reports on the hyperinternetweb), you could also try switching to using LLVM (via your projects "Compiler version" settings) and see if that makes a difference.
Finally, you could simply avoid the issue by using an if/else construct instead, painful though that will be.
UPDATE
To try out LLVM (instead of gcc), select your project's build target from the "Targets" section in the Groups & Files area, alt-click and select "Get info". In the window that appears then select the Build tab (if it's not already selected) and scroll down to the "C/C++ Compiler Version" setting within the Compiler Version category. You then then choose to use "LLVM compiler" instead of gcc.