Доступ к методу viewController из другого класса - PullRequest
4 голосов
/ 10 апреля 2011

Я пытался использовать действие UIButton для вызова метода в другом классе (AppViewController). Сначала я попытался создать экземпляр контроллера представления в UIButton's вызывающем классе (caller.m), а затем вызвать метод, но это привело к EXC_BAD_ACCESS .

Я понимаю, что мне нужно указать на тот же экземпляр контроллера представления, и сейчас пытаюсь убедиться, что экземпляр контроллера представления правильно объявлен в caller.m.

У меня есть объявление AppViewController *viewController в AppDelegate, поэтому я думаю сослаться на тот же экземпляр из caller.m.

#import "caller.h"
#import "AppDelegate.h"

@implementation caller

- (id)initWithFrame:(CGRect)frame {
...
[btnSplash addTarget:viewController action:@selector(loadSplashView) forControlEvents:UIControlEventTouchUpInside];
....
}

Однако viewController по-прежнему отображается как необъявленный. Я пробовал несколько других вещей, но знаю, что, возможно, мне не хватает чего-то простого.

:::: :::: UPDATE

Хорошо, оказалось, что мне нужно было создать следующее, чтобы целевой "viewController" был фактически объявлен и указывал на правильный экземпляр:

AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
AppViewController* viewController = appDelegate.viewController;

Метод в классе контроллера представления теперь правильно вызывается.

Чтобы получить более понятную и более общую версию этого вопроса, перейдите сюда: Основы Objective-c: объект, объявленный в MyAppDelegate, недоступен в другом классе

Ответы [ 3 ]

6 голосов
/ 11 апреля 2011

Существует несколько способов, которыми объекты могут инициировать действия, общаться с другими объектами и / или наблюдать изменения, в которых они заинтересованы, включая:

  1. UIControl привязки к цели / действию
  2. Протоколы
  3. Наблюдение за ключом / значением (KVO)
  4. Уведомления

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

Я бы рекомендовал использовать протокол. Вы увидите множество протоколов, используемых в платформах iOS, в основном любой класс, имеющий свойство delegate, обычно определяет протокол, которому должны соответствовать делегированные объекты. Протокол - это контракт между двумя объектами, так что объект, определяющий протокол, знает, что он может взаимодействовать с объектом, соответствующим протоколу, без каких-либо других предположений относительно его класса или цели.

Вот пример реализации. Извинения, если какие-либо опечатки / упущения.

В caller.h (я предполагал, что caller является UIViewController):

@class Caller

@protocol CallerDelegate
    - (void)userDidSplashFromCaller:(Caller *)caller;
@end

@interface Caller : UIViewController
    id <CallerDelegate>    delegate;
@end

@property (nonatomic, assign)    id <CallerDelegate>    delegate;

@end

В звонилке м .:

@implementation Caller

@synthesize delegate;

- (void)viewDidLoad {
    // whatever you need
    // you can also define this in IB
    [btnSplash addTarget:self forAction:@selector(userTouchedSplashButton)];
}

- (void)dealloc {
    self.delegate = nil;
    [super dealloc];
}

- (void)userTouchedSplashButton {
    if (delegate && [delegate respondsToSelector:@selector(userDidSplashFromCaller:)]) {
        [delegate userDidSplashFromCaller:self];
    }
}

в другом ViewController.m:

// this assumes caller is pushed onto a navigationController
- (void)presentCaller {
    Caller *caller = [[Caller alloc] init];
    caller.delegate = self;
    [self.navigationController pushViewController:caller animated:YES];
    [caller release];
}

// protocol message from Caller instance
- (void)userDidSplashFromCaller:(Caller *)caller {
    NSLog(@"otherVC:userDidSplashFromCaller:%@", caller);
}

[РЕДАКТИРОВАТЬ: УТОЧНЕНИЯ]

После того, как я снова посмотрел на ваш вопрос и код, я понял, что сделал некоторые предположения, которые могут оказаться неверными в вашем коде. Скорее всего, вы все равно должны использовать протокол, но точный способ интеграции моего примера зависит от вашего приложения. Я не знаю, какой класс Caller есть в вашем приложении, но что бы это ни было, он имеет дело с UIButtons, так что это, скорее всего, контроллер представления или представление.

Ваш комментарий о том, что у вас нет правильного экземпляра вашего appViewController, заставляет меня задуматься, понимаете ли вы разницу между классами и экземплярами класса. Если мой ответ вам не поможет, пожалуйста, опубликуйте еще немного кода, показывающего, как вы создаете и представляете свой контроллер представления, а также как вы настраиваете кнопку, и я могу попытаться уточнить мой ответ.

3 голосов
/ 10 апреля 2011

Вы должны опубликовать NSNotification при нажатии кнопки, которая будет поймана и выполнена в AppViewController.

Так должно быть: В классе отправителя:

[btnSplash addTarget:self 
              action:@selector(loadSplashView) 
    forControlEvents:UIControlEventTouchUpInside]; 

-(void)loadSplashView:(id)sender 
{ 
[[NSNotificationCenter defaultCenter] postNotificationName:@"notif_name" object:some_sender_object];
}

В целикласс: Зарегистрируйтесь, чтобы получить уведомление при загрузке представления:

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(some_function:) name:@"notif_name" object:nil];

Определите действие, которое нужно выполнить в этом классе:

-(void) some_function:(NSNotification *)notif {
   //do something
   // to access the object do: [notif object]
}
0 голосов
/ 10 марта 2015

Связь между различными объектами вашего приложения является решением на уровне дизайна. Хотя iOS предоставляет удобные способы сделать это во время кода (свойства) - это жесткая связь.

Истинное взаимодействие между объектами не связывает объекты во время компиляции - это то, что может быть гарантировано только при следовании шаблонам проектирования.

Наблюдатели и делегаты - два наиболее часто используемых шаблона, и вам стоит узнать , когда использовать какой из них - см. Observer vs Delegate .

...