Передача данных из interfaceController watchOS с помощью блока и перехода
Передача данных туда и обратно между интерфейсными контроллерами не так проста. В WatchKit есть процесс перехода, но первая проблема заключается в том, что нет prepareForSegue, и вы не можете получить доступ к targetViewController перехода, поэтому вы не можете легко вводить данные в новый контроллер (WatchOS 3-4). В обратном направлении выхода нет, поэтому вы не можете добраться до разматывающего перехода.
Еще одна проблема заключается в том, что эти решения пытаются обновить данные и пользовательский интерфейс первого interfaceController в методе willActivate, который запускается каждый раз, когда просыпается экран часов — довольно часто — и это может вызвать проблемы и усложнить.
Практика программирования в основном использует делегата и внедряет self с использованием контекста перехода, как описано в приведенных выше ответах.
Но использование делегата немного сложнее, поэтому я использую блоки, которые более современны и, как мне кажется, лучше и элегантнее.
Давайте посмотрим, как это сделать:
Сначала давайте подготовим переход в конструкторе интерфейсов раскадровки Apple Watch, просто соедините кнопку с другим интерфейсным контроллером, нажав кнопку Ctrl, и назовите переход.
![InterfaceBuilder для раскадровки Apple Watch](https://i.stack.imgur.com/guEl0.png)
затем в файле .h исходного interfaceController давайте назовем его SourceInterfaceController.h и объявим свойство для блока:
@property (nonatomic, strong) BOOL (^initNewSessionBlock)(NSDictionary *realTimeDict, NSError *error);
затем используйте contextForSegueWithIdentifier:, чтобы передать блок или любые другие данные в интерфейсный контроллер назначения, используя segueIdentifier, если у вас больше переходов.
Этот метод Apple фактически использует контекст (id) в качестве возвращаемого объекта, который может быть любым объектом, и метод awakeWithContext:(id)context целевого интерфейсаController будет использовать его при запуске interfaceController.
Итак, давайте объявим блок в SourceInterfaceController.m, а затем передадим его в контекст:
- (id)contextForSegueWithIdentifier:(NSString *)segueIdentifier {
__unsafe_unretained typeof(self) weakSelf = self;
if ([segueIdentifier isEqualToString:@"MySegue"]) {
self.initNewSessionBlock = ^BOOL (NSDictionary *mySegueDict, NSError *error)
{
[weakSelf initNewSession];
NSLog(@"message from destination IC: %@", realTimeDict[@"messageBack"]);
return YES;
};
return self.initNewSessionBlock;
}
else if ([segueIdentifier isEqualToString:@"MyOtherSegue"]) {
self.otherBlock = ^BOOL (NSString *myText, NSError *error)
{
//Do what you like
return YES;
};
return self.otherBlock;
}
else {
return nil;
}
}
Если вы хотите передать больше данных, чем просто блок с контекстом, в интерфейсный контроллер назначения, просто оберните их в NSDictionary.
В целевом интерфейсном контроллере с именем DestinationInterfaceController.h давайте объявим другое свойство для хранения блока, используя любое имя, но то же объявление переменной
@property (copy) BOOL (^initNewSessionBlock)(NSDictionary *realTimeDict, NSError *error);
затем извлеките блок из контекста в DestinationInterfaceController.m:
- (void)awakeWithContext:(id)context {
[super awakeWithContext:context];
self.initNewSessionBlock = context;
}
Позже в DestinationInterfaceController.m просто активируйте блок, например, в методе действия с кнопкой:
- (IBAction)initNewSessionAction:(id)sender {
NSError *error = nil;
NSDictionary *realTimeDict = @{@"messageBack" : @"Greetings from the destination interfaceController"};
BOOL success = self.initNewSessionBlock(realTimeDict, error);
if (success) {
[self popController];
}
}
Блок будет выполняться любым методом исходного интерфейсного контроллера, используя данные в области действия целевого интерфейсного контроллера, поэтому вы можете отправить данные обратно в целевой исходный контроллер. Вы можете вытолкнуть интерфейсный контроллер с помощью popController, если все в порядке и блок возвращает yes как BOOL.
Примечание. Конечно, вы можете использовать любой переход, будь то push или modal, а также вы можете использовать pushControllerWithName:context: для запуска segue, и вы можете использовать контекст этого метода таким же образом.
person
BootMaker
schedule
26.09.2017