UIButton无法正确加载MKAnnotationView [英] UIButton Not Loading Properly For MKAnnotationView

查看:119
本文介绍了UIButton无法正确加载MKAnnotationView的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在创建带有详细信息披露按钮的MKAnnotationView.

在mapView中:viewForAnnotation:我只是创建一个占位符按钮.

//  the right accessory view needs to be a disclosure button ready to bring up the photo
aView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];

在mapView中:didSelectAnnotationView:我实际上创建了一个要使用的按钮(带有相关标签)

//  create a button for the callout
UIButton *disclosure                = [self.delegate mapController:self buttonForAnnotation:aView.annotation];

NSLog(@"DisclosureButton: %@", disclosure);

//  set the button's target for when it is tapped upon
[disclosure addTarget:self.delegate action:@selector(presentAnnotationPhoto:) forControlEvents:UIControlEventTouchUpInside];

//  make the button the right callout accessory view
aView.rightCalloutAccessoryView = disclosure;

在日志中,该按钮似乎已完全实例化并设置了正确的标记.

这是按钮创建者:

/**
 *  returns an button for a specific annotation
 *
 *  @param  sender              the map controller which is sending this method to us (its' delegate)
 *  @param  annotation          the annotation we need to create a button for
 */
- (UIButton *)mapController:(MapController *)   sender
        buttonForAnnotation:(id <MKAnnotation>) annotation
{
    //  get the annotation as a flickr photo annotation
    FlickrPhotoAnnotation *fpa  = (FlickrPhotoAnnotation *)annotation;

    //  create a disclosure button used for showing photo in callout
    UIButton *disclosureButton      = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];

    //  associate the correct photo with the button
    disclosureButton.tag            = [self.photoList indexOfObject:fpa.photo];

    return disclosureButton;
}

选择注释时出现问题.在选择注释并点击详细信息披露按钮几秒钟后,什么都没有发生.但是,在轻按几次并返回到注释并测试按钮后,它最终将按预期工作.

奇怪的延迟是怎么回事?有时,当该按钮将起作用时,它似乎就像将alpha设置为0.0一样,直到您点击它并出现为止.

严重的是我遇到的更奇怪的问题之一.

解决方案

在调用didSelectAnnotationView委托方法之前,地图视图已经基于注释视图的属性(在更改之前)准备了标注视图. >

因此,您在第一次点击时看到的标注没有更改应用程序在didSelectAnnotationView中所做的更改.在随后的拍子中,标注可以基于上一拍子中设置的值(这实际上取决于在viewForAnnotation中如何处理注释视图重用).

看来,代码在didSelectAnnotationViewbuttonForAnnotation中唯一要做的就是设置按钮的动作和标签.

我假设您使用的是标记"方法,因为presentAnnotationPhoto:方法需要引用所选注释的属性.

您无需在操作方法中使用标签来获取选定的注释.相反,有几个更好的选择:

  • 您的自定义操作方法可以从地图视图的selectedAnnotations属性中获取选定的注释.请参阅此问题有关如何执行此操作的示例.
  • 使用地图视图自己的委托方法calloutAccessoryControlTapped而不是自定义操作方法.委托方法将对引用的引用传递给注释视图,该引用包含指向其注释的属性(即view.annotation),因此无需猜测,搜索或询问选择了哪个注释.我建议使用此选项.

在第一个选项中,执行viewForAnnotation中的addTarget,而不必费心设置tag.您也不需要buttonForAnnotation方法.然后在按钮操作方法中,从mapView.selectedAnnotations获取选定的注释.

当前,您的操作方法在self.delegate上,因此从该其他控制器访问地图视图时可能会遇到一些麻烦.您可以做的是 在地图控制器中创建本地按钮操作方法 ,该方法将获取选定的注释,然后然后调用presentAnnotationPhoto:操作方法在self.delegate上(除非现在可以编写该方法以接受注释参数而不是按钮点击处理程序).

第二个选项类似,除了您不需要执行任何addTarget且在calloutAccessoryControlTapped方法中,调用self.delegate上的presentAnnotationPhoto:.

