Подтвердить что ты не робот

Странное исключение в макетах

Попробуйте вызвать этот метод:

avatarIconImageView.setContentHuggingPriority(UILayoutPriorityDefaultLow, forAxis: UILayoutConstraintAxis.Horizontal)

и поймать это исключение:

Undefined символы для архитектуры armv7:
"_UILayoutPriorityDefaultLow", на который ссылаются:       __TFC13TCProject_iOS36TCAvatarWithCounterUniversalCellView22configureBodyCellViewsfS0_FT_T_ в TCAvatarUniversalCellView.o ld: символ не найден для архитектура armv7 clang: ошибка: команда компоновщика не удалась с кодом выхода 1 (используйте -v, чтобы увидеть вызов)

что это значит?

4b9b3361

Ответ 1

Это похоже на ошибку в SDK iOS 8. Вы можете обойти это, просто передав исходное значение.

  • UILayoutPriorityDefaultRequired = 1000
  • UILayoutPriorityDefaultHigh = 750
  • UILayoutPriorityDefaultLow = 250

В вашем случае

avatarIconImageView.setContentHuggingPriority(250, forAxis: UILayoutConstraintAxis.Horizontal)

Ответ 2

Это не ошибка. Это недостаток ожидания импорта библиотек Objective-C в Swift. Следует понимать, как Swift импортирует код (даже из библиотек Apple UIKIt) из Objective-C в Swift.

UILayoutPriority - это float. В Objective-C для нас предопределена пара значений. Предварительно определенные значения выглядят как перечисление. Мы могли бы ожидать, что те же перечисления будут доступны нам в Swift.

В документации предлагается перечисление:

Декларация SWIFT

typealias UILayoutPriority = Float

OBJECTIVE-C

enum {
   UILayoutPriorityRequired = 1000,
   UILayoutPriorityDefaultHigh = 750,
   UILayoutPriorityDefaultLow = 250,
   UILayoutPriorityFittingSizeLevel = 50,
};
typedef float UILayoutPriority;

Но в Xcode, если вы попросите увидеть определение одного из этих значений enum (например, UILayoutPriorityRequired), вы увидите, что они фактически определены в файле заголовка как постоянные поплавки.

typedef float UILayoutPriority;
static const UILayoutPriority UILayoutPriorityRequired NS_AVAILABLE_IOS(6_0) = 1000; // A required constraint.  Do not exceed this.
static const UILayoutPriority UILayoutPriorityDefaultHigh NS_AVAILABLE_IOS(6_0) = 750; // This is the priority level with which a button resists compressing its content.
static const UILayoutPriority UILayoutPriorityDefaultLow NS_AVAILABLE_IOS(6_0) = 250; // This is the priority level at which a button hugs its contents horizontally.

Итак, хотя нам может показаться, что заранее определенные приоритеты макета являются значениями перечисления (как предполагает документация), приоритеты компоновки на самом деле не определены как перечисления; они определяются как постоянные поплавки.

Подсказка для всех, кто знает язык программирования C, состоит в том, что C-enum может содержать только значения int. Следующее правовое и будет компилироваться:

enum myEnum {
    JGCEnum_one = 1,
    JGCEnum_two,
    JGCEnum_three
} JGCEnum;

Но мы не можем определить float как значения для C перечислений. Следующие команды не будут компилироваться:

    enum myEnum {
        JGCEnum_one = 1.5, // compilation error
        JGCEnum_two,
        JGCEnum_three
    } JGCEnum;

Objective-C перечисления такие же, как C перечисления (Swift перечисления разные). Важно знать, имеем ли мы дело с действительными целыми числами или поплавками. Поскольку целые числа могут быть определены с помощью макроса NS_ENUM, который затем может быть импортирован в Swift как переименование Swift.

В iBook говорится:

Swift импортирует как перечисление Swift любое перечисление C-стиля, отмеченное макросом NS_ENUM. Это означает, что префиксы для имен значений перечисления усекаются, когда они импортируются в Swift, независимо от того, определены ли они в системных рамках или в пользовательском коде.

Отрывок из: Apple Inc. "Использование Swift с Cocoa и Objective-C." интерактивные книги. https://itun.es/us/1u3-0.l

Это означает, что если UILayoutPriority был определен как целое число с использованием макроса NS_ENUM, он был бы импортирован в Swift как переименование Swift. Это относится к UILayoutConstraintAxis.

Декларация SWIFT

enum UILayoutConstraintAxis : Int {
    case Horizontal
    case Vertical
}

OBJECTIVE-C

enum {
   UILayoutConstraintAxisHorizontal = 0,
   UILayoutConstraintAxisVertical = 1
};
typedef NSInteger UILayoutConstraintAxis;

Глядя на заголовочный файл Objective-C, подтверждает, что говорится в документации.

//
// UIView Constraint-based Layout Support
//

typedef NS_ENUM(NSInteger, UILayoutConstraintAxis) {
    UILayoutConstraintAxisHorizontal = 0,
    UILayoutConstraintAxisVertical = 1
};

Итак, существует как минимум два способа узнать, доступно ли предварительно определенное значение, которое вы используете для использования в Objective-C в Swift:

  • проверить документацию
  • проверьте файл заголовка в Objective-C (найденный, щелкнув правой кнопкой мыши значение, а затем выбрав "Перейти к определению" )

Есть еще один способ узнать, используется ли typedef для использования константа или перечисление. В коде проверьте, существует ли адрес константы. Константы имеют адрес памяти, а перечисления - нет. См. Код ниже.

// this line will compile and run just fine. 
// UILayoutPriorityDefaultHigh is a constant and has a memory address
// the value will be true if the device is running iOS 6.0 or later
// and false otherwise
BOOL predefinedValueIsAvailable = (NULL != &UILayoutPriorityDefaultHigh);

// this line will not compile
// UILayoutConstraintAxisHorizontal is an enum (NOT a constant) 
// and does not have a memory address
predefinedValueIsAvailable = (NULL != &UILayoutConstraintAxisHorizontal);

Ссылки