困惑为啥在Objective C中一段代码有效而另一段代码无效

Posted

技术标签:

【中文标题】困惑为啥在Objective C中一段代码有效而另一段代码无效【英文标题】:Confused why one piece of code works and another doesn't in Objective C困惑为什么在Objective C中一段代码有效而另一段代码无效 【发布时间】:2010-10-12 11:32:58 【问题描述】:

很抱歉标题非常模糊,我是 Objective C 的新手,并且在使用它时遇到了一些困难。基本上我有以下代码部分:

Graph *graph1 = [[Graph alloc] init];
[graph1 addNode:@"TEST"];

这在一定程度上起作用。但我想更改它,因为上面的代码发生在按下按钮时,因此我假设我每次执行此操作时都会创建一个新的“*graph1”。我想我可以简单地把它改成这样:

if(self = [super init]) 

    [self setGraph: [[Graph alloc] init]];

return self;

上面在init方法中,下面是修改后的函数:

[graph addNode:@"TEST"];

但是在调试时我发现 addNode 方法永远不会像这样被调用。

谢谢 扎克

这是 testViewController.h

#import <UIKit/UIKit.h>
@class Graph;
@class Node;

@interface testViewController : UIViewController 

    Graph       *graph;
    UILabel     *label;




@property (nonatomic, retain) IBOutlet UILabel *label;
@property (nonatomic, retain) Graph *graph;

- (IBAction) buttonPressed:(id)sender;

@end

这是 textViewController.m

#import "testViewController.h"
#import "Graph.h"
@implementation testViewController

@synthesize  label, graph;

- (id)init

    if(self = [super init]) 
    
        [self setGraph: [[Graph alloc] init]];
    
    return self;


- (IBAction)buttonPressed:(id)sender

    //Graph *graph1 = [[Graph alloc] init];
    [graph addNode:@"TEST"];


    Node *node1 = [[Node alloc] initWithLabel: @"LABEL"];
    label.text = node1.label;

【问题讨论】:

只是为了清楚我已经合成了“图表”。 【参考方案1】:

首先想到的是 graph 是 nil ,因此向它调用方法(发送消息)将不会产生任何结果。不需要的释放会导致 EXC_BAD_ACCESS,而这似乎并非如此。

我想您是在 UIViewController 子类中调用所有这些,对吧?你确定调用了正确的init吗?如果您使用的是 NIB,则应覆盖 -(id)initWithNibName:bundle: 并将代码放在那里。我猜代码可能在普通的 -(id)init 中,因为您调用的是 [super init] 而不是 [super initWithNibName:nameOrNil bundle:bundleOrNil],但是这样,如果初始化控制器使用 NIB,您的自定义代码永远不会被调用,因此 graph 为零。

顺便说一句,如果图形属性是(保留),您也会在 init 中导致内存泄漏。

【讨论】:

是的,我在 -(id)init 方法中调用它。我会尝试使用 -(id)initWithNibName:bundle: 好吧,我将不得不成为一个完整的菜鸟,并问我在哪里可以找到我的笔尖名称? 带有 xib 扩展名的文件。可能是@"testViewController" 您不需要调用 initWithNibName:bundle -- @sigsegv 建议这是您需要覆盖的 init 方法。它已经被你调用了,你的 init 没有被调用。 它通常在资源文件夹中,并且与您的 UIViewController 类具有相同的名称,但带有 .xib(是的,.xib)estension,但 UIViewController 不关心名称笔尖。您只需要定义一个 -(id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)bundle 方法并在其主体中调用超级实现。如果您使用的是 sdk“模板”应用程序之一,它可能从源代码中丢失,但如果您将新的 UIViewController 类添加到项目中,您会发现它已被注释。快速浏览一下就会清楚很多事情。【参考方案2】:

我确定您现在已经解决了这个问题,但我同意“添加”是“未被调用”的原因是您的图形对象此时为 nil

我会说,首先在您的“addNode”调用周围放置一条测试消息

 NSLog(@"We tried to add here");
[graph addNode:@"TEST"];

这将显示 add 正在被调用——我敢打赌。

然后,在您之前调用 add 调用之前初始化“graph”的地方,尝试有条件地初始化它:

 if(graph == nil) graph = [[Graph alloc] init];
[graph addNode:@"TEST"];

注意,这一切都只是为了发现问题。最后我想说你在如何处理记忆方面遇到了一些挑战。您可能没有参考问题,但后来泄漏。根据这段代码的执行频率,这可能是个问题。

但至少您可以通过上述测试更轻松地解决您的问题。

【讨论】:

【参考方案3】:

您是否在标题中声明了图形变量?即:Graph *graph; 和对应的@property (nonatomic, retain) Graph *graph;

然后我会这样做:

   -(id) init 
        graph = [[Graph alloc] init];
        [graph retain];
    

这可能会有所帮助(我认为它不会的唯一原因是因为 a)如果您的变量未声明,那么您将收到类似 graph may not respond to addNode 的警告,如果未保留,那么您的应用程序将崩溃当它运行时)......除此之外,我看不出会有什么问题。如果这不起作用,能否请您发布 .h 和 .m 文件中的所有代码?

【讨论】:

【参考方案4】:

然后我会这样做:

-(id) init 
        graph = [[Graph alloc] init];
        [graph retain];
    

这可能会有所帮助

这会导致内存泄漏。 graph 指向的对象的保留计数将具有 2 的保留计数。不理想。如果您使用 retain 属性声明该属性,那么

[self setGraph:[[[Graph alloc] init] autorelease]];

应该这样做。我去 -

self.graph = [[[Graph alloc] init] autorelease];

addNode: 方法未被调用的原因可能有很多。在封闭的方法中设置断点,看看一切是否如你所愿。

【讨论】:

如果你正确释放它不会导致内存泄漏......如果有一个保留属性,那么不能保证在你调用变量时它仍然在记忆。经过一定数量的代码行后,目标 c 中的变量可能会被遗忘。当您尝试访问该变量时,这将导致错误。这可以通过向变量添加保留来排序。另外,我认为这可能是问题,但可能不是问题。

以上是关于困惑为啥在Objective C中一段代码有效而另一段代码无效的主要内容,如果未能解决你的问题,请参考以下文章

为啥一个代码路径会立即在顶部显示表单,而另一个则不会?

为啥说Objective-C很难学

javascript组件封装中一段通用代码解读

对故事板和以编程方式推送 ios Objective C 感到困惑

为啥我在 Objective C 中获取 NSString 的值,例如 0xb000000000000033

为啥 Objective-C API 会返回隐式展开的可选项?