无法将Google Maps的GMSMapView放置在主视图的子视图中?

42

我正在苦恼这个问题! 我想把谷歌地图 GMSMapView 添加到一个 UIView 中,这个视图只是我的 ViewController 的主要 UIView 的一部分。

这应该很简单... 我使用故事板创建了一个所需大小的 UIView 并将其放入主 UIView 中。

接口文件中的代码片段:

@interface MapViewController : UIViewController <CLLocationManagerDelegate>

@property(nonatomic) IBOutlet GMSMapView *mapView;

将地图视图与主 UIView 中的此 UIView 相关联。

在实现中我做了什么:

@synthesize mapView = _mapView;

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.

    GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:-33.8683
                                                            longitude:151.2086
                                                                 zoom:10];
    _mapView = [GMSMapView mapWithFrame:_mapView.bounds camera:camera];
    _mapView.myLocationEnabled = YES;

}

这应该可以工作,不是吗?但我得到的是我的内部UIView为空。

如果我按照谷歌的入门指南实例化地图Google 地图集成文档,它可以工作,但它会将地图分配给主 UIView,这是一个不同的事情。

我甚至尝试在故事板中将mapView的类从UIView更改为GMSMapView,地图显示在内部视图中,但以奇怪的方式初始化,导致

  1. 系统抛出一个错误,说

"Failed to make complete frame buffer"

并且大大减慢了视图的加载速度(模拟器上需要2-3秒)

  1. viewDidLoad方法中进行的任何相机更改地图都没有响应。

有什么建议吗?

我在StackOverflow上阅读了一些帖子,但找不到有效的解决方案:(

11个回答

85

基于其他答案,以下是三种真正可行的方式。

  1. 在XIB中放置一个视图,将其类更改为GMSMapView。参见下面的*map1。或者...
  2. 全部编码。将地图作为主视图的子视图添加。参见下面的*map2。或者...
  3. 将地图作为已具有输出口的另一个子视图的子视图添加到XIB中。参见下面的*map3。

.h

@interface GPViewController : UIViewController
@property (strong, nonatomic) IBOutlet GMSMapView *map1;
@property (strong, nonatomic) IBOutlet UIView *plainViewOnXIBHoldsMap3;
@end

毫米

- (void)viewDidLoad{
    [super viewDidLoad];
    GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:-33.0
                                                        longitude:151.20
                                                             zoom:6];

    /* Option 1. view on XIB is class GSMMapView */
    self.map1.camera = camera;

    /* Option 2. add a map as a subview */
    GMSMapView *map2 = [GMSMapView mapWithFrame:CGRectMake(0, 0, 100, 100) camera:camera];
    [self.view addSubview:map2];

    /* Option 3. add a map to a subview already on the XIB */
    GMSMapView *map3 = [GMSMapView mapWithFrame:self.plainViewOnXIBHoldsMap3.bounds camera:camera];
    [self.plainViewOnXIBHoldsMap addSubview:map3];
}

选项1正常工作。最重要的是,不要手动设置地图框架,让它从XIB中获取,否则会覆盖您的委托方法。 - Scott D
选项1不起作用,我不知道问题在哪里,因为我是一个初学者。 - Muhammad Ali Hassan
1
为什么我之前没有找到这个解决方案,它就像魔法一样解决了我的问题。当然,我还做了一些其他的编码,但它给了我前进的方向... +1 - Abi
如果您按照Google的入门指南进行操作,请不要忘记从代码中删除空的loadView方法,否则这些选项都将无法正常工作。 - Dog
如果有人想以option 2中提到的自定义框架编程方式创建GMSMapView,请在loadView方法中执行此操作,而不是在viewDidload方法中,并且不要忘记添加[super loadView];,这样它就可以工作了! - Ketan Parmar

23

已经尝试并在Swift 2.0中成功地使用了cloudsurfin提供的三个选项。以下是他的回答的翻译,供那些在Swift 2.0中面临相同问题的人参考:

选项1 - 在XIB上放置一个视图,并将其类更改为XIB构建器中的GMSMapView。

选项2 - 编写全部代码。将地图添加为主视图的子视图。

选项3 - 将地图作为已有UIView子视图的GMSMapView子视图添加。

选项1准备工作的说明:

1)为你的视图设置一个类:

GMSMapView Mark

2)别忘了在代码中连接你的视图和outlet:

Connecting view and outlet

import UIKit
import GoogleMaps

class MapViewController: UIViewController {

    @IBOutlet weak var map1 : GMSMapView!

    @IBOutlet weak var map3 : UIView!

    override func viewDidLoad() {
        super.viewDidLoad()

        let camera = GMSCameraPosition.cameraWithLatitude(53.9,
        longitude: 27.5667, zoom: 6)

        // Option 1. view on XIB is class GSMMapView
        self.map1.camera = camera;

        // Option 2. add a map as a subview
        let map2 = GMSMapView.mapWithFrame(CGRectMake(0, 64, 320, 460), camera:camera)
        self.view.addSubview(map2)

        // Option 3. add a map to a subview of UIView class that is already on the XIB
        let map3 = GMSMapView.mapWithFrame(self.plainViewOnXIBHoldsMap3.bounds, camera:camera)
        self.plainViewOnXIBHoldsMap3.addSubview(map3)
    }
}
希望这个笔记能对某人有所帮助 :)

Hope this note helps someone :)


在Swift 3中,它对我不起作用。有任何更改吗? - Dhruv Khatri

