【问题标题】:Method in View Controller Called before View initialized - iPhone iOS 5 SDK在视图初始化之前调用视图控制器中的方法 - iPhone iOS 5 SDK
【发布时间】:2012-02-25 00:44:51
【问题描述】:

由于某种原因,属性的自定义设置器永远不会被调用。所以它在运行时总是以 nil 的形式出现。

我有一个视图控制器,它创建一个 NSValue 对象的 NSArray 并将其作为属性传递给视图。但是,该属性始终为 nil,即使我使用调试器验证视图控制器中的 NSArray 是否正常。

视图控制器 @interface GraphingViewController() @property (nonatomic, weak) IBOutlet GraphingView *graphingView; @结束

- (void) determinePointsOnGraph
{
    NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
    NSMutableArray *pointsForGraph = [[NSMutableArray alloc] init];

    float startingPoint = -250;
    for (int i = 0; i < 500; i++) {
        float x = startingPoint;
        startingPoint++;

       [dict setValue:[NSNumber numberWithFloat:x] forKey:[NSString stringWithString:@"x"]];
       float y = [CalculatorBrain runProgram:[self graph] usingVariableValues:dict];

       [pointsForGraph addObject:[NSValue valueWithCGPoint:CGPointMake(x,y)]];
}

//This calls the pointer to the view, and the setter for the view's property
[self.graphingView setPointsOnGraph:pointsForGraph];
}

查看

@synthesize pointsOnGraph = _pointsOnGraph;
- (void)setPointsOnGraph:(NSArray *)pointsOnGraph
{
    //Custom setter for property, never gets called if a break point is put here
    _pointsOnGraph = pointsOnGraph;
    [self setNeedsDisplay];
}

- (void)drawLine:(NSArray *)pointsOfLine inContext:(CGContextRef)context
{    
    CGPoint pointsOfLineAsCGPoints[[pointsOfLine count]];

    for (int i = 0; i < sizeof(pointsOfLineAsCGPoints); i++) {
       pointsOfLineAsCGPoints[i] = [[pointsOfLine objectAtIndex:i] CGPointValue];
    }

    CGContextAddLines(context, pointsOfLineAsCGPoints, sizeof(pointsOfLine));
    CGContextClosePath(context);
    CGContextStrokePath(context);
}

drawLine 方法由drawRect 调用,并作为pointsOfLine 传递给pointsOnGraph 属性。即使我在 drawRect 中放置一个断点并查看 pointsOnGraph 属性,它在视图中始终为零。然而,当它被视图控制器传递给视图时,它包含数百个对象。

我只是不明白为什么该属性总是 nil,如果我在 setter 中设置一个断点,它就永远不会被调用。

更新 我已经验证第一次调用视图时对视图的 faceView 引用为零,但 IBOutlet 似乎已正确连接,并且视图最终会显示。似乎在 self.graphingView IBOutlet 初始化之前调用了视图控制器方法

以下内容来自我从视图控制器

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if([segue.identifier isEqualToString:@"Graphing"] ) {
        [segue.destinationViewController setGraph:[[self.brain program] mutableCopy]]; 
        [segue.destinationViewController determinePointsOnGraph];

    }
}

解决方案 在 viewDidLoad 委托中调用 determinePointsOnGraph 方法,而不是在准备 segue 中。这可确保已创建视图。我还遇到了另一个问题,即从视图中访问视图控制器中数据的出口没有在视图设置器中初始化。

【问题讨论】:

    标签: iphone objective-c ios nsarray setter


    【解决方案1】:

    在视图委托方法 viewDidLoad 中调用确定图上的点

    【讨论】:

    • 非常感谢,它需要更多的操作才能让它工作,但问题是我不懂代表。感谢您的帮助,并为我指明了正确的方向。
    【解决方案2】:

    在调用 setter 之前确保 self.graphingView 不为零

    【讨论】:

    • self.graphingView 为零,但我指的是一个出口,所以我不确定我应该如何创建视图?
    • 如果视图可见,请确保您的 IBOutlet 连接正确
    • 我从另一个视图控制器segue到graphingViewController,似乎在IBOutlet初始化视图之前调用了视图控制器方法?
    【解决方案3】:

    您似乎在 self.graphingView 初始化之前太早发送消息 - (void)setPointsOnGraph:(NSArray *)pointsOnGraph

    我建议你在GraphingViewController的viewWillAppear中发送消息- (void)determinePointsOnGraph。这是因为你的 self.graphingView 应该在你设置 NSArray pointsOnGraph 之前被初始化(这应该在 -viewDidLoad 被调用的时候完成)。

    为确认我的建议可行,请添加您对此 GraphingViewController 的实现,尤其是调用消息的部分 - (void) determinePointsOnGraph

    供您参考,当我对视图和方法的顺序感到困惑时,我在 viewDidAppear、viewDidLoad、drawRect 和 viewWillAppear 中输入 NSLogs 以澄清发生了什么。顺序应该是viewDidLoad -> viewWillAppear -> drawRect -> viewDidAppear

    另一方面,如果您的代码正常工作,您在 graphingView 中的 setter 方法会泄漏内存。在将 _pointsOnGraph 设置为给定指针之前,您需要释放它。例如,您可以按如下方式实现它:

    - (void)setPointsOnGraph:(NSArray *)pointsOnGraph
    {
        [_pointsOnGraph release];
        _pointsOnGraph = pointsOnGraph;
        [self setNeedsDisplay];
    }
    

    另外,您应该在发送消息之前自动释放 NSArray,例如:

    [self.graphingView setPointsOnGraph:[pointsForGraph autorelease]];
    

    但更好的是,您可以通过不分配初始化 NSMutableArray 来减少代码和括号的数量。这可以通过改变来完成

    NSMutableArray *pointsForGraph = [[NSMutableArray alloc] init];
    

    NSMutableArray *pointsForGraph = [NSMutableArray dictionary];
    

    忘记自动释放。

    【讨论】:

    • 谢谢,你说得对,我在视图初始化之前调用了该方法。我对其进行了更改,以便视图使用插座来调用视图控制器,这似乎可以解决所有问题。
    • 关于内存管理的笔记也很有用,非常感谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-11-27
    • 2010-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多