Check if UIBarButtonSystemItemPageCurl exists in iOS version - ios

I am trying to check if UIBarButtonSystemItemPageCurl exists on a given device.
Note: UIBarButtonSystemItemPageCurl exists on iOS 4.0 and above. I am also targeting iOS 3.1.3. Don't worry about the targeting iOS 3 part.
Currently tried:
if (UIBarButtonSystemItemPageCurl != NULL)
and
if ((UIBarButtonSystemItemPageCurl) == TRUE)
to check existence of the constant (Is UIBarButtonSystemItemPageCurl considered a constant? It's a value of typedef enum UIBarButtonSystemIcon). These two methods are currently not working. Can someone provide guidance on checking the existence a value of in a struct (not the containing struct)? Thanks.

If you look in UIBarButtonItem.h, you'll find that UIBarButtonSystemItemPageCurl is defined conditionally using the preprocessor:
typedef NS_ENUM(NSInteger, UIBarButtonSystemItem) {
⋮
#if __IPHONE_4_0 <= __IPHONE_OS_VERSION_MAX_ALLOWED
UIBarButtonSystemItemPageCurl,
#endif
};
…_MAX_ALLOWED is defined to the SDK version. Once the constant is defined, the constant always exists.
Comparing it against NULL is meaningless because this isn't a pointer. You are effectively comparing it against zero, and as it isn't the first thing in the enumeration, it isn't zero, so it is never NULL.
What it is is an integer. UIBarButtonSystemItemPageCurl is synonymous with 23, and the number 23 always exists, regardless of OS version.
So the question becomes “is UIBarButtonSystemItemPageCurl (a.k.a. 23) something that UIKit will recognize?”
One way to find that out would be to pass it to initWithBarButtonSystemItem:target:action: and see what happens. Hopefully, it will either return nil or throw an exception; either way, you can detect that and recover by doing whatever you need to do on iOS 3 devices.
Another way would be to ask the device for its systemVersion and compare it to #"4.0" in a way that understands version numbers. The Growl project has code for parsing and comparing version number strings. It's written for OS X, but should work with little to no modification on iOS.
I'd do the try-it-and-see approach first. Only if it silently fails (i.e., always returns a UIBarButtonItem, even on iOS 3, and the item you get on 3 just doesn't work) should you resort to comparing OS versions.

Related

Using g_autoptr() together with G_DEFINE_AUTOPTR_CLEANUP_FUNC() when using older and newer GLib versions

There is something about using g_autoptr() together with G_DEFINE_AUTOPTR_CLEANUP_FUNC() when using different GLib versions which I don't understand (this affects also the other g_auto... variants and its G_DEFINEs).
The documentation says
"The way to clean up the type must have been defined using the macro
G_DEFINE_AUTOPTR_CLEANUP_FUNC()"
When using for example GLib 2.62 and using the G_DEFINE macro this results in errors like
/usr/include/glib-2.0/glib/gmacros.h:1032:49: error: redefinition of ‘glib_slistautoptr_cleanup_GtkTreePath’
1032 | #define _GLIB_AUTOPTR_SLIST_FUNC_NAME(TypeName) glib_slistautoptr_cleanup_##TypeName
Leaving out the G_DEFINE macro will solve the problem and the program works just fine.
However, on older GLib versions like 2.50 (which is for example still used by Debian 9), using the G_DEFINE macro will not result in an error message. But I can't see any changes reflected by the GLib documentation. I cannot determine when exactly the aforementioned change of behaviour has been introduced. How am I supposed to cope with this when I want to support all GLib versions from 2.50 on?
The issue is probably in Gtk, not GLib. g_autoptr() was supported for most things in Gtk+ 3.22 (the one in Debian 9) already: so you shouldn't have to call G_DEFINE_AUTOPTR_CLEANUP_FUNC() on Gtk types yourself. GtkTreePath however was still missing a call: this was added in 3.24, see https://gitlab.gnome.org/GNOME/gtk/-/commit/86dd1e37a70e9bae057a9a11332f7254cda242e8.
You'll probably have to do the macro call behind a version check if you want to use g_autoptr() with TreePath on Gtk < 3.24.

MantisBT not listing changelog

