Неэкранные iOS 6 MKMapViews и UIViewPrintFormatter - заставить их рендериться вовремя?
Я заинтересован в печати некоторых MKMapViews, которые не являются частью иерархии представлений и создаются только тогда, когда пользователь нажимает кнопку Print.
Кажется, что следующие вещи являются правдой:
- Внеэкранные MKMapViews не отображаются вообще.
- Печать MKMapView печатает это отрендеренный, однако это в настоящее время.
Похоже, что для печати видов на карте мне нужно поместить их в иерархию видов. К счастью, из экспериментов кажется, что я могу разместить на экране несколько видов карт друг перед другом, и они все равно будут визуализироваться.
Мой главный вопрос: откуда мне знать, что они отрисовали? Если я просто отключу команду печати сразу после помещения представлений карты в иерархию представлений, они будут печатать частично обработанные с отсутствующими битами, как показано ниже. Я хотел бы подождать, пока они не загрузятся, а затем запустить задание на печать. (Еще лучше, если они могут загружаться в фоновом режиме, пока лист печати находится на экране, а затем я просто предоставляю пользователю индикатор выполнения после того, как он нажимает кнопку Печать, пока карты не закончат загрузку.)
(Ниже: изображение, показывающее, что происходит, если вы печатаете частично загруженный вид карты.)
Мой второй вопрос: есть ли лучший способ напечатать несколько видов карты? Вводить все в иерархию представлений не очень хорошо - это ограничивает максимальный размер, который я могу использовать, и это означает, что у меня много неуклюжего кода для манипулирования подпредставлениями.
2 ответа
Вы должны установить делегат (MKMapViewDelegate) на ваших видах карты и реализовать mapViewDidFinishLoadingMap:, который будет вызываться, когда вид карты завершит загрузку необходимых плиток.
У меня была похожая проблема с рендерингом MKMapView к изображению, когда вид карты не обязательно виден на экране. Я нашел следующее решение работает для меня. Я надеюсь, что это помогает кому-то. По сути, это гарантирует, что на карте есть окно. в ios6.0 вам нужно дать ему окно для загрузки карты, а затем, когда он закончил загрузку, вы немного подождите, прежде чем выполнить рендеринг, чтобы дать плиткам возможность загрузить. в ios 5.0 вам не нужно ждать didfinishload, вы просто убедитесь, что на карте есть окно в функции рендеринга, и плитки будут видны.
{
if ([@"5.9.9" compare:[UIDevice currentDevice].systemVersion options:NSNumericSearch] == NSOrderedAscending) {
// actualVersion is lower than the requiredVersion
self.oldSuperview = nil;
if (self.map.window == nil) {
self.oldSuperview = self.map.superview;
[[[[UIApplication sharedApplication] delegate] window] insertSubview:self.map atIndex:0];
}
} else {
[self performSelector:@selector(renderMap) withObject:nil afterDelay:0.10];
}
}
-(void) renderMap {
//map will only render tiles if it has a window, so we need to add it to
//the main window if it does not have a window.
if ([@"5.9.9" compare:[UIDevice currentDevice].systemVersion options:NSNumericSearch] != NSOrderedAscending) {
if (self.map.window == nil) {
self.oldSuperview = self.map.superview;
[[[[UIApplication sharedApplication] delegate] window] addSubview:self.map];
}
}
// Generate the image centred
UIGraphicsBeginImageContextWithOptions(self.map.bounds.size, NO, 0.0);
[self.map.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *theImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// Save the image here
if ([@"5.9.9" compare:[UIDevice currentDevice].systemVersion options:NSNumericSearch] != NSOrderedAscending) {
if (self.oldSuperview) {
[self.map removeFromSuperview];
[self.oldSuperview addSubview:self.map];
self.oldSuperview = nil;
}
}
}
}
-(void) cleanMap {
if (self.map.superview == [[[UIApplication sharedApplication] delegate] window]) {
if (oldSuperview) {
[oldSuperview addSubview:self.map];
self.oldSuperview = nil;
}
}
}
-(void) mapViewDidFinishLoadingMap:(MKMapView *)mapView {
if ([@"5.9.9" compare:[UIDevice currentDevice].systemVersion options:NSNumericSearch] == NSOrderedAscending) {
if (oldSuperview) {
[self performSelector:@selector(renderMap) withObject:nil afterDelay:1.10];
[self performSelector:@selector(cleanMap) withObject:nil afterDelay:1.41];
} else {
[self renderMap];
}
} else {
[self renderMap];
}
}