24

" " のような自己を使用していますが、次のコードで " "self = [super init];エラーが発生します。cannot assign to self out of a method in the init family

- (id)showDropDown:(UIButton *)b:(CGFloat *)height:(NSArray *)arr:(NSString *)direction {
    btnSender = b;
    animationDirection = direction;
    self = [super init];
    if (self) {
        // Initialization code
        CGRect btn = b.frame;
        self.list = [NSArray arrayWithArray:arr];

        if ([direction isEqualToString:@"up"]) {
            self.frame = CGRectMake(btn.origin.x, btn.origin.y, btn.size.width, 0);
            self.layer.shadowOffset = CGSizeMake(-5, -5);
        }else if ([direction isEqualToString:@"down"]) {
            self.frame = CGRectMake(btn.origin.x, btn.origin.y+btn.size.height, btn.size.width, 0);
            self.layer.shadowOffset = CGSizeMake(-5, 5);
        }

        self.layer.masksToBounds = NO;
        self.layer.cornerRadius = 8;
        self.layer.shadowRadius = 5;
        self.layer.shadowOpacity = 0.5;

        table = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, btn.size.width, 0)];
        table.delegate = self;
        table.dataSource = self;
        table.layer.cornerRadius = 5;
        table.backgroundColor = [UIColor colorWithRed:0.239 green:0.239 blue:0.239 alpha:1];
        table.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
        table.separatorColor = [UIColor grayColor];

        [UIView beginAnimations:nil context:nil];
        [UIView setAnimationDuration:0.5];
        if ([direction isEqualToString:@"up"]) {
            self.frame = CGRectMake(btn.origin.x, btn.origin.y-*height, btn.size.width, *height);
        } else if([direction isEqualToString:@"down"]) {
            self.frame = CGRectMake(btn.origin.x, btn.origin.y+btn.size.height, btn.size.width, *height);
        }
        table.frame = CGRectMake(0, 0, btn.size.width, *height);
        [UIView commitAnimations];

        [b.superview addSubview:self];
        [self addSubview:table];
    }
    return self;
}

エラー:

 Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Requesting the window of a view (<NIDropDown: 0x684ac50; frame = (0 0; 0 0); transform = [0, 0, 0, 0, 0, 0]; alpha = 0; opaque = NO; layer = (null)>) with a nil layer. This view probably hasn't received initWithFrame: or initWithCoder:.
4

5 に答える 5

64

If your method is an initializer, it must start with init:

- (instancetype)initWithDropDown:(UIButton *)b:(CGFloat *)height:(NSArray *)arr:(NSString *)direction

Otherwise, you can change it to be a class method, and return a new instance:

+ (instancetype)showDropDown:(UIButton *)b:(CGFloat *)height:(NSArray *)arr:(NSString *)direction
{
    btnSender = b;
    animationDirection = direction;
    YourClassName obj = [[self alloc] init];
    if (obj) {
        // Initialization code
        // …
    }
    return obj;
}
于 2013-04-15T10:56:13.100 に答える
7

次の規則のため、メソッドのself外で初期化することはできません。init

オブジェクトのクラスが初期化子を実装していない場合、Objective-C ランタイムは代わりに最も近い祖先の初期化子を呼び出します。

一部のメソッドの名前は、ランタイムのメモリ管理システムによって認識されるためです。

メソッドの名前が alloc init、retain、または copy で始まる場合、呼び出し元のために作成されていることを意味します。呼び出し元は、オブジェクトの処理が完了したときにオブジェクトを解放する責任があります。それ以外の場合、返されたメソッドは呼び出し元によって所有されていないため、オブジェクトで保持を呼び出し続けたいことを示す必要があります。

したがって、すべてのイニシャライザは、次のバリエーションとして記述する必要があります。

- (id) init {
    self = [super init];
    if (self){
        _someVariable = @"someValue";
    }
    return self;
}
  • 汚いので使わないif ((self = [super init]))でください。
  • self.someVariableオブジェクトがまだ初期化されていない可能性があるため、使用しないでください。代わりに直接変数アクセスを使用してください ( _someVariable)。
  • 異なるインスタンスが返される可能性があるという理由self = [super init]だけではありません。[super init]
  • if (self)戻ってくる場合もあるので書いておきnilます。

ただし、この方法にはさらに 2 つの問題があります。

  • [super init]オブジェクトの作成 ( ) とアクション ( -showDropDown::::) を同じメソッドで組み合わせています。代わりに、2 つの別個のメソッドを作成する必要があります。
  • メソッドの名前は-showDropDown::::. Objective-C プログラマーは代わりに、自己文書化されたメソッド名を期待しています-showDropDown:height:array:direction:。あなたは別の言語から来たと思いますが、ローマにいるときは、ローマ人のように行動してください。そうしないと、チームの他のメンバーと一緒にプレーすることはできません.
于 2013-04-15T11:21:04.043 に答える
1
于 2013-04-15T10:55:03.683 に答える