I am making use of MantisBT to track issues and have so far collected a number of issues. However, my changelog remains empty
No Change Log information available. Issues are included once projects
have versions and issues are resolved with "fixed in version" set.
Each bug report has
Product version, target version (needed for roadmap) and a fixed in version (needed for changelog).
Likewise I have released certain versions.
I have customized my workflow and I suspect this is part of the reason.
# custom access list
$g_access_levels_enum_string = '10:VIEWER,20:REPORTER,30:ENGINEER,40:CCB,90:ADMINISTRATOR';
# custom resolution list
$g_resolution_enum_string = '10:OPEN,20:REOPEN,30:WONTFIX,60:DISPOSITIONED, 70:FIXED';
From what I have been able to determine, for a changelog to appear you need
1) a released version (done)
2) a bug with a fixed in version matching this (done
3) a bug closed as "fixed"
now in a fresh MantisBT (and testing shows changelog works), FIXED has a constant of 20 so part of me suspect it is my g_resolution_enum_string but this would also imply that there should be another variable that sets which threshold should be used
$g_bug_resolution_fixed_threshold = FIXED;
This does not work
What am I missing? Also if it is of importance... my versions are labeled: v0.0, v0.1, v0.2 (ie prepended by 'v')
I suggest you read the documentation's Enumerations section, in particular
The strings included in the enumerations here are just for documentation purposes
So, your enum definition of 70:FIXED does not actually match the constant FIXED which, as you have pointed out, is still set to 20 which means that $g_bug_resolution_fixed_threshold actually points to your 20:REOPEN... You may want to define your own constants.
Also note that there is another important threshold in this context, $g_bug_resolution_not_fixed_threshold - resolutions above it are considered to be resolved in an unsuccessful way. By default it is set to _UNABLE_TO_REPRODUCE_ (40).
In other words, for an issue to appear in the Changelog, it must match all of the following criteria (reference):
status >= bug_resolution_fixed_threshold
resolution >= bug_resolution_fixed_threshold
resolution < bug_resolution_not_fixed_threshold
Note that this standard behavior can be changed with a custom function.
So your problem is indeed caused by your custom resolution_enum_string, most likely in combination with the values in the 2 above-mentioned thresholds.

CLANG_WARN_NULLABLE_TO_NONNULL_CONVERSION removed?

Seems like CLANG_WARN_NULLABLE_TO_NONNULL_CONVERSION was removed in Xcode 8. It provided some really good warnings in case nil was passed to nonnull parameters/return types. Any idea why this was removed and whether there exists a replacement?
I still see warning, when I pass nil to nonull expected method. Maybe it's enabled by default for now.

How to check for NS_AVAILABLE_IOS with const CGFloat

When a method can only be used on certain iOS versions, I usually check for its availability using respondsToSelector:.
With a const CGFloat declaration this is not possible.
The specific constant I'm trying to use is UIFontWeightBlack which is defined as:
UIKIT_EXTERN const CGFloat UIFontWeightBlack NS_AVAILABLE_IOS(8_2);
What is the best way to check if the iOS version my code is running in supports this constant?
Also if I want to support building my framework with older versions of the iOS SDK, what is the best way to check at compile time, if the used SDK offers this symbol?
I would currently do the check with
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_8_2
Is there a way to check for the symbol directly, without having to rely on / explicitly specify the iOS SDK version?
This is covered in the SDK Compatibility Guide.
Check the availability of an external (extern) constant or a notification name by explicitly comparing its address—and not the symbol’s bare name—to NULL or nil.
So your code would be:
if (&UIFontWeightBlack != NULL) {
// It is safe to use the constant
}
To answer the second part of your question, change your compile time check to the following:
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80200 // 80200 is the value of __IPHONE_8_2
We want to fall back to use the value of the macro rather than the macro itself as the macro is not defined in older versions of the iOS SDK.
As you mentioned in a comment, this is covered in the Conditionally Compiling for Different SDKs section:
The following code excerpt demonstrates this. Notice the use of the
numerical value 1050 instead of the symbol __MAC_10_5 in the #if
comparison clause: If the code is loaded on an older system that does
not include the symbol definition, the comparison still works.

What do I need to do to use tgmath on iOS?

I'm compiling my first project with 64 bit support enabled. I'm running into a bunch of compiler warnings about implicit conversions to float. This is happening because I'm using fabsf() and assigning the result to a CGFloat (which is a double, not float on the new 64 bit architecture).
According to the answer on this question:
CGFloat-based math functions?
I just need to #include <tgmath.h> to solve this problem and probably change fabsf to fabs. I have at least one file where this doesn't seem to be helping. I still get the warning: implicit conversion loses floating-point precision 'double' to 'CGFloat' aka (float). Here's the line that generates that warning:
CGFloat deltaX = fabs(item.center.x-point.x);
Has anyone else run across this? How did you solve it? I'd rather not disable this warning or litter my code with a ton of typecasts.
I guess, you are using CGPoint types, so the conversion doesn't occur within fabs(DOUBLE -> FLOAT), but on assignment CGFloat = DOUBLE. That's probably because compiler used fabs from math.h which operates on doubles.
Problem with math.h is that it's internally imported by OSX headers (carbon if I remember correctly), so I guess some iOS header might also do that. After quick look, it seems that basic set of frameworks doesn't import math.h, so probably you should look for it being manually imported. In case it's imported internally by some system libs, you'll probably won't be able to use those libs and tgmath in a single implementation file.
If you want to check if there are some math.h dependencies, you can use a dirty trick to prevent it's inclusion - add this line to a file (or better on top of prefix file):
#define __MATH_H__
I was able to get the tgmath.h functions to work by including the header at the top of my PCH file.
At some point (read: Xcode update) I had to start disabling Modules to get this to work. The details of such are in the question Dima links to below.

Resources