在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()
,则图标会正确加载。
我不知道为什么会这样,有什么建议或暗示可以解决这个问题吗?
答案 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)
好的,那时候,我对并发性了解不多,看到所有答案并不能真正解决我的初衷。
由于从URL
(downloadImage(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代码!