2015-01-31 2 views
4

У меня возникают проблемы с приложением iOS 8. Моему приложению нужно получить информацию с веб-сервера, чтобы определить, должны ли рекламироваться или нет. Это может занять некоторое время, поэтому код в viewDidLoad не ждет его и вместо этого вызывает setCanDisplayBannerAds:NO. Затем, когда информация поступает, setCanDisplayBannerAds:YES вызывается за пределами viewDidLoad.Неверный макет после ротации, если баннерная реклама включена вне viewDidLoad

Я определил, что мне нужно позвонить setCanDisplayBannerAds:NO внутри viewDidLoad иначе setCanDisplayBannerAds:YES не будет правильно ссылаться на объявления и генерировать множество внутренних исключений.

Проблема заключается в том, что после того, как объявления включены за пределами viewdidLoad, макет испортится. Я проиллюстрировал два изображения ниже. Верхний «до», нижний «после», как и после Показывает рекламу.

Обратите внимание на «до» изображения, Показать объявления и Просто Ярлык оба появляются в соответствующих углах после поворота. В изображении «после» ориентация ландшафта больше не правильная. Он поддерживает портретные рамки с Только ярлык и рекламный баннер отключен.

Я представил отчет об ошибке Apple и предоставил образец проекта, доступный на DropBox, как ID19658866.zip. Не стесняйтесь загружать его и попробовать.

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

before *Show Ads* is tappedafter *Show Ads* is tapped

ответ

4

Поместите эти две линии в viewdidLoad:

[self setCanDisplayBannerAds:YES]; 
[self setCanDisplayBannerAds:NO]; 

Первый вызов устанавливает объявления правильно, второй сразу же делает, что они не показывают. Позже вы можете позвонить [self setCanDisplayBannerAds:YES];, и он без проблем справится с изменениями ориентации.

1

Всего выстрел в темноте, но что произойдет, если вы звоните setNeedsLayout или setneedsupdatecontraint (при условии, что вы используете автоматическую раскладку, которую я предполагаю, что вы есть), как только объявления приходят? Кроме того, убедитесь, что ваши ограничения правильно настроены между просмотром объявления и другими. Вероятно, это неверный ответ, но я надеюсь, что он предоставит дополнительную информацию о реальной проблеме/решении.

+0

Спасибо, попробовали как 'setNeedsUpdateConstraints',' setNeedsLayout', так и 'setNeedsDisplay' в отдельности и в комбинации - все еще есть ошибка компоновки. Потому что он включает iAds, надеясь получить ответ от Apple раньше, чем позже. – Buddy

+0

Да, я был уверен, что это не будет решением, но, надеюсь, вы увидите что-то, что может пролить некоторый дополнительный свет на реальную проблему/решение. Что бы вы ни обнаружили, я надеюсь, что вы вернетесь и обновите свою публикацию тем, что вы в конечном итоге узнаете. Спасибо дружище. – BonanzaDriver

+0

Возможно, это комментарий. Сохранить ответы для ответов, а не догадываться, чтобы схватить очки. – jww

3

Если честно, Yimin Rong's answer, вероятно, будет работать, по крайней мере, с текущим SDK. Но это немного странно. На самом деле это не объясняет , почему это сработает.

Глядя на документацию для setCanDisplayBannerAds: мы видим:

Важно отметить, что это будет изменить иерархию вида контроллера вида, вставив новый вид контейнера выше точки зрения контроллера представления. Воздействие на то, что свойство представления контроллера представления больше не будет возвращать первоначально предоставленное представление, оно вернет новый контейнер. Чтобы получить доступ к исходному виду, используйте свойство originalContentView.

Таким образом, это фактически заменяет ваше имущество .view вашего UIViewController. Запомни.

Когда UIViewController отображается на экране, он изменяется на весь экран (или, по крайней мере, на контейнер, который он занимает). Из-за этого свойство .view UIViewController получает autoresizing maskUIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth, поэтому его высота и ширина являются гибкими и могут растягиваться, чтобы соответствовать контейнеру.

