Подтвердить что ты не робот

Невозможно назначить себя вне метода в семействе init?

Я использую self like "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:.
4b9b3361

Ответ 1

Если ваш метод является инициализатором, он должен начинаться с init:

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

В противном случае вы можете изменить его как метод класса и вернуть новый экземпляр:

+ (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;
}

Ответ 2

Вы не можете инициализировать self вне метода init из-за следующего соглашение:

Если класс объектов не реализует инициализатор, Objective-C runtime вызывает инициализатор ближайшего предка вместо этого.

и потому, что имя некоторых методов распознается системой управления памятью среды выполнения:

Когда имя метода начинается с выделения init, сохранения или копирования, оно означает, что он создается для вызывающего, который несет ответственность за отпустите объект, когда он закончит с ним. В противном случае метод возвращенный не принадлежит вызывающему, и он должен указать, что он хочет чтобы он сохранял объект на объекте.

Следовательно, все инициализаторы должны быть записаны как вариация этого:

- (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.

Однако у вас есть еще две проблемы с вашим методом:

  • Вы комбинируете создание объекта ([super init]) и действие (-showDropDown::::) в том же методе. Вместо этого вы должны написать два разных метода.
  • Имя вашего метода -showDropDown::::. Objective-C программисты ожидают самоидентификацию имен методов, таких как -showDropDown:height:array:direction:. Я думаю, вы исходите из другого языка, но когда в Риме делайте то же, что и римляне, иначе вы не будете играть вместе с остальной командой.

Ответ 3

Я думаю, вам нужно переименовать ваш инициализатор (в настоящее время названный showDropDown) на что-то, начинающееся с init (например, initWithDropDown…). Это было просто соглашение (хотя и разумное), но теперь с ARC это жесткое требование.

Ответ 4

Проверьте правописание в этом методе

-(id)initwithArray:(NSArray *)array  

Код: (Objective-C)

-(id)initwithArray:(NSArray *)array