Типы Foundation при компиляции для arm64 и 32-битной архитектуры

Составив код приложения iOS для arm64, я столкнулся с интересной проблемой, связанной с различными базовыми типами для пользовательских типов Foundation. Скажем, я хочу напечатать f (или stringWithFormat) число, объявленное как NSUInteger

[NSString stringWithFormat:@"%u", _depth,

Это создаст предупреждение для arm64, потому что NSUInteger объявлен как unsigned long для arm64. Поэтому я должен заменить "% u" на "% lu", но теперь это становится недействительным при компиляции для архитектуры armv7 (s), потому что для 32-разрядных архитектур NSUInteger объявлено как unsigned int. Я знаю, что предупреждение гласит: "NSUInteger не следует использовать как аргумент формата", поэтому давайте перейдем к floats:

typedef CGFLOAT_TYPE CGFloat;

в 64-битном CGFLOAT_TYPE double, а на 32-битном - float. Поэтому, делая что-то вроде этого:

- (void)foo:(CGFloat)value;

а затем

[self foo:10.0f]; 
[self foo:10.0]; 

Будет выдавать предупреждение при компиляции для двух архитектур. В 32-битной архитектуре второй вызов неверен (преобразование из double в float), в 64-битной архитектуре, первая конвертирует float в double (что нормально, но все равно не хорошо).

Хотелось бы услышать ваши мысли по этой проблеме.

Ответ 1

Один (по общему признанию, ужасный) подход, который я видел, используется, чтобы использовать магию #define и компилировать литеральную литературную конкатенацию. Вот так:

// In your prefix header or something
#if __LP64__
#define NSI "ld"
#define NSU "lu"
#else
#define NSI "d"
#define NSU "u"
#endif

// Then later you can use these like this...
NSString* foo = [NSString stringWithFormat:@"%"NSU" things in the array.", array.count]);

Довольно ужасно, но он работает.

Другим, казалось бы, более распространенным подходом является просто повышение значения для более крупного типа на каждой платформе, например:

NSString* foo = [NSString stringWithFormat:@"%lu things in the array.", (unsigned long)array.count]);

Совсем недавно (т.е. с момента появления нового синтаксиса с сокращением бокса), я обнаружил, что я ленив и начал просто бокс, как это:

NSString* foo = [NSString stringWithFormat:@"%@ things in the array.", @(array.count)]);

Может быть, лучший способ, но те, что я видел больше всего.