Невозможно назначить себя вне метода в семействе 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:.
Ответы
Ответ 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