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

IOS 8 MKAnnotationView rightCalloutAccessoryView смещен

Я все еще довольно новичок в iOS в целом и нашел проблему при тестировании нашего приложения для совместимости с iOS 8. В iOS 7 все работало нормально, но в iOS 8 rightCalloutAccessoryView смещается при определенных обстоятельствах.

Первый снимок экрана: Правильно выровненный Correctly aligned

Вторая скриншот: неправильное выравнивание Wrong alignment

Как вы можете видеть, проблема возникает, когда InfoWindow имеет длинный заголовок. Но это не относится к iOS 7, и я не мог найти ничего, что могло бы измениться?

Я попытался понять, почему и найти способ решить эту проблему, но ничего не смог найти. Является ли это решаемым самостоятельно или мы должны подать вопрос Apple?

Любая помощь/идеи будет высоко оценена, поскольку я как-то переусердствовал с этой проблемой.

Код, который добавляет MKAnnotationViews

- (MKAnnotationView *)viewForStation:(id<MKAnnotation>)annotation {
      static NSString *stationIdentifier = @"stao";
      MKAnnotationView *annotationView = [self.mapView dequeueReusableAnnotationViewWithIdentifier:stationIdentifier];
      if (annotationView == nil) {
          annotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation           reuseIdentifier:stationIdentifier];
          annotationView.image = [UIImage bundleImageNamed:PIN_IMAGE];
          annotationView.canShowCallout = YES;
          annotationView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
      }
      return annotationView;
}

Как вам может быть интересно, я (сейчас) также добавил этот вопрос в раздел iOS 8 Beta на apple.developer.com: https://devforums.apple.com/thread/242282?tstart=0

Если я получу ответ либо здесь, либо на apple.developer.com, я отражу его, чтобы мы могли найти его на обоих сайтах.

4b9b3361

Ответ 1

Я решил это, установив маску autoresizing для исправления вертикальной ошибки и frame.size.width для горизонтальной ошибки

UIButton* infoButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[infoButton setFrame:CGRectMake(0, 0, CGRectGetWidth(infoButton.frame)+10, CGRectGetHeight(infoButton.frame))];
[infoButton setAutoresizingMask:UIViewAutoresizingFlexibleBottomMargin|UIViewAutoresizingFlexibleTopMargin];
[annotationView setRightCalloutAccessoryView:infoButton];

Ответ 2

Ужасно, как черт, но мне удалось найти обходной путь к этой проблеме.

Установите высоту вид аксессуара равным высоте представления выноски. Я использовал жестко заданные значения:

  • для целей iOS 7: 45.0 px
  • для целей iOS 8: 54.0 px

(Вероятно, вы заметили, что высота объявления по умолчанию для аннотации больше в iOS 8, чем в iOS 7).

В вашем коде это будет:

- (MKAnnotationView *)viewForStation:(id<MKAnnotation>)annotation {
  static NSString *stationIdentifier = @"stao";
  MKAnnotationView *annotationView = [self.mapView dequeueReusableAnnotationViewWithIdentifier:stationIdentifier];
  if (annotationView == nil) {
      annotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation 
                                                    reuseIdentifier:stationIdentifier];
      annotationView.image = [UIImage bundleImageNamed:PIN_IMAGE];
      annotationView.canShowCallout = YES;

      UIButton *detailButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];

      // N.B. In production code, you would need a more generic way to adjust 
      // height values instead of hard-coding values based on NSFoundationVersionNumber...

      CGFloat height = (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_7_1) ? 55.f : 45.f;

      detailButton.frame = CGRectMake(0.f, 0.f, 32.f, height);
      annotationView.rightCalloutAccessoryView = detailButton;
  }
  return annotationView;
}

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

Ответ 3

Привет, у меня была такая же проблема, вот что я сделал для ее решения:

Кажется, что проблема с представлением Callout имеет проблемы с отображением текста заголовка MKAnnotation, когда он слишком длинный. Даже с вашего скриншота вы можете видеть, что проблема возникает только тогда, когда заголовок усечен и добавлен многоточие. Таким образом, стандартная MKAnnotation не закладывает взгляды должным образом, и это ошибка в iOS8.

В то же время вы можете создать свою собственную выноску, выполнив следующие шаги здесь.

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

if (locTitle.length > 15) 
{
    locTitle = [NSString stringWithFormat:@"%@...", [locTitle substringToIndex:14]];
}

Ответ 4

Одно любопытство, которое я заметил, это то, что моя первая выверка, которая будет отображаться, правильно выравнивает виды аксессуаров, но последующие выборы не будут. Я добавил вызов [view setNeedsLayout] до возвращения просмотренного аннотационного представления, и все снова стало правильно выравниваться.

Не тратя больше времени на это, я думаю, что повторная компоновка не запускается для представления, которое было отменено, поскольку иерархия представления не изменилась.

Я настоятельно рекомендую представить радар для этой проблемы. Нет необходимости применять обходные пути для такого стандартного варианта использования.

EDIT:

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

Ответ 5

Пока что Im скрывает rightCalloutAccessoryView с

pin.rightCalloutAccessoryView.frame = CGRectZero;

и нажмите "Просмотр аннотаций", все еще работающий, без кнопки справа. Протестировано на iOS7 и iOS8, не уверен в iOS6.

Ответ 6

Я получил свою работу, установив свой делегат с отображением карты до добавления аннотации и не должен ничего менять в del.

Переход от следующего:

    self.mapView = [[MKMapView alloc] init];
    NGAAnnotation *annotation = [[NGAAnnotation alloc] init];
    annotation.coordinate = coordinates;
    annotation.title = self.project.name;

    [self.mapView addAnnotation:annotation];
    self.mapView.delegate = self;

To:

    self.mapView = [[MKMapView alloc] init];
    NGAAnnotation *annotation = [[NGAAnnotation alloc] init];
    annotation.coordinate = coordinates;
    annotation.title = self.project.name;

    self.mapView.delegate = self;
    [self.mapView addAnnotation:annotation];

Исправлено это для меня. Я заметил, что метод делегата вызывается при добавлении аннотации, поэтому если делегат не задан перед добавлением аннотации, он не будет вызван.

Ответ 7

В Swift 3:

let infoButton = UIButton(type: .detailDisclosure)
annotationView.rightCalloutAccessoryView = infoButton