【问题标题】:How to properly code "init" method in Objective-C, prevent "Expression result unused" warning如何在 Objective-C 中正确编码“init”方法,防止“表达式结果未使用”警告
【发布时间】:2013-02-19 08:59:52
【问题描述】:

我的教授给了我一个主要内容,我必须使用 Xcode 在 Objective-C 中制作 .h 和 .m 文件。我几乎完成了,但有两个警告我无法弄清楚如何摆脱,“未使用的表达式结果”。这些错误与我创建大小为 100 的数组的 init 方法有关。这里是 main 创建一个对象然后调用我不正确编码的方法的地方,这部分是我的老师给出的,我无法更改它:

//  main.m
//  ChutesAndLadders

#import <Foundation/Foundation.h>
#import "ChutesAndLadders.h"
int main(int argc, const char * argv[])
{   
    @autoreleasepool {

        ChutesAndLadders *cl = [[ChutesAndLadders alloc]init];
        [cl initBoard];
        [cl makeChutes:10];
        [cl makeLadders:10];

        int chutes=0; 
        int ladders=0;

        for(int i=0;i<cl.board.count;i++){
            NSString * cell = (NSString *)[cl.board objectAtIndex:i];
            int additionalSpaces = (int)[cl addToMove:cell];
            if(additionalSpaces>0)
                ladders++;
            else if (additionalSpaces<0)
                chutes++;
        }
        [cl printBoard];
    }
    return 0;
}

这是我的方法的相关部分:错误来自上面的“initBoard”方法和下面的“initWithCapacity”行。我知道这两个警告描述的是同一个错误。下面的代码是我的,所以我可以改变它,不像上面的。

@synthesize board = _board;

-(id) initBoard
    if((self = [super init]){
        [board intiWithCapacity: 100];
        for(int i = 0; i < 100; i++){
            [board addObject:@""];       
        }
    }
return self;
}

这是我在 .h 文件中声明“板”的相关代码:

@interface ChutesAndLadders : NSObject{
    @private

    NSMutableArray * board;
}
@property (readwrite, retain) NSMutableArray *board;

-(id) initBoard;

我尝试了很多语法上的小改动,但无济于事。 请不要直接告诉我解决方案,但我认为我只需要在正确的方向上轻推或推一下,我会在找到解决方案后发布解决方案。

伪解:

@synthesize board=board;

-(void) initBoard{
    _board = [board initWithCapacity: 100];
    for(int i =0; i < 100; i++){
        [_board addObject:@""];
    }
}

这消除了其中一个警告,但我的程序运行不正常,所以我还有其他方法要做。虽然这个具体问题已经得到解决,但我对它现在的工作方式有了更好的了解。

实际解决方案

@synthesize board=_board;

-(void) initBoard{
    _board = [NSMutableArray arrayWithCapacity:100];
    for(int i =0; i < 100; i++){
        [_board addObject:@"   "];
    }
}

这是最终根据Hermann 工作的一个。我发誓我尝试过一次但没有成功,所以我一直在玩并改变一些东西(把它搞得更糟),然后最终又回到了这个,它当然奏效了。 Xcode 的谎言有时会激怒我。

【问题讨论】:

  • 不能两次初始化对象...而board是实例对象的一个​​属性...

标签: objective-c init


【解决方案1】:

编辑因为起初我忽略了一些东西:

简单使用:

ChutesAndLadders *cl = [[ChutesAndLadders alloc]initBoard];

因为在 initBoard 中,无论如何您都在调用 [super init]

你的教授想欺骗你吗? 不看所有代码就很难说。 您正在合成具有 iVar _board 的属性板。 这意味着您可以通过self.board[self board][self setBoard: ...] 分别访问它的getter 或setter。

但是在 initBoard 方法中它的访问方式不同:

[board intiWithCapacity: 100];

尽管我们看不到板实际分配在哪里并且没有使用 initWithCapacity 方法的结果,但我问自己board 实际上是什么。它不是属性(即 self.board 等),也不是 iVar(即_board)。 显然,board 指的是您声明的私有 iVar。但是

@synthesize board = _board;

创建一个名称为 _board 且类型相同的 iVar (NSMutableArray*)。 因此,在您的方法中,board_board 不同。

