В настоящее время я делаю приложение, которое будет иметь несколько таймеров, которые в основном одинаковы.
Я хочу создать собственный класс, который использует весь код для таймеров, а также макет / анимацию, чтобы у меня было 5 одинаковых таймеров, которые работают независимо друг от друга.
Я создал макет с помощью IB (xcode 4.2), и весь код для таймеров в настоящее время находится только в классе viewcontroller.
Мне трудно понять, как инкапсулировать все в пользовательский класс, а затем добавить его в viewcontroller, любая помощь будет очень признательна.
UITableViewCell
илиUICollectionViewCell
. В моем случае мне нужно небольшое, но довольно сложное представление, которое я могу использовать много раз в контроллерах и представлениях коллекций. И дизайнеры продолжают его переделывать, поэтому я хочу, чтобы макет был определен в одном месте. Следовательно, перо.Ответы:
Чтобы ответить концептуально, ваш таймер, скорее всего, должен быть подклассом
UIView
вместоNSObject
.Чтобы создать экземпляр вашего таймера в IB, просто перетащите
UIView
его на представление вашего контроллера представления и установите его class равным имени вашего класса таймера.Не забудьте указать
#import
свой класс таймера в контроллере представления.Изменить: для дизайна IB (для создания экземпляра кода см. Историю изменений)
Я совсем не знаком с раскадровкой, но я знаю, что вы можете создать свой интерфейс в IB, используя
.xib
файл, который почти идентичен использованию версии раскадровки; Вы даже должны иметь возможность копировать и вставлять свои представления целиком из существующего интерфейса в.xib
файл.Чтобы проверить это, я создал новый пустой
.xib
файл с именем «MyCustomTimerView.xib». Затем я добавил представление, к которому добавил метку и две кнопки. Вот так:Я создал новый подкласс класса объектного C под
UIView
названием «MyCustomTimer». В моем.xib
я установил для своего класса владельца файла значение MyCustomTimer . Теперь я могу подключать действия и выходы, как и любой другой вид / контроллер. Полученный.h
файл выглядит так:Единственное препятствие, которое нужно преодолеть, - это получить это
.xib
на моемUIView
подклассе. Использование.xib
значительно сокращает требуемые настройки. И поскольку вы используете раскадровки для загрузки таймеров, мы знаем,-(id)initWithCoder:
что это единственный инициализатор, который будет вызван. Итак, вот как выглядит файл реализации:Названный метод
loadNibNamed:owner:options:
делает именно то, что кажется. Он загружает Перо и устанавливает для свойства «Владелец файла» значение self. Мы извлекаем первый объект в массиве, который является корневым представлением Nib. Мы добавляем представление как подвид, и вуаля оно отображается на экране.Очевидно, это просто меняет цвет фона метки при нажатии кнопок, но этот пример должен помочь вам в этом.
Примечания на основе комментариев:
Стоит отметить, что если у вас возникают проблемы с бесконечной рекурсией, вы, вероятно, упустили тонкую уловку этого решения. Он не делает то, что вы думаете. Представление, помещенное в раскадровку, не отображается, а вместо этого загружает другое представление как подпредставление. Это представление, которое он загружает, определено в пере. «Владелец файла» в пере - это невидимое изображение. Крутая часть заключается в том, что это невидимое представление по-прежнему является классом Objective-C, который можно использовать как своего рода контроллер представления для представления, которое он приносит из пера. Например,
IBAction
методы вMyCustomTimer
классе - это то, чего вы ожидаете больше от контроллера представления, чем от представления.В качестве примечания, некоторые могут возразить, что это не работает,
MVC
и я в чем-то согласен. С моей точки зрения, это более тесно связано с кастомомUITableViewCell
, который также иногда должен быть частью контроллера.Также стоит отметить, что этот ответ должен был предоставить очень конкретное решение; создайте один наконечник, который можно создавать несколько раз в одном и том же виде, что и на раскадровке. Например, вы легко можете представить шесть из этих таймеров одновременно на экране iPad. Если вам нужно только указать представление для контроллера представления, который будет использоваться несколько раз в вашем приложении, то решение, предоставленное jyavenard для этого вопроса , почти наверняка будет лучшим решением для вас.
источник
userInfo
свойство в уведомлении@property(nonatomic,copy) NSDictionary *userInfo;
File's Owner
установлено имя вашего класса, моя проблема с бесконечной рекурсией решена.[self addSubview:[[[NSBundle mainBundle] loadNibNamed:@"MyCustomTimerView" owner:self options:nil] objectAtIndex:0]];
добавления второго UIView ... Это выглядит странно для меня, никто другой не чувствует того же? Если да, то это яблоко сделано по дизайну? Или решение кто-то нашел, сделав это?Быстрый пример
Обновлено для Xcode 10 и Swift 4
Вот базовая процедура. Изначально я многому научился из этого сериала видео на Youtube . Позже я обновил свой ответ на основе этой статьи .
Добавить файлы пользовательского просмотра
Следующие два файла сформируют ваше собственное представление:
UIView
подклассДетали для их добавления приведены ниже.
Xib файл
Добавьте в свой проект файл .xib (Файл> Создать> Файл ...> Пользовательский интерфейс> Просмотр) . Я звоню своим
ReusableCustomView.xib
.Создайте макет, который должен иметь ваш пользовательский вид. В качестве примера я сделаю макет с a
UILabel
и aUIButton
. Рекомендуется использовать автоматический макет, чтобы размер объектов автоматически изменялся независимо от того, какой размер вы установите позже. (Я использовал Freeform для размера xib в инспекторе атрибутов, чтобы я мог настроить моделируемые метрики, но в этом нет необходимости.)Swift файл
Добавьте в проект файл .swift (Файл> Создать> Файл ...> Источник> Файл Swift) . Это подкласс,
UIView
и я называю его своимReusableCustomView.swift
.Сделайте файл Swift владельцем
Вернитесь к вашему файлу .xib и щелкните «Владелец файла» в структуре документа. В Identity Inspector напишите имя вашего файла .swift в качестве имени настраиваемого класса.
Добавить собственный код просмотра
Замените
ReusableCustomView.swift
содержимое файла следующим кодом:Убедитесь, что вы правильно написали имя вашего файла .xib.
Подключите розетки и действия
Подключите выходы и действия, перетащив элемент управления от метки и кнопки в макете xib к быстрому пользовательскому коду представления.
Используйте свой собственный вид
Ваш индивидуальный вид готов. Все, что вам нужно сделать, это добавить
UIView
в главную раскадровку в любом месте. Установите имя класса представленияReusableCustomView
в Identity Inspector.источник
Bundle.main
наBundle(for: ...)
помогает. Судя по всему,Bundle.main
во время разработки недоступен.init(frame:)
. После того, как вы добавите это (и поместите весь код инициализации в какую-либоcommonInit()
функцию), он будет работать нормально и отображаться в IB. См. Дополнительную информацию здесь: stackoverflow.com/questions/31265906/…Ответ для контроллеров представлений, а не представлений :
Есть более простой способ загрузить xib из раскадровки. Скажем, ваш контроллер имеет тип MyClassController, который наследуется от
UIViewController
.Вы добавляете
UIViewController
использующий IB в свою раскадровку; измените тип класса на MyClassController. Удалите вид, который был автоматически добавлен в раскадровку.Убедитесь, что XIB, который вы хотите вызвать, называется MyClassController.xib.
Когда будет создан экземпляр класса во время загрузки раскадровки, автоматически загрузится xib. Причина этого связана с реализацией по умолчанию,
UIViewController
которая вызывает XIB с именем класса.источник
'Could not load NIB in bundle: 'NSBundle </Users/me/.../MyAppName.app> (loaded)' with name 'uB0-aR-WjG-view-4OA-9v-tyV''
. Обратите внимание на whacko nibName. Я использую правильное имя класса для пера.На самом деле это не ответ, но я думаю, что полезно поделиться этим подходом.
Objective-C
стриж
По желанию :
Все, теперь вы можете добавить свой собственный вид в свою раскадровку, и он будет показан :)
CustomViewWithXib.h :
CustomViewWithXib.m :
CustomViewWithXib.swift :
Вы можете найти здесь несколько примеров .
Надеюсь, это поможет.
источник