由于某些原因,永远不会调用属性的自定义setter。所以它在运行时总是以零的形式出现。
我有一个视图控制器,它创建NSValue对象的NSArray,并将其作为属性传递给视图。然而,即使我使用调试器验证视图控制器中的NSArray是否正常,该属性也始终为零。
视图控制器@接口图形ViewController()@属性(非原子,弱)IBOutlet GraphingView*graphicView;@结束
- (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属性,它在视图中也始终为零。但是,当视图控制器将其传递到视图时,它包含数百个对象。
我只是不明白为什么这个属性总是零,如果我在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方法,而不是在prepare for segue中调用。这样可以确保视图已经创建。我还遇到了另一个问题,因为从视图访问视图控制器中数据的出口没有在视图设置器中初始化。
在视图委托方法viewDidLoad 中调用图上的确定点
在调用setter 之前,请确保self.graphingView不是nil
在初始化self.graphingView之前,您似乎过早地发送了消息-(void)setPointsOnGraph:(NSArray*)pointsOnGraph。
我建议您在GraphingViewController的viewWillAppear中发送消息-(void)determinePointsOnGraph。这是因为在设置NSArray点OnGraph之前,您的self.graphingView应该被初始化(这应该在调用-viewDidLoad时完成)。
为了确认我的建议是否有效,请添加此GramingViewController的实现,特别是调用消息-(void)determinePointsOnGraph的部分。
为了供您参考,当我对视图和方法的顺序感到困惑时,我在viewDidAppear、viewDidLoad、drawRect和viewWillAppear中输入NSLogs,以澄清发生了什么。顺序应为viewDidLoad->viewWillAppear->drawRect->viewDidAppear。
另一方面,如果您的代码工作正常,则graphicView中的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];
忘记自动释放。