Как установить значения по умолчанию для IBInspectable в Objective-C?

Я знаю, что значения по умолчанию для IBInspectable-properties могут быть установлены как:

@IBInspectable var propertyName:propertyType = defaultValue в Свифте. Но как мне добиться аналогичного эффекта в Objective-C, чтобы я мог иметь значение по умолчанию для некоторого свойства, установленного на что-то в Interface Builder?


person Can Poyrazoğlu    schedule 20.11.2014    source источник
comment
Вы когда-нибудь получали решение для этого?   -  person Fogmeister    schedule 22.01.2015
comment
@Fogmeister Нет, к сожалению, нет. Я начал думать, что это невозможно, поскольку IB Inspectables — это новая функция, появившаяся одновременно со Swift, которая поддерживает значения по умолчанию. Поскольку ObjC не поддерживает значения по умолчанию, и поскольку Apple вряд ли добавит такую ​​функцию в ObjC, я очень сомневаюсь, что это возможно. Они могли бы добавить макрос Xcode (например, что-то вроде IBDefaultValue), но это будет поддерживать устаревший язык, против которого, я думаю, Apple будет.   -  person Can Poyrazoğlu    schedule 22.01.2015
comment
Хорошо, спасибо за ответ: D Тогда вернемся к старому методу для меня. Раздражает, что вы также не можете указать UIFont как тип IBInspectable. Я бы подумал, что это возможно, учитывая, что он есть у UILabel. Ну что ж :)   -  person Fogmeister    schedule 22.01.2015
comment
@Fogmeister, да, это очень раздражает, однако я думаю, что со временем он будет поддерживать больше типов (глядя на вас, перечисления!) И функций. Если вы хотите добавить свойство шрифта, взгляните на это: github.com /can16358p/CPTutorial/blob/master/CPTutorialBalloon.m (перейдите к строке 212) Это небольшая библиотека, которую я написал, которая принимает имя шрифта в Interface Builder и может динамически преобразовать строку имени шрифта в фактический шрифт в ИБ и время выполнения. Не стесняйтесь копировать его в свой проект, если это поможет.   -  person Can Poyrazoğlu    schedule 22.01.2015
comment
Хорошо, спасибо! Сейчас посмотрю.   -  person Fogmeister    schedule 22.01.2015
comment
Зарегистрировано как ошибка некоторое время назад: openradar.me/19044397 и закрыто как воспроизводимое/обман... Dupe master, похоже, отсутствует на OpenRadar.   -  person jscs    schedule 21.03.2016


Ответы (5)


Поскольку значения IBInspectable устанавливаются после initWithCoder: и перед awakeFromNib:, вы можете установить значения по умолчанию в методе initWithCoder:.

@interface MyView : UIView
@property (copy, nonatomic) IBInspectable NSString *myProp;
@property (assign, nonatomic) BOOL createdFromIB;
@end

@implementation MyView

- (id)initWithCoder:(NSCoder *)aDecoder {
    self = [super initWithCoder:aDecoder];
    if(self != nil) {
        self.myProp = @"foo";
        self.createdFromIB = YES;
    }
    return self;
}

- (void)awakeFromNib {
    if (self.createdFromIB) {
        //add anything required in IB-define way
    }
    NSLog(@"%@", self.myProp);
}

@end
person rintaro    schedule 21.11.2014
comment
спасибо, но я на самом деле ищу способ, чтобы значения были видны IB. это возможно? - person Can Poyrazoğlu; 21.11.2014
comment
Извините, но я не знаю. - person rintaro; 21.11.2014
comment
Вы только что спасли мой бекон @rintaro. Я пытался настроить свой пользовательский элемент управления со значениями из IBInspectables во время initWithCoder: и не мог понять, почему все они равны нулю. Теперь я настраиваю свой пользовательский элемент управления в awakeFromNib, и все в порядке. Спасибо! - person user2320861; 14.10.2015
comment
Спасибо за ответ! Кроме того, чтобы увидеть последствия использования в раскадровке, вам необходимо реализовать - (void)prepareForInterfaceBuilder, который будет использовать проверяемые значения для рендеринга. - person ElyashivLavi; 29.10.2017

