Obj-C: метод делегата не вызывается - PullRequest
3 голосов
/ 10 января 2012

Я новичок в iOS Dev, я слежу за классами Stanford CS193P на осень 2010 года. Я нахожусь на задании 3, и я настраиваю своего делегата на свое видение, и с помощью отладчика я замечаю вызов с моим делегатом метод не произойдет, я не понимаю, что может происходить. Мой код выглядит следующим образом:

GraphViewController.h:

@interface GraphViewController : UIViewController <GraphViewDelegate> {
    GraphView *graphView;
    float scale;
}

@property (retain) IBOutlet GraphView *graphView;
@property float scale;

- (IBAction)zoomIn;
- (IBAction)zoomOut;

@end

GraphViewController.m:

@implementation GraphViewController

@synthesize graphView, scale;

- (NSString *)functionForGraph:(GraphView *)requestor {
    NSLog(@"%@", @"culo peluo");
    return @"lol";
}

- (float)scaleForGraph:(GraphView *)requestor {
    return self.scale;
}

- (IBAction)zoomIn {

}

- (IBAction)zoomOut {

}

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {

    }
    return self;
}

- (void)dealloc
{
    [super dealloc];
}

- (void)didReceiveMemoryWarning
{
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];

    // Release any cached data, images, etc that aren't in use.
}

#pragma mark - View lifecycle

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.graphView.delegate = self;
    self.scale = 20;
    [self.graphView setNeedsDisplay];
}

- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    // Return YES for supported orientations
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

@end

GraphView.h:

@class GraphView;

@protocol GraphViewDelegate 
- (NSString *)functionForGraph:(GraphView *)requestor;
- (float)scaleForGraph:(GraphView *)requestor;
@end

@interface GraphView : UIView {
    id <GraphViewDelegate> delegate;
}

@property (assign) id <GraphViewDelegate> delegate;

@end

GraphView.m:

@implementation GraphView

@synthesize delegate;

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
    }
    return self;
}

- (void)drawRect:(CGRect)rect
{
    CGFloat cgScale = [self.delegate scaleForGraph:self];
    [AxesDrawer drawAxesInRect:self.bounds originAtPoint:self.center scale:cgScale]; 
}


- (void)dealloc
{
    [super dealloc];
}

@end

Ответы [ 4 ]

8 голосов
/ 10 января 2012
  1. Поместите точку останова на линию, где вы устанавливаете делегата представления графика.
  2. Проверьте переменную graphView. Это ноль?

Это происходит со мной все время, и всегда (ну почти всегда), потому что мне не удалось подключить розетку к представлению в конструкторе интерфейсов.

3 голосов
/ 31 июля 2013

Допустим, класс YourClass является делегатом для какого-то другого класса. И методы делегата не вызываются, несмотря на то, что свойство делегата установлено.

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

Изменение

YourClass *instance = [[YourClass alloc] init];

по

@property(nonatomic, strong) YourClass *instance;
self.instance = [[YourClass alloc] init]; 

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

Я написал большое сообщение в блоге по этой проблеме. Это довольно распространенная ситуация. http://alwawee.com/wordpress/2013/07/31/on-xmppframework-delegate-method-not-being-called/

1 голос
/ 10 января 2012

У меня есть несколько указателей для тебя:

  1. Вам не нужен iVar (внутренняя переменная), если у вас есть переменная в качестве свойства, она все равно будет работать, ямы никогда не узнаем этого.

GraphView

@interface GraphView : UIView {

}

@property (assign) id <GraphViewDelegate> delegate;

@end

GraphViewController

@interface GraphViewController : UIViewController <GraphViewDelegate> {

}

@property (retain) IBOutlet GraphView *graphView;
@property float scale;

- (IBAction)zoomIn;
- (IBAction)zoomOut;

@end
  1. Вы должны настроить своего делегата в своем представлении, чтобы иметь возможность его использовать.

GraphViewController

@implementation GraphViewController

( ... )

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        self.delegate = self;
    }
    return self;
}


( ... )

@end
0 голосов
/ 10 января 2012

Вы не вызываете делегатские функции нигде в вашем GraphView.m.Попробуйте протестировать его, поместив этот фрагмент кода в метод - (id)initWithFrame:(CGRect)frame прямо перед возвратом.

[self.delegate functionForGraph:nil];

и посмотрите, не записывает ли оно какие-либо сообщения на консоль.

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

...