Preprocessor macro for OS X targets? - objective-c

I have a project that has both an iOS and an OS X target. Is there a preprocessor macro that is true when I'm compiling for OS X? I tried this:
#if TARGET_OS_MAC
#interface BFNode : NSObject <NSPasteboardReading, NSPasteboardWriting> {
#else
#interface BFNode : NSObject {
#endif
But TARGET_OS_MAC doesn't seem to work. When I try to run the app on iOS I get a compiler error, because it tries to compile the first line and there is no NSPasteboardReading protocol defined on iOS.
I know there is TARGET_OS_IPHONE too. If I use that and swap the #interface declarations it works.
But there are a lot of places where I have code, that has no iOS version, so I need a macro for OS X too.
SOLUTION:
I ended up defining a new macro in the .pch file:
#define TARGET_OSX TARGET_OS_IPHONE == 0

The documentation in TargetConditionals.h has this diagram (it seems, as of 2022; any platform):
+---------------------------------------------------------------------+
| TARGET_OS_MAC |
| +---+ +-----------------------------------------------+ +---------+ |
| | | | TARGET_OS_IPHONE | | | |
| | | | +---------------+ +----+ +-------+ +--------+ | | | |
| | | | | IOS | | | | | | | | | | |
| |OSX| | |+-------------+| | TV | | WATCH | | BRIDGE | | |DRIVERKIT| |
| | | | || MACCATALYST || | | | | | | | | | |
| | | | |+-------------+| | | | | | | | | | |
| | | | +---------------+ +----+ +-------+ +--------+ | | | |
| +---+ +-----------------------------------------------+ +---------+ |
+---------------------------------------------------------------------+
This tells us:
TARGET_OS_MAC will be 1 for (probably) any Cocoa application running on an Apple platform.
TARGET_OS_OSX will only be 1 for macOS targets
TARGET_OS_IPHONE will be 1 for any non-Mac Apple products
TARGET_OS_IOS is just for iOS
TARGET_OS_MACCATALYST is just for Project Catalyst. It seems TARGET_OS_UIKITFORMAC will also work.
TARGET_OS_TV is just for tvOS
TARGET_OS_WATCH is just for watchOS
TARGET_OS_BRIDGE is just for bridgeOS (which currently doesn't even support 3rd-party apps so you'll likely always see that be 0)
TARGET_OS_DRIVERKIT will be 1 when building for DriverKit
⚠️ But wait! ⚠️
I got that from the iOS 14 (macOS 11, watchOS 7) SDK. If I look back into the iOS 13 (macOS 10.15, watchOS 6) SDK, I see this:
+----------------------------------------------------------------+
| TARGET_OS_MAC |
| +---+ +-----------------------------------------------------+ |
| | | | TARGET_OS_IPHONE | |
| |OSX| | +-----+ +----+ +-------+ +--------+ +-------------+ | |
| | | | | IOS | | TV | | WATCH | | BRIDGE | | MACCATALYST | | |
| | | | +-----+ +----+ +-------+ +--------+ +-------------+ | |
| +---+ +-----------------------------------------------------+ |
+----------------------------------------------------------------+
Notably, TARGET_OS_DRIVERKIT is new in 14, and TARGET_OS_MACCATALYST is inside IOS now. This tells us that compiling against the iOS 14 / macOS 11 SDK can break some C code written for iOS 13 / macOS 10.15, if it assumes that TARGET_OS_MACCATALYST and TARGET_OS_IOS are completely separate.
There's More!
Additionally, these are defined:
TARGET_OS_SIMULATOR is just for iOS, tvOS, and watchOS simulators. You can further refine this using the above #defines
TARGET_OS_WIN32 is in case you wanna use Apple's SDKs to make Windows apps. I don't personally know of any other than Apple's own (like iTunes, Safari, and QuickTime). This might become useful now that Swift has Windows support, if you want to take existing Objective-C code with you.
TARGET_OS_UNIX is for non-Apple UNIX systems
And these are deprecated, and should not be used anymore. That said, you might find them in code you have to maintain, so here's what they meant:
TARGET_IPHONE_SIMULATOR used to mean the iPhoneOS simulator. Use TARGET_OS_SIMULATOR instead (along with TARGET_OS_IOS to target only iOS simulators)
TARGET_OS_EMBEDDED used to mean iOS, tvOS, and watchOS non-simulated devices. Use the standard OS targets instead.
TARGET_OS_NANO probably used to mean iPod Nano (I can't find any historical usage online). Apple advises to use TARGET_OS_WATCH instead.
Something else to note is that the TargetConditionals.h which is used in swift-corelibs-foundation is significantly different, and includes #defines for Android, Cygwin, and other not-explicitly-supported-but-they-technically-work platforms.
I'm not entirely sure what to make of this. I would guess it's for compiling the Swift Foundation framework, and not for consuming it, since Swift doesn't consume #defines.

If you're using Swift, there's a great language feature for this. If you're using Objective-C, it's often useful to do something like this:
#include <TargetConditionals.h>
#if TARGET_OS_IPHONE
#import UIKit;
#else
#import AppKit;
#endif
Understanding the TARGET_OS_* defines will make this make a lot more sense. Most notably, TARGET_OS_MAC is any Apple platform which is pretty unexpected. !TARGET_OS_IPHONE is macOS and TARGET_OS_IPHONE is anything besides that. There are more specific defines for iOS, tvOS, and watchOS.
From TargetConditions.h:
TARGET_OS_*
These conditionals specify in which Operating System the generated code will
run. Indention is used to show which conditionals are evolutionary subclasses.
The MAC/WIN32/UNIX conditionals are mutually exclusive.
The IOS/TV/WATCH conditionals are mutually exclusive.
TARGET_OS_WIN32 - Generated code will run under 32-bit Windows
TARGET_OS_UNIX - Generated code will run under some Unix (not OSX)
TARGET_OS_MAC - Generated code will run under Mac OS X variant
TARGET_OS_IPHONE - Generated code for firmware, devices, or simulator
TARGET_OS_IOS - Generated code will run under iOS
TARGET_OS_TV - Generated code will run under Apple TV OS
TARGET_OS_WATCH - Generated code will run under Apple Watch OS
TARGET_OS_SIMULATOR - Generated code will run under a simulator
TARGET_OS_EMBEDDED - Generated code for firmware
TARGET_IPHONE_SIMULATOR - DEPRECATED: Same as TARGET_OS_SIMULATOR
TARGET_OS_NANO - DEPRECATED: Same as TARGET_OS_WATCH

That is because TARGET_OS_MAC is defined when building for iOS as well.
See http://sealiesoftware.com/blog/archive/2010/8/16/TargetConditionalsh.html on that.
I would try and build my own target specific define via build-settings on the target.

As of Xcode 8 GM, this is the relevant section of TargetConditionals.h in iOS 10.0:
#define TARGET_OS_MAC 1
#define TARGET_OS_WIN32 0
#define TARGET_OS_UNIX 0
#define TARGET_OS_OSX 0
#define TARGET_OS_IPHONE 1
#define TARGET_OS_IOS 1
#define TARGET_OS_WATCH 0
#define TARGET_OS_BRIDGE 0
#define TARGET_OS_TV 0
#define TARGET_OS_SIMULATOR 0
#define TARGET_OS_EMBEDDED 1
#define TARGET_IPHONE_SIMULATOR TARGET_OS_SIMULATOR /* deprecated */
#define TARGET_OS_NANO TARGET_OS_WATCH /* deprecated */
(In the 'breadcrumb' above the text editor in Xcode, iOS 10.0 > usr/include > TargetConditionals.h)
...And this is the same file, for macOS:
#define TARGET_OS_MAC 1
#define TARGET_OS_WIN32 0
#define TARGET_OS_UNIX 0
#define TARGET_OS_OSX 1
#define TARGET_OS_IPHONE 0
#define TARGET_OS_IOS 0
#define TARGET_OS_WATCH 0
#define TARGET_OS_BRIDGE 0
#define TARGET_OS_TV 0
#define TARGET_OS_SIMULATOR 0
#define TARGET_OS_EMBEDDED 0
#define TARGET_IPHONE_SIMULATOR TARGET_OS_SIMULATOR /* deprecated */
#define TARGET_OS_NANO TARGET_OS_WATCH /* deprecated */
(In the 'breadcrumb' above the text editor in Xcode, macOS 10.12 > usr/include > TargetConditionals.h)
TARGET_OS_MAC is defined as 1 on both platforms, but TARGET_OS_OSX is 1 only on macOS.
In the file's comments, they are described as follows:
TARGET_OS_MAC: Generated code will run under Mac OS X variant.
TARGET_OS_OSX: Generated code will run under OS X devices.
I guess at some point back then (perhaps around when the iPhone was announced?) somebody decided that iOS (né "iPhone OS") fits the definitions of "Mac OS X variant".

Look in TargetConditionals.h for an entire list, including:
#define TARGET_OS_MAC 1
#define TARGET_OS_IPHONE 1
#define TARGET_IPHONE_SIMULATOR 1

I ran into this same situation, but needed it for Swift.
This answer here on the Apple developer forums was very helpful in dealing with the NSPasteboard protocols in your situation, but for Swift.
https://forums.developer.apple.com/thread/16757
I ended up doing:
#if os(iOS) || os(watchOS)
public protocol TFPasteboardReading { }
public protocol TFPasteboardWriting { }
#elseif os(macOS)
public typealias TFPasteboardReading=NSPasteboardReading
public typealias TFPasteboardWriting=NSPasteboardWriting
#endif
#objc(TFCategory)
public class TFCategory: TFBaseModel, TFPasteboardReading, TFPasteboardWriting {
...
}
That way TFPasteboardReading and TFPasteboardWriting is defined for macOS meaning NSPasteboardReading and NSPasteboardWriting respectively and in iOS it has no meaning, but can still be referenced in iOS. So the code compiles properly for both.

I would recommend using this:
#define TARGET_OS_OSX (!(TARGET_OS_IOS || TARGET_OS_TV || TARGET_OS_WATCH))

Related

How to add extra info to BenchmarkDotNet summary?

How can I add extra informationto extend the summary information produced by BenchmarkDotNet?
Like:
current host name or
current (Git) branch name
I would like to achieve something similar to this example:
Host MachineName: <Environment.MachineName>
Branch: <Git-Branch-Name>
BenchmarkDotNet=v0.13.1, OS=Windows 10...
Intel Core i7...
[Host] : .NET Framework 4.8 (4.8.4300.0), X64 RyuJIT
Dry : .NET Framework 4.8 (4.8.4300.0), X64 RyuJIT
Job=Dry IterationCount=1 LaunchCount=1
RunStrategy=ColdStart UnrollFactor=1 WarmupCount=1
| Method | Mean | Error |
|----------------- |----------- |------ |
| Foo | 1,940.3 ms | NA |
Currently there is no way to extend the Summary with extra data. All you can do is to implement a custom column and add it to the config: https://benchmarkdotnet.org/articles/configs/columns.html

Intellij idea 2021.2 cannot render markdown table currently?

I use idea 2021.2 and corresponding markdown plugin. But the simple table cannot display in previous mode:
Why? I found somebody has related the problem to the JavaFx, however, I think it is occured in old version idea. I cannot find javafx render option in my version.
How to solve it?
You are using the wrong Markdown syntax.
The following code works fine (minimum three - for table header)
| Column 1 | Column 2 |
| :--- | :--- |
| AAA | BBB |

How to use regex and awk to detect and extract variable length and width text table?

In running some scripts that update WordPress, the output of the scripts is logged to a file. Here is a relevant portion of the log file:
Downloading update from https://downloads.wordpress.org/plugin/adrotate.5.8.15.zip...
Unpacking the update...
Installing the latest version...
Removing the old version of the plugin...
Plugin updated successfully.
Downloading update from https://downloads.wordpress.org/plugin/cookie-notice.2.0.0.zip...
Unpacking the update...
Installing the latest version...
Removing the old version of the plugin...
Plugin updated successfully.
Downloading update from https://downloads.wordpress.org/plugin/google-site-kit.1.25.0.zip...
Unpacking the update...
Installing the latest version...
Removing the old version of the plugin...
Plugin updated successfully.
Disabling Maintenance mode...
+-----------------+-------------+-------------+---------+
| name | old_version | new_version | status |
+-----------------+-------------+-------------+---------+
| adrotate | 5.8.14 | 5.8.15 | Updated |
| cookie-notice | 1.3.2 | 2.0.0 | Updated |
| google-site-kit | 1.24.0 | 1.25.0 | Updated |
+-----------------+-------------+-------------+---------+
[32;1mSuccess:[0m Updated 3 of 3 plugins.
[32;1mSuccess:[0m Theme already updated.
What I want to do next is open, read, and extract a portion of that log file to write it to a separate file as-is. The critical piece I need is this table from the output above:
+-----------------+-------------+-------------+---------+
| name | old_version | new_version | status |
+-----------------+-------------+-------------+---------+
| adrotate | 5.8.14 | 5.8.15 | Updated |
| cookie-notice | 1.3.2 | 2.0.0 | Updated |
| google-site-kit | 1.24.0 | 1.25.0 | Updated |
+-----------------+-------------+-------------+---------+
So, what I'm doing is using
awk '/Disabling Maintenance mode...$/,/[32;1mSuccess:$/' logfile.txt
to attempt to grab that table. Unfortunately, with this awk command, I seem to also get the Disabling Maintenance mode... and [32;1mSuccess: parts along with it. And those strings aren't reliably consistent enough to use them as proper start/end markers for awk. The most accurate thing I can think of is the correct regex to grab just that table and nothing more.
The problem with the text-formatted table is that the length and width of it can vary depending on what the script is updating. The "name" column could have an item in it that's 50 characters long, for example, which makes the table wider. It could also have, like, 20 "rows". So I never know how many hyphens or pipe characters to count in regex or in some kind of loop.
I've tried various tutorials and also regex101.com to devise a pattern that will help me find this variable length/width pattern. But I'm making no progress. I'm not sure I know how to frame the problem correctly within regex syntax. All tutorials I'm reading are using "abc" and "xxx" as examples and this is so much more complex.
Can anyone help me figure out how to do this?
Maybe this is too simple?
awk 'bar == 3 {exit}; /--/ {bar++} bar ' logfile.txt
If you don't want the bars in the output:
awk 'bar == 3 {exit}; /--/ {bar++; next} bar' logfile.txt
With your shown samples please try following. Written and tested in GNU awk.
awk '
/^\[32;1mSuccess:/ { found="" }
/^Disabling Maintenance/{ found=1; next }
found
' Input_file
Explanation: Adding detailed explanation for above.
awk ' ##Starting awk program from here.
/^\[32;1mSuccess:/ { found="" } ##Checking if line starts from [32;1mSuccess: then unset found here.
/^Disabling Maintenance/{ found=1; next } ##Checking if line starts from Disabling Maintenance then set found to 1 here.
found ##checking condition if found is set(NOT NULL) then print that line.
' Input_file ##Mentioning Input_file name here.
I would use GNU AWK following way, let file.txt content be
Downloading update from https://downloads.wordpress.org/plugin/adrotate.5.8.15.zip...
Unpacking the update...
Installing the latest version...
Removing the old version of the plugin...
Plugin updated successfully.
Downloading update from https://downloads.wordpress.org/plugin/cookie-notice.2.0.0.zip...
Unpacking the update...
Installing the latest version...
Removing the old version of the plugin...
Plugin updated successfully.
Downloading update from https://downloads.wordpress.org/plugin/google-site-kit.1.25.0.zip...
Unpacking the update...
Installing the latest version...
Removing the old version of the plugin...
Plugin updated successfully.
Disabling Maintenance mode...
+-----------------+-------------+-------------+---------+
| name | old_version | new_version | status |
+-----------------+-------------+-------------+---------+
| adrotate | 5.8.14 | 5.8.15 | Updated |
| cookie-notice | 1.3.2 | 2.0.0 | Updated |
| google-site-kit | 1.24.0 | 1.25.0 | Updated |
+-----------------+-------------+-------------+---------+
[32;1mSuccess:[0m Updated 3 of 3 plugins.
[32;1mSuccess:[0m Theme already updated.
then
awk '/^[+|].*[+|]$/' file.txt
output
+-----------------+-------------+-------------+---------+
| name | old_version | new_version | status |
+-----------------+-------------+-------------+---------+
| adrotate | 5.8.14 | 5.8.15 | Updated |
| cookie-notice | 1.3.2 | 2.0.0 | Updated |
| google-site-kit | 1.24.0 | 1.25.0 | Updated |
+-----------------+-------------+-------------+---------+
Explanation: print only lines which begin with one of: +| and end with one of: +|. Note that this might give false positives if you have any non-table lines starting with + or | and ending with + or |, so I suggest you run further test with your input data if you wish to use my solution.

Get version of rich edit library

ALL,
Is it possible to get the version of the RichEdit control the program uses?
| Version | Class name | Library | Shipped with | New features
|------------|---------------|--------------|-----------------|
| 1.0 | "RICHEDIT" | Riched32.dll | Windows 95 |
| 2.0 | "RichEdit20W" | Riched20.dll | Windows 98 | ITextDocument
| 3.0 | "RichEdit20W" | Riched20.dll | Windows 2000 | ITextDocument2
| 3.1 | "RichEdit20W" | Riched20.dll | Server 2003 |
| 4.1 | "RICHEDIT50" | Msftedit.dll | Windows XP SP1 | tomApplyTmp
| 7.5 | "RICHEDIT50" | Msftedit.dll | Windows 8 | ITextDocument2 (new), ITextDocument2Old, Spell checking, Ink support, Office Math
| 8.5 | "RICHEDIT50" | Msftedit.dll | Windows 10 | LocaleName, more image formats
I know I can just have some variable and assign it appropriately if Msftedit.dll library is loaded or not. However if I do load RichEd20.dll, I can get either RichEdit 2 or RichEdit 3 implementation. And they are quite different. A lot of stuff were added in the latter.
If i did load Msftedit.dll, there are features that 7.5 that would not be available in earlier versions (e.g. automatic spell checking).
It's even possible that the same process can have all three DLLs loaded, and even using all three versions of RichEdit in the same process:
"RICHEDIT" → 1.0
"RichEdit20W" → 2.0, 3.0
"RICHEDIT50" → 4.1, 7.5, 8.5
Given a RichEdit control (e.g. WinForms RichTextBox, WPF RichTextBox, WinRT RichEditBox, VCL TRichEdit) is there a way to determine the version of a RichEdit control?
Or maybe I can somehow differentiate them by Windows version where it is available?
If using c++ you may find the following snippet useful to read out the class name :
TCHAR className[MAX_PATH];
GetClassName(GetRichEditCtrl().GetSafeHwnd(), className, _countof(className));
GetRichEditCtrl() is function on another control, you may need to substitute with whatever gives you a hwnd to the control.
Another method is using a tool like spy++ to inspect the class name.

Objective C: Accelerometer directions

I'm trying to detect a shaking motion in an up and down direction like this:
/ \
|
________________________________
| |
| |
| |
|o |
| |
| |
|______________________________|
|
\ /
-(void) bounce:(UIAcceleration *)acceleration {
NSLog(#"%f",acceleration.x);
}
I was thinking it's the x axis but that responds if you turn it to be parallel to the floor. How do I detect this?
I don't have a direct answer for you, but a great experiment is to make a quick app which spews the numbers out onto the screen or into a file (or both). Then shake it the way to you want to detect, and see which set has the greatest change.