При вызове [self setCanDisplayBannerAds:YES]; в viewDidLoad, .view свойства вашего UIViewController ныряет заменяется новым UIView, и так как он находится в viewDidLoad, его autoresizingMask получает соответствующее значение. И наоборот, вызов [self setCanDisplayBannerAds:NO]; в viewDidLoad фактически ничего не делает.

В вашем примере приложения, когда вы звоните [self setCanDisplayBannerAds:YES];вне из viewDidLoad, мы можем видеть, что autoresizingMask делает не на самом деле получить набор растягиваться. Это то, что вызывает проблему:

- (IBAction)TouchUpInside:(id)sender { 
    NSLog(@"Touch Up Inside"); 
    NSLog(@"Original View: %@", self.view); 
    [self setCanDisplayBannerAds:YES]; 
    NSLog(@"New View: %@", self.view); 
    NSLog(@"Content View: %@", self.originalContentView); 
} 

Output: 
2015-02-05 11:32:19.654 ID19658866[12404:3600041] Touch Up Inside 
2015-02-05 11:32:19.655 ID19658866[12404:3600041] Original View: <UIView: 0x7f9c42717440; frame = (0 0; 375 667); autoresize = W+H; layer = <CALayer: 0x7f9c42717710>> 
2015-02-05 11:32:19.666 ID19658866[12404:3600041] New View: <UIView: 0x7f9c42523fb0; frame = (0 0; 375 667); layer = <CALayer: 0x7f9c42524080>> 
2015-02-05 11:32:19.666 ID19658866[12404:3600041] Content View: <UIView: 0x7f9c42717440; frame = (0 0; 375 667); autoresize = W+H; layer = <CALayer: 0x7f9c42717710>> 

Ключевым моментом здесь является в 3-й строке вывода, где «Новый взгляд» делает не уже autoresize = W+H; включены в вывод. Мы также подтвердили, что self.view заменяется новым представлением между 2-й и 3-й строками вывода.

Чтобы исправить это, мы можем убедиться, что наш новый self.view свойство получает необходимое autoresizingMask, добавив следующую строку после того, как мы называем [self setCanDisplayBannerAds:YES];:

self.view.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; 

И это будет работать, и мы будем знать, почему.

Или мы могли бы, вы знаете ... просто заменить нашу self.view собственность по телефону [self setCanDisplayBannerAds:YES]; внутри viewDidLoad, поэтому он автоматически получает autoresizingMask установлен правильно.

+0

Спасибо. Я думаю, что есть опечатка примерно на полпути, абзац, начинающийся с «В вашем примере приложения, когда вы звоните ...», я думаю, что это должно быть '[self setCanDisplayBannerAds: YES];' вместо 'NO'? – Buddy

+0

Ах, вы правы; исправлено.Точка в том, что вызов его с помощью «YES» изменяет иерархию представлений, и поэтому вызов его вне 'viewDidLoad' не получает набор' autoresizingMask', как он должен быть. – cjwirth

+0

Одна вещь, которую я заметил, если я не делаю никаких вызовов 'setCanDisplayBannerAds:' в 'viewDidLoad', а позже включил рекламу, объявления не будут отображаться, и генерируется много связанных с делегатом исключений, поэтому быть более активным, чем просто авторезистировать. – Buddy

1

Честно говоря, у Иминь Ронга есть самое лучшее solution из всех доступных. Однако, если это стандартный тип учетной записи с премией v., Было бы лучше, если бы вы сохранили переменную локально и пользователь нажал кнопку «восстановить покупку». Таким образом, даже если пользователь находится в автономном режиме, вы можете показывать рекламу (если они были сохранены локально), и когда они выходят онлайн, вы можете получать прибыль от рекламодателей. Желаем удачи в вашем приложении!

+0

спасибо. Согласились, что было бы лучше иметь локальную переменную, но не хотелось бы слишком сильно модифицировать существующую логику. Это первый выпуск с использованием встроенных баннеров. Также согласованное решение Йиминь Ронга является самым чистым, но мне нравятся исследования, проведенные cjwirth. – Buddy

Смежные вопросы