对于这两个选项,我建议修改presentAnnotationPhoto:方法以接受注释对象本身(FlickrPhotoAnnotation *)而不是当前的UIButton *,并且在地图控制器中,对方法 local 到地图控制器(或使用calloutAccessoryControlTapped),然后从该方法手动调用presentAnnotationPhoto:并将注释传递给它.

I am creating an MKAnnotationView with a detail disclosure button.

In mapView: viewForAnnotation: I just create an placeholder button.

//  the right accessory view needs to be a disclosure button ready to bring up the photo
aView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];

In mapView: didSelectAnnotationView: I actually create a button to be used (with the relevant tag)

//  create a button for the callout
UIButton *disclosure                = [self.delegate mapController:self buttonForAnnotation:aView.annotation];

NSLog(@"DisclosureButton: %@", disclosure);

//  set the button's target for when it is tapped upon
[disclosure addTarget:self.delegate action:@selector(presentAnnotationPhoto:) forControlEvents:UIControlEventTouchUpInside];

//  make the button the right callout accessory view
aView.rightCalloutAccessoryView = disclosure;

In the log, the button appears to be fully instantiated as well as set with the correct tag.

This is the button creator:

/**
 *  returns an button for a specific annotation
 *
 *  @param  sender              the map controller which is sending this method to us (its' delegate)
 *  @param  annotation          the annotation we need to create a button for
 */
- (UIButton *)mapController:(MapController *)   sender
        buttonForAnnotation:(id <MKAnnotation>) annotation
{
    //  get the annotation as a flickr photo annotation
    FlickrPhotoAnnotation *fpa  = (FlickrPhotoAnnotation *)annotation;

    //  create a disclosure button used for showing photo in callout
    UIButton *disclosureButton      = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];

    //  associate the correct photo with the button
    disclosureButton.tag            = [self.photoList indexOfObject:fpa.photo];

    return disclosureButton;
}

The problem comes when I select the annotation. For a few seconds when the annotation is selected and the detail disclosure button is tapped, nothing happens. However, after tapping away and back onto the annotation a few times and testing the button, it eventually works as expected.

What is going on with the strange delay? Sometimes when the button is going to work, it just appears as if the alpha is set to 0.0 until you tap on it and it appears.

Seriously one of the more odd problems I've encountered.

解决方案

Before the didSelectAnnotationView delegate method is called, the map view has already prepared the callout view based on the annotation view's properties (before your changes).

So the callout you see the on the first tap is without the changes the app makes in didSelectAnnotationView. On the following taps, the callout could be based on the values set from the previous tap (this actually depends on how annotation view re-use is handled in viewForAnnotation).

It looks like the only things the code is doing in didSelectAnnotationView and buttonForAnnotation is setting the button action and tag.

I assume you're using the "tag" approach because the presentAnnotationPhoto: method needs to reference the selected annotation's properties.

You don't need to use a tag to get the selected annotation in your action method. Instead, there are a couple of better options:

  • Your custom action method can get the selected annotation from the map view's selectedAnnotations property. See this question for an example of how to do this.
  • Use the map view's own delegate method calloutAccessoryControlTapped instead of a custom action method. The delegate method passes a reference to the annotation view which contains a property pointing to its annotation (ie. view.annotation) so there's no guessing, searching, or question as to what annotation was selected. I recommend this option.

In the first option, do the addTarget in viewForAnnotation and don't bother setting the tag. You also don't need the buttonForAnnotation method. Then in the button action method, get the selected annotation from mapView.selectedAnnotations.

Currently, your action method is on self.delegate so you might have some trouble accessing the map view from that other controller. What you can do is create a local button action method in the map controller which gets the selected annotation and then calls the presentAnnotationPhoto: action method on self.delegate (except now that method can be written to accept an annotation parameter instead of being a button tap handler).

The second option is similar except you don't need to do any addTarget and in the calloutAccessoryControlTapped method, call presentAnnotationPhoto: on self.delegate.

For both options, I suggest modifying the presentAnnotationPhoto: method to accept the annotation object itself (FlickrPhotoAnnotation *) instead of the current UIButton * and in the map controller, do an addTarget on a method local to the map controller (or use calloutAccessoryControlTapped) and from that method, manually call presentAnnotationPhoto: and pass it the annotation.

这篇关于UIButton无法正确加载MKAnnotationView的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