19
我的建议:
  1. 将你的故事板中的UIView链接到头文件作为一个UIView实例变量,而不是GMSMapView
  2. 将mapWithFrame:camera:方法更改为设置为链接UIView的边界
  3. 在viewDidLoad:方法的末尾,将UIView实例变量设置为你的GMSMapView,或添加一个子视图。我也遇到了这个问题,通常调整一下这个可以解决。

.h

@interface MapViewController: UIViewController <CLLocationManagerDelegate>
{
    IBOutlet UIView *mapViewOnSreen;
}

.m

- (void)viewDidLoad
{
    [super viewDidLoad];

    // Do any additional setup after loading the view.
    GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:-33.8683
                                                                longitude:151.2086
                                                                     zoom:10];
    _mapView = [GMSMapView mapWithFrame:mapViewOnScreen.bounds camera:camera];
    _mapView.myLocationEnabled = YES;

    mapViewOnScreen = _mapView
    //OR [self.view addSubview:_mapView];
    //OR [mapViewOnScreen addSubview:_mapView];   <--This worked for me
}

*编辑:我在IB中创建了一个小的UIView,放在主视图内。我按照列出的步骤操作,当我设置[mapViewOnScreen addSubview:_mapView];时,我能够在小的UIView中看到地图。

在我的情况下,mapWithFrame:mapViewOnScreen.bounds被设置为CGRectZero。这是来自Google教程的内容。 - palme

11

你可以通过IB来做到这一点。

.h
@property (weak, nonatomic) IBOutlet GMSMapView *theMapView;

.m
GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:-33.868
                                                        longitude:151.2086
                                                             zoom:12];

//This next line is not needed if you have a GMSMapView outlet
//self.theMapView = [GMSMapView mapWithFrame:self.theMapView.frame camera:camera];
self.theMapView.camera=camera;
self.theMapView.mapType = kGMSTypeSatellite;
self.theMapView.delegate=self;

10

我只是因为忘记加入这一行代码而遇到了黑屏问题:

[super loadView];

8

对于Swift 3,如果你要子类化GMSMapView

  1. 在story board中将UIView添加到UIViewController

enter image description here

  1. 将class改为GMSMapView而不是UIView

enter image description here

  1. Create reference in UIViewController class

    @IBOutlet weak var mapView: GMSMapView!
    
  2. As you are subclassing you do not need use that GMSMapView.map(withFrame: CGRect.zero, camera: camera) mentioned in the docs. Just load map as follows

        let camera = GMSCameraPosition.camera(withLatitude: 51.50, longitude: -0.076, zoom: 10.0)
        mapView.camera = camera
    
  3. In order to add marker

    let marker = GMSMarker()
    marker.position = CLLocationCoordinate2D(latitude: 51.50, longitude: -0.076)
    marker.title = "London"
    marker.snippet = "UK"
    marker.map = mapView
    
  4. Together as a function

    override func viewDidLoad() {
    super.viewDidLoad()
    
      load()
    }
    
    func load() {
      //map
      let camera = GMSCameraPosition.camera(withLatitude: 51.50, longitude: -0.076, zoom: 10.0)
      mapView.camera = camera
    
      //marker
      let marker = GMSMarker()
      marker.position = CLLocationCoordinate2D(latitude: 51.50, longitude: -0.076)
      marker.title = "London"
      marker.snippet = "UK"
      marker.map = mapView
    }
    

1
省了几个小时呢,伙计。谢谢! :) - Ashish Sharma
1
非常感谢。我已经苦苦寻找了数小时才找到正确的位置。 - Mandeep Singh

7

我花了大约半个小时尝试让它工作,然后我发现我把它放在了错误的方法中。Google入门示例告诉您将其放在 - (void)loadView 中,但如果您这样做,您将得到一个黑屏或全屏地图。您需要将其放在 - (void)viewDidLoad 中。然后它就可以正常工作了。


哇!太棒了。 - Lenka Pitonakova

1
将UIVIEW类设置为GMSMapView,可以在identity inspector中完成。
然后从中创建IBOutlet:D,它就能工作了:P

0

按照2017年9月的谷歌教程学习Swift

我通过将代码放在viewDidLoad中进行了修复,如下所示

var mapView: GMSMapView!

override func viewDidLoad() {
    super.viewDidLoad()

    // Create a GMSCameraPosition to display the initial center of the map
    let camera = GMSCameraPosition.camera(withLatitude: 23.885942, longitude: 45.079162, zoom: 5.1)

    // Set the frame size , don't forget to replace "<CustomFrame>" with the required frame size
    mapView = GMSMapView.map(withFrame: "<CustomFrame>", camera: camera)

    // Add the map to any view here 
    view.addSubview(mapView)  //or customView.addSubview(mapView)
}

0
使用viewDidLayoutSubviews来设置mapView的大小。
我只需在viewDidLayoutSubviews()中调用函数,而不是在viewDidLoad()中调用,就可以简单地解决它。
@IBOutlet weak var mapView: GMSMapView!

override func viewDidLayoutSubviews() {
        self.setData()
}

func setData(){
    let latitude = YOUR_LAT
    let longitude = YOUR_LONG

    // Do any additional setup after loading the view.
    let camera = GMSCameraPosition.camera(withLatitude: latitude, longitude: longitude, zoom: 14.0)
    let mapView = GMSMapView.map(withFrame: self.mapView.bounds, camera: camera)
    self.mapView.addSubview(mapView)
    
    let marker = GMSMarker()
    marker.position = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
    marker.map = mapView
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接