iOS 8 MKAnnotationView rightCalloutAccessoryView misaligned
Asked Answered
R

7

39

I'm still pretty new to the iOS stuff in general and found a problem while testing our App for iOS 8 compatibility. In iOS 7 everything worked fine but on iOS 8 the rightCalloutAccessoryView is misaligned under certain circumstances.

First Screenshot: Correctly aligned Correctly aligned

Second Screenshot: Wrong alignment Wrong alignment

As you can see, the problem takes place when the InfoWindow has a long title. But this was not the case on iOS 7 and I couldn't find anything mentioning this has changed?

I tried to understand why and find a way to resolve this, but couldn't find anything yet. Is this solvable on our own or do we have to file an issue for Apple?

Any help/ideas would be highly appreciated as I'm somehow overchallenged with this problem.

Code which adds the 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;
}

As you may be interested, I (just now) also added this question to the iOS 8 Beta section on apple.developer.com: https://devforums.apple.com/thread/242282?tstart=0

If I get an answer either here or on apple.developer.com I will reflect it so we can find it on both sites

Randellrandene answered 25/8, 2014 at 11:11 Comment(5)
Nobody has an idea yet?Randellrandene
Myself as well, i am unable to fix this :(Girt
Same problem here...Alms
They closed my issue as a duplicate without any comment and you can't even view the pending issue. FU Apple!Randellrandene
Are there any updates about this?Sommers
P
18

I solved this by setting the autoresizingmask to fix the vertical bug and frame.size.width for the horizontal bug

UIButton* infoButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[infoButton setFrame:CGRectMake(0, 0, CGRectGetWidth(infoButton.frame)+10, CGRectGetHeight(infoButton.frame))];
[infoButton setAutoresizingMask:UIViewAutoresizingFlexibleBottomMargin|UIViewAutoresizingFlexibleTopMargin];
[annotationView setRightCalloutAccessoryView:infoButton];
Prorogue answered 17/12, 2014 at 15:2 Comment(0)
A
10

Ugly as heck, but I did manage to find a workaround to this issue.

Set the accessory view height to a value equal to the callout view height. I used hard-coded values:

  • for iOS 7 targets: 45.0 px
  • for iOS 8 targets: 54.0 px

(You probably noticed the height of the default annotation callout view is bigger in iOS 8 than in iOS 7).

In your code, that would be:

- (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;
}

Also, from what I've seen so far, if you specify both left and right accessory views, you would have to set both their heights to the same value to get proper alignment. Hopefully this issue will be fixed in subsequent iOS releases to avoid writing this kind of code...

Archeozoic answered 26/9, 2014 at 19:43 Comment(2)
At least some solution. But I'm not sure if we should wait for a fix by Apple. Seems they get worse and worse with their software :(Randellrandene
I found I had to adjust the width too, as otherwise the button is hard up against the right edge of the callout. I also only adjusted the frame if the version was 8 or above; if the version was less than 8 I left the existing frame.Hive
L
3

Hi I was having the exact same problem here is what I did to solve it:

It seems to be an issue with the Callout view having issues displaying the MKAnnotation title text when it is too long. Even from your screenshot you can see the issue only happens when the title has been truncated and the ellipsis is added. So the standard MKAnnotation is not laying out the views properly and this is a bug in iOS8.

In the mean time you could create your own custom callout by following the steps here.

I thought this was too much work for what I needed so I just trimmed the title string and added the ellipsis to preventing it from trying to do itself. (Not ideal but is a quick solution, and the text would be truncated anyway)

if (locTitle.length > 15) 
{
    locTitle = [NSString stringWithFormat:@"%@...", [locTitle substringToIndex:14]];
}
Lanctot answered 21/10, 2014 at 16:40 Comment(0)
R
0

One curiosity I noticed was that my first callout to be displayed would properly align the accessory views, but subsequent selections would not. I added a call to [view setNeedsLayout] prior to returning the dequeued annotation view, and everything began aligning properly again.

Without spending more time on this, my best guess is that a re-layout is not being triggered for a view that has been dequeued because the view heirarchy has not changed.

I highly recommend submitting a radar for this issue though. It should not be necessary to implement workarounds for such a standard use case.

EDIT:

While this still appears to be better for many cases, I'm still encountering this issue with annotations whose title is long enough to be truncated.

Rifkin answered 7/9, 2014 at 18:54 Comment(0)
T
0

For now, I’m hiding rightCalloutAccessoryView with

pin.rightCalloutAccessoryView.frame = CGRectZero;

and click on Annotation View still working, just no button on the right side. Tested on iOS7 and iOS8, not sure about iOS6.

Tubercle answered 17/9, 2014 at 10:0 Comment(0)
C
0

I got mine to work by setting my map view's delegate prior to adding the annotation and did not have to change anything in the del.

Going from the following:

    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];

Fixed it for me. I noticed that the delegate method gets called when the annotation is added so if the delegate is not set prior to you adding the annotation it will not get called.

Crossbar answered 28/9, 2014 at 6:46 Comment(2)
This didn't work for me. I already had the delegate set through the storyboard, but even explicitly setting it before adding annotations didn't solve the issue.Hive
Does you delegate have the view for annotation method defined?Crossbar
S
0

In Swift 3:

let infoButton = UIButton(type: .detailDisclosure)
annotationView.rightCalloutAccessoryView = infoButton
Schoenfelder answered 9/12, 2016 at 8:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.