Не удается получить доступ к UIView во внешнем методе - PullRequest
0 голосов
/ 15 июня 2011

Я новичок в Objective-C, поэтому то, что я делаю по этому поводу, может быть смешным, но здесь говорится:

У меня есть форма для входа в приложение для iPhone.Когда пользователь вводит свои учетные данные, он нажимает Готово в верхнем правом углу, что вызывает IBAction, и появляется всплывающий пользовательский индикатор прогресса.Я создал этот индикатор с помощью класса, содержащего метод экземпляра с именем showProgressIndicator . showProgressIndicator создает и возвращает UIView, который я затем добавляю в свое представление следующим образом:

ProgressIndicatorElement *ProgressIndicator = [[ProgressIndicatorElement alloc] init];
box = [ProgressIndicator showProgressIndicator];
[self.view addSubview:box];

Я, конечно, объявил в качестве UIView поле в моем заголовочном файле.Индикатор прогресса прекрасно появляется, и тем временем я делаю закулисный URL-запрос, который, когда закончил, вызывает другой метод в моем контроллере представления с именем receiveServerResponse .Теперь я хочу удалить индикатор прогресса, поэтому я делаю это:

- (void)receivedServerResponse {
    [box removeFromSuperview];
}

Но ничего не происходит вообще.Я не получаю никаких ошибок или предупреждений, и код подсвечивается, как будто все работает гладко.Я пытался сохранить индикатор в своем IBAction, но это тоже не помогло.

Надеюсь, вы поможете!

Обновлено:

Вот метод showProgressIndicator :

- (UIView *)showProgressIndicator {
    box = [[UIView alloc] initWithFrame:CGRectMake(85, 190, 210, 140)];
    box.backgroundColor = [UIColor colorWithRed:0.0 / 255 green:0.0 / 255 blue:0.0 / 255 alpha:.6];
    box.layer.cornerRadius = 8;

    UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
    spinner.layer.frame = CGRectMake((box.layer.bounds.size.width - spinner.layer.bounds.size.width)/2, 20, spinner.layer.bounds.size.width, spinner.layer.bounds.size.height);
    [spinner startAnimating];
    [box addSubview:spinner];

    UILabel *titleInBox = [[UILabel alloc] initWithFrame:CGRectMake(0, 65, 150, 20)];
    titleInBox.font = [UIFont boldSystemFontOfSize:16];
    titleInBox.textColor = [UIColor whiteColor];
    titleInBox.textAlignment = UITextAlignmentCenter;
    titleInBox.backgroundColor = [UIColor clearColor];
    titleInBox.text = @"Authorizing...";
    [box addSubview:titleInBox];

    return box;
}

Второе обновление:

@ Дипак только что указал в комментариях, что я мог работатьдва разных экземпляра моего контроллера представления, который на самом деле, кажется, имеет место.Во внешнем классе, который обрабатывает вышеупомянутый URL-запрос, я возвращаюсь к методу receiveServerResponse контроллера представления, выполняя это:

- (void)requestFinished:(ASIHTTPRequest *)request {
    NSString *responseString = [request responseString];
    SignInViewController *viewController = [[SignInViewController alloc] init];
    [viewController receivedServerResponse];
}

Не распространяя себя слишком тонко (вероятно, слишком поздно;)), ASIHTTPRequest настроен так, что если вы вызываете один метод, который выполняет асинхронный URL-запрос, вызывается предопределенный метод с именем requestFinished (выше), поэтому мне пришлось вызывать мой контроллер представления следующим образомкстати, потому что я не могу получить доступ к возвращенному значению более простым способом (о котором я знаю).

Ответы [ 5 ]

2 голосов
/ 15 июня 2011

Создание нового экземпляра SignInViewController - неправильный путь.Кажется правильным только поддерживать слабую ссылку (свойство assign ed) объекта SignInViewController.Скажем, ваш класс RequestHandler.

@interface RequestHandler: [..] {
}

@property (nonatomic, assign) SignInViewController * signInViewController;

@end

@implementation RequestHandler
@synthesize signInViewController;
[..]
- (void)requestFinished:(ASIHTTPRequest *)request {
    NSString *responseString = [request responseString];
    [signInViewController receivedServerResponse];
}
@end

Итак, когда вы создаете RequestHandler объект в экземпляре SignInViewController, вы делаете,

RequestHandler * requestHandler = [[RequestHandler alloc] init];
requestHandler.signInViewController = self;
[..]

Обратите внимание, выможно также посмотреть на делегирование и notifications.

1 голос
/ 15 июня 2011

Я думаю, что часть проблемы может быть связана с управлением памятью. Если showProgressIndicator не возвращает автоматически выпущенный объект, попробуйте снять флажок после добавления его в качестве подпредставления, например так:

[self.view addSubview:box];
[box release];

box может не исчезнуть, если box не освобожден при удалении из суперпредставления.

Моя другая рекомендация заключается в том, что вместо того, чтобы делать это так, как вы, создавая представление, добавляя его, а затем пытаясь удалить его, вы можете попробовать добавить поле в качестве подпредставления, когда создается представление входа в систему и настройка его hidden свойство до YES, а затем, при необходимости, его скрытие.

На основе вашего обновления: У вас есть некоторые проблемы с управлением памятью в showProgressIndicator. Всякий раз, когда вы выделяете объект, вы должны освободить его. В этом случае отпустите все свои переменные после добавления их в качестве подпредставлений, как я упоминал выше. Однако box должен быть возвращен как объект с автоматическим освобождением, поскольку showProgressIndicator не знает, когда его нужно будет освободить. Для этого вам следует заменить return box; на return [box autorelease];

0 голосов
/ 15 июня 2011

Не раскрывая себя слишком (вероятно, слишком поздно;)), ASIHTTPRequest настроен так, что если вы вызываете один метод, который выполняет асинхронный URL-запрос, вызывается предопределенный метод requestFinished (выше), поэтому я ' Мне пришлось вызывать мой контроллер вида таким образом, потому что я не могу получить доступ к возвращенному значению более простым способом (насколько я знаю).

ASIHTTPRequest вызывает -requestFinished: для объекта, который вы указали в качестве делегата запроса. Вы должны спроектировать свои классы так, чтобы этот объект-делегат либо имел ссылку на контроллер представления, с которым вы хотите, чтобы он действовал, либо имел какие-то средства уведомления этого контроллера представления о необходимости выполнения действий. Самым простым решением может быть сделать контроллер делегатом запроса.

0 голосов
/ 15 июня 2011

Как насчет добавления вида окна на окно в appDelgate?Присвойте тег вашему boxView и в методе удаления верните boxView с помощью тега.Например, если вы задаете тег 99

- (void)receivedServerResponse {
    UIView *box = [window viewWithTag:99];
    [box removeFromSuperview];
}

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

0 голосов
/ 15 июня 2011

Вам нужно отправить индикатор активности сообщение stopAnimating, когда вы хотите остановить анимацию.Нет необходимости удалять его из суперпредставления;вместо этого просто убедитесь, что его свойство hidesWhenStopped установлено в YES.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...