objective-c

@available guard/weak linking not compiling


I'm trying to use a different property names for a future macOS version due to deprecation. Specifically, NSCursor.columnResizeCursor is available on 15.0+, but I'm using the 14.0 SDK.

I read that @available guards are the correct way to handle this. However, the code below does not compile when ran with

clang -mmacos-version-min=10.14 -weak_framework AppKit main.m.

The error is

error: property 'columnResizeCursor' not found on object of type 'NSCursor'

Is there anything I am doing wrong? I was under the impression that weak linking the AppKit framework wouldn't have it complain about missing properties.

// main.m

#include <AppKit/AppKit.h>

int main() {
    if (@available(macOS 15.0, *)) {
        // This line does not compile!
        [NSCursor.columnResizeCursor set];
    } else {
        [NSCursor.resizeLeftRightCursor set];
    }
}

Solution

  • If you are compiling against an older SDK which does not know about newer APIs, then @available won't work, because the compiler still needs to know the method it's calling.

    Normally, you would do this once you switch to a newer SDK (i.e. newer Xcode).

    You can forcibly declare the method though, if you need to enable building with SDKs (i.e. using an older Xcode). You can check if you are compiling against an SDK older than the API in question, and if so, declare it the same way Apple does. This can go in your .m file so only the code that needs it can "see" it, or more publicly if you need the @available check across several files.

    #if TARGET_OS_OSX && (!defined(__MAC_15_0) || __MAC_OS_X_VERSION_MAX_ALLOWED < __MAC_15_0)
    @interface NSCursor (ForwardDeclaration15_0_Methods)
    @property (class, readonly, strong) NSCursor *columnResizeCursor NS_SWIFT_NAME(columnResize) API_AVAILABLE(macos(15.0));
    @end
    #endif
    

    After that, the compiler knows about the method, and the code you had above should work, even with an older Xcode. The name of the category does not matter (though best to avoid duplicating another one).