通过URL下载GMSMarker图标

时间:2014-06-12 11:06:44

标签: ios google-maps-sdk-ios sdwebimage

GMSMarker中将图标设置为Google Maps SDK需要UIImage,但目前我的要求是从特定的URL

下载

问题

问题在于,某种程度上只会显示最后一项。这是关于如何创建标记的代码(在Swift中更新

func createMarkers() {
    mapView.clear()

    let mapCoordinates: [CLLocationCoordinate2D] = coordinates()
    let iconURLs: [URL] = imageURLs()

    var marker = GMSMarker()
    for i in 0..<mapCoordinates.count {
        let imageURL = iconURLs[i]

        marker = GMSMarker()
        marker.position = mapCoordinates[i]
        marker.map = mapView

        downloadImage(from: imageURL) { image in
            marker.icon = image
        }
    }
}

// It is a helper function calling `SDWebImage` which caches the `UIImage` based on its `URL` string
func downloadImage(from url: URL, completion: @escaping (UIImage) -> Void)

从上面提供的代码中,我在第一次加载数据时遇到问题,因为引脚显示在地图上但没有图像。如果我在一段时间后再次呼叫createMarkers(),则图标会正确加载。

我不知道为什么会这样,有什么建议或暗示可以解决这个问题吗?

4 个答案:

答案 0 :(得分:3)

只使用SDWebimage,而.iconView不是.icon

let imageView = UIImageView(image: pinImage)
imageView.sd_setImage(with: URL(string: "https://pbs.twimg.com/profile_images/469017630796296193/R-bEN4UP.png"), placeholderImage: pinImage)
marker.iconView = imageView

答案 1 :(得分:0)

也许试试这个......在完成块内移动几行,使用标记...

[imageView setImageWithURL:[NSURL URLWithString:placeObject.photoPath] completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType)
{
    image = [self image:image ByScalingAndCroppingForSize:CGSizeMake(44, 44)];
    [marker setIcon:image];
    [pins addObject:marker]; //assuming you use pins later
    marker.map = mapView_;
}];

因为您已经拥有了正在处理的标记。当然,你需要注意你的错误处理程序。

答案 2 :(得分:0)

同样的问题。这是我的解决方案:添加2次

这是我的代码:D

- (void)addMarkers {
    //for() {
         NSString *avatarLink = [tempLocation.userInfo objectForKey:@"avatar"];
        GMSMarker *marker = [self addMarker:tempLocation andCustomView:customView];

        [customView.imageGame setImageWithURL:[NSURL URLWithString:avatarLink] placeholderImage:[UIImage imageNamed:LOADING_ICON] options:SDWebImageCacheMemoryOnly completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType) {
            marker.icon = [self captureView:customView];
        }];
    //}
}
- (GMSMarker*)addMarker: (FriendLocation*)tempLocation andCustomView: (FriendCustomInforwindow*)customView {
    GMSMarker *marker = [[GMSMarker alloc] init];
    marker.position = CLLocationCoordinate2DMake(tempLocation.coordinate.latitude, tempLocation.coordinate.longitude);
    marker.animated=YES;
    marker.infoWindowAnchor = CGPointMake(0.5, 2.37);
    marker.icon = [self captureView:customView];
    marker.map = mapView;
    [markersArray addObject:marker];
    return marker;
}

答案 3 :(得分:0)

好的,那时候,我对并发性了解不多,看到所有答案并不能真正解决我的初衷。

问题

由于从URLdownloadImage(from url: URL, completion: @escaping (UIImage) -> Void))下载图像是一项后台操作,因此在下载图像之前,marker已经超出了范围再次在循环上初始化。

这样,就无法知道哪个图像被绑定到了哪个标记。

关于为什么它在重新加载时起作用?,重新加载时的SDWebImage已经下载并缓存了图像,因此下次没有延迟时,它就必然会直接marker

解决方案

将可变变量标记作为不可变值移动到循环内部。

func createMarkers() {
    let mapCoordinates: [CLLocationCoordinate2D] = coordinates()
    let iconURLs: [URL] = imageURLs()

    for i in 0..<mapCoordinates.count {
        let imageURL = iconURLs[i]

        let marker = GMSMarker()
        marker.position = mapCoordinates[i]
        marker.map = mapView
        applyImage(from: imageURL, to: marker)
    }
}

现在您看到我引入了一个名为applyImage(from:, to:)的辅助程序,该辅助程序基本上没有什么特别的功能,只是从URL下载图像并将其绑定到类型GMSMarker的参数上。

func applyImage(from url: URL, to marker: GMSMarker) {
    DispatchQueue.global(qos: .background).async {
        guard let data = try? Data(contentsOf: url),
            let image = UIImage(data: data)?.cropped()
            else { return }

        DispatchQueue.main.async {
            marker.icon = image
        }
    }
}

另外还有一个扩展名,用于将图像裁剪为 44pt X 44pt ,这是不对的,但这只是为了预览已加载的内容。

extension UIImage {

    func cropped() -> UIImage? {
        let cropRect = CGRect(x: 0, y: 0, width: 44 * scale, height: 44 * scale)

        guard let croppedCGImage = cgImage?.cropping(to: cropRect) else { return nil }

        return UIImage(cgImage: croppedCGImage, scale: scale, orientation: imageOrientation)
    }
}

注意:可以在我写的Gist中找到整个ViewController代码!

输出

Demo