虽然我现在第三次编辑这个,但我仍然没有得到它。 .m 文件是老师给的,你必须创建一个匹配的 .h 文件,对吗?在这种情况下,你应该去

@private
NSMutableArray * _board;

好吧,无论如何这都是自动完成的,但是用“_”编写它可以避免创建类似的命名 iVar,从而避免可能的错误。

背景 AFAIK:理论上甚至实际上 init 可能会创建与 alloc 创建的实例不同的实例。因此,您应该始终使用 init 的返回值。

一般来说——独立于围绕对象初始化的奇怪的objective-c符号——当一个方法返回一个值时,然后

[object method];

在语法上是正确的,运行良好,除了返回值之外的所有内容都未使用。这就是您的警告信息的全部内容。即使您将其分配给像

这样的虚拟对象
SomeClass *someObject = [object method];

你会得到警告说 `someClass' 是一个未使用的变量。

上次编辑: 你快到了。但是,这是当前版本的 Obj-C 的快捷方式,而不是旧版本: .h 文件:

@interface ChutesAndLadders : NSObject

@property (readwrite, retain) NSMutableArray *board;

-(void) initBoard;
@end

.m 文件:

// omitting @synthesize forces the compiler to autosynthesize. In that case it is named "_board"

    -(void) initBoard
        _board = [NSMutableArray arrayWithCapacity: 100]; // this implies the alloc
        for(int i = 0; i < 100; i++){
            [_board addObject:@""];       
        }
    }

【讨论】:

  • 我明白为什么第一行更可取。我没有明确说明我不允许触摸老师给出的那部分代码。
  • 请出示您老师的完整代码或至少更多。我有一种胆量,他想欺骗你们。
  • 好的,所以不需要 _。我对此感到困惑。我想我现在差不多了。
  • 我没说不需要。实际上使用它是一个很好的商业惯例,因为这样你总是可以看到你是在使用 setter/getter 还是直接访问 iVar。当涉及到不使用 ARC 的内存管理时,这可能是一个关键的区别。但它必须与@synthesize 语句相匹配。
  • @synthesize board=board; -(id) initBoard{ self = [super init]; if (self){ board = [board initWithCapacity: 100]; for(int i =0; i &lt; 100; i++){ [board addObject:@""]; } } return self; }
【解决方案2】:

您正在退回一些您没有使用的东西。还阅读了在 Objective-C 中编写正确的构造函数/初始化对象。

【讨论】:

  • 你说得对,我没有教科书,而且很难为初学者找到最新的指南/教程。我没有 Mac,买不起,所以我必须在虚拟机上编写代码,因为延迟时间有点让人头疼。
  • 查看http://developer.apple.com。有一个很好的初始化器解释here
  • 直到第二天我才收到“退回我不使用的东西”!我将方法更改为 void,但我仍在处理程序的其余部分。
【解决方案3】:

正如赫尔曼所说,你应该这样做

ChutesAndLadders *cl = [[ChutesAndLadders alloc]initBoard];

然后在你的 initBoard 方法中

self.board = [NSMutableArray alloc] intiWithCapacity: 100];

【讨论】:

    【解决方案4】:

    您没有遵循标准的 Objective-C 约定,这会让您陷入困境。

    你有一个实例变量板。 Objective-C 约定是所有实例变量都应该以下划线字符开头。

    你有一个属性板,@synthesize board = _board。合成创建一个带有下划线字符的实例变量,名为 _board。现在你有两个实例变量:board 和 _board。其中之一,_board,是支持 board 属性的实例变量。另一个,董事会,与董事会财产完全无关。

    然后在某个地方你有一个看起来无害但致命的声明板 = 随便什么。分配给那个完全无用的实例变量板。不是_board,而是board。如果您编写了 _board,那么您将遵循 Objective-C 约定:使用高度可见的名称分配给实例变量。或 self.board 这将是财产。

    而且 [board initWithCapacity:100] 什么也没做。首先,因为 board 实例变量(与 board 属性或 _board 实例变量完全无关)尚未分配。是零。将 initWithCapacity 发送到 nil 什么也不做。将 addObject 发送到 nil 也无济于事。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-09-02
      • 2012-02-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多