Я написал свой код так. У меня это работает очень хорошо, как при проектировании в конструкторе интерфейсов, так и при работе в качестве приложения.

@interface MyView : UIView

@property (copy, nonatomic) IBInspectable propertyType *propertyName;

@end

- (void)makeDefaultValues {
    _propertyName = defaultValue;
    //Other properties...
}

- (instancetype)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        [self makeDefaultValues];
    }
    return self;
}

- (instancetype)initWithCoder:(NSCoder *)aDecoder {
    if (self = [super initWithCoder:aDecoder]) {
        [self makeDefaultValues];
    }
    return self;
}
person GetToSet    schedule 02.08.2015
comment
Позволяет ли это мне проверить значения в Interface Builder, о чем я и спрашиваю. - person Can Poyrazoğlu; 02.08.2015
comment
Вы можете видеть только значения по умолчанию в инспекторе атрибутов, но вы можете видеть представление, нарисованное со значениями по умолчанию, записанными в коде. - person GetToSet; 02.08.2015
comment
Да, спасибо за ответ, но я уже знаю об этом. Я спрашиваю о решении, которое позволяет Inspector получать эти значения по умолчанию, как в Swift. - person Can Poyrazoğlu; 02.08.2015
comment
Может быть, я не могу решить эту проблему, но я думаю, что нет необходимости видеть значения в инспекторе, поскольку они уже нарисованы в представлении. - person GetToSet; 02.08.2015
comment
С точки зрения программирования мне не нужен ни один из них. Но при проектировании (особенно при передаче его нетехническим людям для настройки значений) это становится проблемой. - person Can Poyrazoğlu; 02.08.2015

я так пользуюсь

@IBInspectable var propertyNameValue:propertyType?
var propertyName:propertyType { return propertyNameValue ?? defaultValue }

если propertyNameValue имеет nil, propertyName вернет defaultValue.

person Wanbok Choi    schedule 03.08.2015
comment
Это может работать в Swift, но проблема с Objective-C. У нас уже есть решение для Swift. - person Can Poyrazoğlu; 03.08.2015
comment
это нормально, мы все так делаем :) - person Can Poyrazoğlu; 03.08.2015

Почему бы не использовать макрос, например:

#if TARGET_INTERFACE_BUILDER   
// .....IB only specific code when being rendered in IB 
#endif 

???

Селектор prepareForInterfaceBuilder также может помочь вам реализовать код, специфичный для IB.

Подробнее об этих двух пунктах можно узнать здесь:
https://developer.apple.com/library/ios/recipes/xcode_help-IB_objects_media/chapters/CreatingaLiveViewofaCustomObject.html

person yonel    schedule 08.12.2014
comment
позволяет ли это мне видеть значения по умолчанию в инспекторе IB, о чем я и спрашиваю? в остальном я знаю макросы и метод prepareForInterfaceBuilder. - person Can Poyrazoğlu; 09.12.2014

Сначала я попытался переопределить геттер и сделал что-то вроде этого:

- (UIColor *)borderColor {
    return _borderColor ?: [UIColor greenColor];
}

Но в этом случае я получил сообщение о необъявленном идентификаторе _borderColor.

Хорошо, я попытался избежать этой проблемы с помощью пользовательского геттера.

- (UIColor *)getBorderColor {
    return _borderColor ?: [UIColor greenColor];
}

На самом деле это не правильный геттер, так как мы не указываем этот метод как геттер. В случае, если мы укажем, мы получим сообщение о необъявленном идентификаторе, поэтому мы не будем.

Затем мы используем этот метод для получения значения свойства в методе updateUI.

Также мы должны переопределить сеттер:

- (void)setBorderColor:(UIColor *)borderColor {
  _borderColor = borderColor;
  [self updateUI];
}
person kaspartus    schedule 02.03.2015
comment
Как это связано с Interface Builder? - person Shebuka; 19.02.2016
comment
Вам нужно добавить @synthesize borderColor=_borderColor, потому что компилятор не будет генерировать iVar, если вы предоставите геттер и сеттер. - person Adam Kaplan; 22.04.2016