Swift alternative for #pragma clang diagnostic

2019-03-12 12:53发布

Problem

I recently encountered a warning in a third party utility (WEPopover) in this piece of code:

_effectivePopoverContentSize = _contentViewController.contentSizeForViewInPopover;

This was generating the following warning:

warning: 'contentSizeForViewInPopover' is deprecated: first deprecated in iOS 7.0 - Use UIViewController.preferredContentSize instead. [-Wdeprecated-declarations]
            _effectivePopoverContentSize = _contentViewController.contentSizeForViewInPopover;

One temporary fix for this in Objective-C is to use pragma clang diagnostic to silence the error (I'll let the code author deal with a true fix). So I revised the code like so:

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
            _effectivePopoverContentSize = _contentViewController.contentSizeForViewInPopover;

#pragma clang diagnostic pop

Question

Which works just fine but this led me to consider what if any alternative exists where one would need to silence a similar false positive warning when coding in Swift?

Considerations

I have observed the fact that I can deactivate such warnings project wide (using Xcode settings) but I want to consider the inline problem as noted above. I've also considered adding a #define into a .bridging-header.h file within my Swift project and somehow making use of that; however I am looking for a Swift specific solution to this problem. I do understand that pragma is no longer available and I have searched SO and found similar but not duplicate questions.

UPDATED RESOLUTION: Swift 2.0

The answer provided handles my concern about inline warnings. The availability command should allow such problems to be avoided altogether because one would be warned at compile time.

Apple's Swift book definitively states:

“You use an availability condition in an if or guard statement to conditionally execute a block of code, depending on whether the APIs you want to use are available at run time. The compiler uses the information from the availability condition when it verifies that the APIs in that “block of code are available.

 if #available(iOS 9, OSX 10.10, *) {
 // Use iOS 9 APIs on iOS, and use OS X v10.10 APIs on OS X 
 } else {
 // Fall back to earlier iOS and OS X APIs 
 }

Excerpt From: Apple Inc. “The Swift Programming Language (Swift 2 Prerelease).” iBooks. https://itun.es/us/k5SW7.l

One could even use the guard statement combined with availability to exit the scope early unless the available conditions are satisfied.

guard #available(iOS 8.0, OSX 10.10, *) else { return }

Excerpt From: Apple Inc. “Using Swift with Cocoa and Objective-C (Swift 2 Prerelease).” iBooks. https://itun.es/us/utTW7.l

Furthermore, my related concerns on handling macros are addressed as noted below. Keeping in mind that Swift has no preprocessor these tools seem like the way to go.

Simple Macros

Where you typically used the #define directive to define a primitive constant in C and Objective-C, in Swift you use a global constant instead. For example, the constant definition #define FADE_ANIMATION_DURATION 0.35 can be better expressed in Swift with let FADE_ANIMATION_DURATION = 0.35. Because simple constant-like macros map directly to Swift global variables, the compiler automatically imports simple macros defined in C and Objective-C source files.”

Excerpt From: Apple Inc. “Using Swift with Cocoa and Objective-C (Swift 2 Prerelease).” iBooks. https://itun.es/us/utTW7.l

Complex Macros

Complex macros are used in C and Objective-C but have no counterpart in Swift. Complex macros are macros that do not define constants, including parenthesized, function-like macros. You use complex macros in C and Objective-C to avoid type-checking constraints or to avoid retyping large amounts of boilerplate code. However, macros can make debugging and refactoring difficult. In Swift, you can use functions and generics to achieve the same results without any compromises. Therefore, the “complex macros that are in C and Objective-C source files are not made available to your Swift code.”

Excerpt From: Apple Inc. “Using Swift with Cocoa and Objective-C (Swift 2 Prerelease).” iBooks. https://itun.es/us/utTW7.l

The developer of the API will be able to mark the availability of functions in Swift using:

available(iOS 8.0, OSX 10.10, *)
func useShinyNewFeature() {
    // ...
}

Excerpt From: Apple Inc. “Using Swift with Cocoa and Objective-C (Swift 2 Prerelease).” iBooks. https://itun.es/us/utTW7.l

Adding these markers to functions rewritten for Swift seems like a good way to maintain backward compatibility for Frameworks. The guard/available combination will allow users of those frameworks to adjust logic as necessary. Which sets my mind at ease about handling both in-line warnings, API fallback, and macros in general.

1条回答
啃猪蹄的小仙女
2楼-- · 2019-03-12 13:15

As of version 2.0 (currently in beta as of this writing), Swift still does not include a preprocessor and that doesn't look to change anytime soon (if ever). The beneficial abilities that preprocessors allow are built into the language itself in various ways (I won't cover all of them here, see the docs) and are compile-time level features.

There are two features I do want to mention (one old, one new) that may be what you're looking for:

  1. Conditional Compilation - As covered in Using Swift with Cocoa and Objective-C, you can implement conditional compilation statements that allow you to only compile code given certain operating systems or processor architectures. If looks something like this:

enter image description here

  1. Checking for API Availability - As covered in The Swift Programming Language, you can now check for API availability based on platform and OS version. This will allow you to take advantage of newer API's while allowing you to handle when that feature isn't available on an older (or different) platform or OS. You could use this to sub in an alternate implementation or present an explanation to the user. If looks something like this:

enter image description here

These tools (along with many others built into the language) should allow a developer to replace the Objective-C and C preprocessor macros. Personally, I think they are a huge improvement.

查看更多
登录 后发表回答