Ứng dụng Bản đồ mở theo lập trình trong iOS 6


159

Trước iOS 6, việc mở một URL như thế này sẽ mở ứng dụng Bản đồ (Google):

NSURL *url = [NSURL URLWithString:@"http://maps.google.com/?q=New+York"];
[[UIApplication sharedApplication] openURL:url];

Giờ đây với việc triển khai Apple Maps mới, việc này chỉ mở Mobile Safari cho Google Maps. Làm cách nào tôi có thể thực hiện hành vi tương tự với iOS 6? Làm cách nào để tôi lập trình mở ứng dụng Bản đồ và để nó trỏ đến một vị trí / địa chỉ / tìm kiếm cụ thể?

Câu trả lời:


281

Đây là cách chính thức của Apple:

// Check for iOS 6
Class mapItemClass = [MKMapItem class];
if (mapItemClass && [mapItemClass respondsToSelector:@selector(openMapsWithItems:launchOptions:)]) 
{
    // Create an MKMapItem to pass to the Maps app
    CLLocationCoordinate2D coordinate = 
                CLLocationCoordinate2DMake(16.775, -3.009);
    MKPlacemark *placemark = [[MKPlacemark alloc] initWithCoordinate:coordinate 
                                            addressDictionary:nil];
    MKMapItem *mapItem = [[MKMapItem alloc] initWithPlacemark:placemark];
    [mapItem setName:@"My Place"];
    // Pass the map item to the Maps app
    [mapItem openInMapsWithLaunchOptions:nil];
}

Nếu bạn muốn nhận hướng dẫn lái xe hoặc đi bộ đến vị trí, bạn có thể bao gồm a mapItemForCurrentLocationvới MKMapItemmảng trong +openMapsWithItems:launchOptions:và đặt các tùy chọn khởi chạy một cách thích hợp.

// Check for iOS 6
Class mapItemClass = [MKMapItem class];
if (mapItemClass && [mapItemClass respondsToSelector:@selector(openMapsWithItems:launchOptions:)]) 
{
    // Create an MKMapItem to pass to the Maps app
    CLLocationCoordinate2D coordinate = 
                CLLocationCoordinate2DMake(16.775, -3.009);
    MKPlacemark *placemark = [[MKPlacemark alloc] initWithCoordinate:coordinate 
                                            addressDictionary:nil];
    MKMapItem *mapItem = [[MKMapItem alloc] initWithPlacemark:placemark];
    [mapItem setName:@"My Place"];

    // Set the directions mode to "Walking"
    // Can use MKLaunchOptionsDirectionsModeDriving instead
    NSDictionary *launchOptions = @{MKLaunchOptionsDirectionsModeKey : MKLaunchOptionsDirectionsModeWalking};
    // Get the "Current User Location" MKMapItem
    MKMapItem *currentLocationMapItem = [MKMapItem mapItemForCurrentLocation];
    // Pass the current location and destination map items to the Maps app
    // Set the direction mode in the launchOptions dictionary
    [MKMapItem openMapsWithItems:@[currentLocationMapItem, mapItem] 
                    launchOptions:launchOptions];
}

Sau đó, bạn có thể giữ nguyên iOS 5 và mã thấp hơn trong một elsetuyên bố if. Lưu ý rằng nếu bạn đảo ngược thứ tự của các mục trong openMapsWithItems:mảng, bạn sẽ nhận được chỉ đường từ tọa độ đến vị trí hiện tại của bạn. Bạn có thể có thể sử dụng nó để nhận chỉ đường giữa bất kỳ hai vị trí nào bằng cách chuyển một mục được xây dựng MKMapItemthay vì mục bản đồ vị trí hiện tại. Tôi đã không thử điều đó.

Cuối cùng, nếu bạn có một địa chỉ (dưới dạng chuỗi) mà bạn muốn chỉ đường đến, hãy sử dụng trình mã hóa địa lý để tạo một MKPlacemark, bằng cách này CLPlacemark.

// Check for iOS 6
Class mapItemClass = [MKMapItem class];
if (mapItemClass && [mapItemClass respondsToSelector:@selector(openMapsWithItems:launchOptions:)])
{
    CLGeocoder *geocoder = [[CLGeocoder alloc] init];
    [geocoder geocodeAddressString:@"Piccadilly Circus, London, UK" 
        completionHandler:^(NSArray *placemarks, NSError *error) {

        // Convert the CLPlacemark to an MKPlacemark
        // Note: There's no error checking for a failed geocode
        CLPlacemark *geocodedPlacemark = [placemarks objectAtIndex:0];
        MKPlacemark *placemark = [[MKPlacemark alloc]
                                  initWithCoordinate:geocodedPlacemark.location.coordinate
                                  addressDictionary:geocodedPlacemark.addressDictionary];

        // Create a map item for the geocoded address to pass to Maps app
        MKMapItem *mapItem = [[MKMapItem alloc] initWithPlacemark:placemark];
        [mapItem setName:geocodedPlacemark.name];

        // Set the directions mode to "Driving"
        // Can use MKLaunchOptionsDirectionsModeWalking instead
        NSDictionary *launchOptions = @{MKLaunchOptionsDirectionsModeKey : MKLaunchOptionsDirectionsModeDriving};

        // Get the "Current User Location" MKMapItem
        MKMapItem *currentLocationMapItem = [MKMapItem mapItemForCurrentLocation];

        // Pass the current location and destination map items to the Maps app
        // Set the direction mode in the launchOptions dictionary
        [MKMapItem openMapsWithItems:@[currentLocationMapItem, mapItem] launchOptions:launchOptions];

    }];
}

Mã này hoạt động rất tốt cho iOS 6. Đáng nói đến mặc dù nếu tuyến đường chúng tôi muốn là từ vị trí người dùng hiện tại đến đích, thì không cần phải đi vào currentLocationMapItem.
Philip007

1
Việc bạn sử dụng tọa độ Tombouctou chỉ khiến câu trả lời trở nên tuyệt vời hơn :)
sachadso

+1 để đề cập rằng đó chỉ là iOS 6 và bạn cần một dự phòng
Henrik Erlandsson 15/03/13

2
Làm cách nào tôi có thể điều hướng đến ứng dụng hiện tại của mình từ các ứng dụng bản đồ?
Apple

1
Điều gì đã từng chọn vị trí tôi chọn khi mở ứng dụng bản đồ táo, nó hiển thị cảnh báo "không thể tìm thấy hướng giữa các vị trí ios 6" này và sau đó nó không làm gì cả? Bất kỳ trợ giúp
NaXir

80

Tìm thấy câu trả lời cho câu hỏi của riêng tôi. Apple tài liệu định dạng URL bản đồ của mình ở đây . Có vẻ như bạn về cơ bản có thể thay thế maps.google.combằng maps.apple.com.

Cập nhật: Hóa ra điều tương tự cũng đúng trong MobileSafari trên iOS 6; nhấn vào một liên kết để http://maps.apple.com/?q=...mở ứng dụng Bản đồ với tìm kiếm đó, giống như cách http://maps.google.com/?q=...đã làm trên các phiên bản trước. Điều này hoạt động và được ghi lại trong trang được liên kết ở trên.

CẬP NHẬT: Điều này trả lời câu hỏi của tôi liên quan đến định dạng URL. Nhưng câu trả lời của nevan king ở đây (xem bên dưới) là một bản tóm tắt tuyệt vời về API Maps thực tế.


1
Hấp dẫn. Nếu bạn mở trình duyệt tới maps.apple.com, nó sẽ chuyển hướng đến maps.google.com. Tôi tự hỏi điều này sẽ kéo dài bao lâu?
pir800

@ pir800 - Tôi thực sự chỉ tự hỏi về những gì sẽ xảy ra nếu bạn nhấn vào một liên kết đến maps.apple.com trong Safari trên iOS 6. Tôi đã thử nó và nó đi tới Maps giống như trên các phiên bản iOS trước đây khi bạn gõ một liên kết đến maps.google.com. Tôi nghĩ rằng thật tốt khi họ chuyển hướng đến bản đồ Google để các tác giả trang web có thể chỉ liên kết bản đồ đến maps.apple.com và để nó hoạt động trên iOS trong Bản đồ nhưng hoạt động bình thường trên tất cả các khách hàng khác. Nhưng tôi muốn xác minh rằng bằng cách nào đó trước khi thay đổi tất cả các liên kết bản đồ của tôi để trỏ đến maps.apple.com!
Tom Hamming

@ pir800 - đối với tôi, việc mở maps.apple.com trong trình duyệt sẽ đưa tôi đến apple.com/ios/maps . Có lẽ bình luận trước đây của tôi là mơ tưởng.
Tom Hamming

Tôi có nghĩa là nếu bạn cố gắng truy vấn một địa chỉ hoặc phối hợp. Hãy thử maps.apple.com/?q=los angeles, ca. Bạn có thể mở nó trên máy tính để bàn của mình và nó sẽ chuyển tiếp tới maps.google.com
pir800

Có cách nào để thêm chế độ chuyển tuyến vào truy vấn đó không? (đi bộ / lái xe). không thể tìm thấy bất kỳ tài liệu tham khảo nào trên web.
Lirik

41

Cách tốt nhất để làm điều đó là gọi phương thức iOS 6 mới trên MKMapItem openInMapsWithLaunchOptions:launchOptions

Thí dụ:

CLLocationCoordinate2D endingCoord = CLLocationCoordinate2DMake(40.446947, -102.047607);
MKPlacemark *endLocation = [[MKPlacemark alloc] initWithCoordinate:endingCoord addressDictionary:nil];
MKMapItem *endingItem = [[MKMapItem alloc] initWithPlacemark:endLocation];

NSMutableDictionary *launchOptions = [[NSMutableDictionary alloc] init];
[launchOptions setObject:MKLaunchOptionsDirectionsModeDriving forKey:MKLaunchOptionsDirectionsModeKey];

[endingItem openInMapsWithLaunchOptions:launchOptions];

Điều này sẽ bắt đầu điều hướng cho lái xe từ vị trí hiện tại.


1
OK, vậy cách dễ nhất để có được một ví dụ MKMapItemkhi tất cả những gì tôi có là một địa chỉ là gì? API này có vẻ hơi phức tạp đối với trường hợp sử dụng đơn giản đó.
Tom Hamming

MKPlacemark * endLocation = [[MKPlacemark alloc] initWithCoordine: nil addressDixi: yourAdressDictHere]; bạn có thể trao một địa chỉ Dictonary trong
marius LAN

7

Tôi thấy bạn đã tìm thấy "lược đồ" url maps.apple.com. Đó là một lựa chọn tốt vì nó sẽ tự động chuyển hướng các thiết bị cũ hơn sang maps.google.com. Nhưng đối với iOS 6, có một lớp mới mà bạn có thể muốn tận dụng: MKMapItem .

Hai phương pháp mà bạn quan tâm:

  1. -openInMapsWithLaunchOptions: - gọi nó trên một phiên bản MKMapItem để mở nó trong Maps.app
  2. + openMapsWithItems: launchOptions: - gọi nó trên lớp MKMapItem để mở một mảng các trường hợp MKMapItem.

Điều đó có vẻ hữu ích. Nhưng nó cũng có vẻ phức tạp hơn một chút để sử dụng; bạn phải init MKMapItemcó một MKPlacemarkcái mà bạn có được bằng cách cung cấp một cặp vĩ độ / kinh độ và một từ điển địa chỉ. Có vẻ đơn giản hơn để chỉ mở http://maps.apple.com/?q=1+infinite+loop+cupertino+ca. Có lợi thế MKMapItemnào khi sử dụng khi tất cả những gì bạn muốn làm là hiển thị một địa chỉ trong Bản đồ?
Tom Hamming

Bạn không cần phải khởi tạo MKMapItemnếu bạn chưa có tài liệu tham khảo đến tài liệu mà bạn muốn sử dụng. Chỉ cần sử dụng các phương pháp lớp học, +openMapsWithItems:launchOptions:trên MKMapItemđể làm điều tương tự.
Mark Adams

@MarkAdams phương thức lớp đó có một loạt các thể hiện của lớp, vì vậy, vâng, anh ta cần phải có ít nhất một khởi tạo.
Filip Radelic

Vì vậy, trong tình huống khi tôi có tọa độ GPS để mở, nhưng không có địa chỉ, tôi sử dụng MKMapItemAPI và nó làm rơi một điểm trên bản đồ có nhãn "Vị trí không xác định". Có cách nào để làm cho nó hiển thị tên cho vị trí không? Tôi không thấy bất kỳ khóa nào cho điều này trong các tùy chọn cho từ điển địa chỉ ...
Tom Hamming

5
@ Mr.Jefferson Đặt thuộc tính tên của MKMapItem
matt

5

Đây là một lớp sử dụng giải pháp của nevan king hoàn thành trong Swift:

class func openMapWithCoordinates(theLon:String, theLat:String){

            var coordinate = CLLocationCoordinate2DMake(CLLocationDegrees(theLon), CLLocationDegrees(theLat))

            var placemark:MKPlacemark = MKPlacemark(coordinate: coordinate, addressDictionary:nil)

            var mapItem:MKMapItem = MKMapItem(placemark: placemark)

            mapItem.name = "Target location"

            let launchOptions:NSDictionary = NSDictionary(object: MKLaunchOptionsDirectionsModeDriving, forKey: MKLaunchOptionsDirectionsModeKey)

            var currentLocationMapItem:MKMapItem = MKMapItem.mapItemForCurrentLocation()

            MKMapItem.openMapsWithItems([currentLocationMapItem, mapItem], launchOptions: launchOptions)
}

4

Tôi thấy khó chịu khi sử dụng http://maps.apple.com?q= ... thiết lập liên kết sẽ mở trình duyệt safari trước tiên tại các thiết bị cũ.

Vì vậy, đối với thiết bị iOS 5 mở ứng dụng của bạn với tham chiếu đến maps.apple.com, các bước sẽ như sau:

  1. bạn nhấp vào một cái gì đó trong ứng dụng và nó đề cập đến url maps.apple.com
  2. safari mở ra liên kết
  3. máy chủ maps.apple.com chuyển hướng đến url maps.google.com
  4. url maps.google.com được diễn giải và mở ứng dụng google Maps.

Tôi nghĩ rằng các bước 2 và 3 (rất rõ ràng và khó hiểu) gây khó chịu cho người dùng. Do đó, tôi kiểm tra phiên bản os và chạy maps.google.com hoặc maps.apple.com trên thiết bị (đối với phiên bản hệ điều hành ios 5 hoặc ios 6).


Đó là những gì tôi đang làm quá. Có vẻ như cách tiếp cận tốt nhất.
Tom Hamming

3

Nghiên cứu của tôi về vấn đề này dẫn tôi đến những kết luận sau:

  1. Nếu bạn sử dụng maps.google.com thì nó sẽ mở bản đồ trong safari cho mọi ios.
  2. Nếu bạn sử dụng maps.apple.com thì nó sẽ mở bản đồ trong ứng dụng bản đồ của ios 6 và cũng hoạt động tuyệt vời với ios 5 và trong ios 5, nó sẽ mở bản đồ như bình thường trong safari.

3

Nếu bạn muốn mở Google Maps thay thế (hoặc cung cấp dưới dạng tùy chọn phụ), bạn có thể sử dụng các lược đồ comgooglemaps://comgooglemaps-x-callback://URL được ghi lại ở đây .


3

Trước khi khởi chạy url, hãy xóa bất kỳ ký tự đặc biệt nào khỏi url và thay thế khoảng trắng bằng +. Điều này sẽ giúp bạn tiết kiệm một số vấn đề đau đầu:

    NSString *mapURLStr = [NSString stringWithFormat: @"http://maps.apple.com/?q=%@",@"Limmattalstrasse 170, 8049 Zürich"];

    mapURLStr = [mapURLStr stringByReplacingOccurrencesOfString:@" " withString:@"+"];
    NSURL *url = [NSURL URLWithString:[mapURLStr stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]];
    if ([[UIApplication sharedApplication] canOpenURL:url]){
            [[UIApplication sharedApplication] openURL:url];
        }

2
NSString *address = [NSString stringWithFormat:@"%@ %@ %@ %@"
                             ,[dataDictionary objectForKey:@"practice_address"]
                             ,[dataDictionary objectForKey:@"practice_city"]
                             ,[dataDictionary objectForKey:@"practice_state"]
                             ,[dataDictionary objectForKey:@"practice_zipcode"]];


        NSString *mapAddress = [@"http://maps.apple.com/?q=" stringByAppendingString:[address stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];

        NSLog(@"Map Address %@",mapAddress);

        [objSpineCustomProtocol setUserDefaults:mapAddress :@"webSiteToLoad"];

        [self performSegueWithIdentifier: @"provider_to_web_loader_segue" sender: self];

// VKJ


2

Đã cập nhật lên Swift 4 dựa trên câu trả lời của @ PJeremyMalouf:

private func navigateUsingAppleMaps(to coords:CLLocation, locationName: String? = nil) {
    let placemark = MKPlacemark(coordinate: coords.coordinate, addressDictionary:nil)
    let mapItem = MKMapItem(placemark: placemark)
    mapItem.name = locationName
    let launchOptions = [MKLaunchOptionsDirectionsModeKey: MKLaunchOptionsDirectionsModeDriving]
    let currentLocationMapItem = MKMapItem.forCurrentLocation()

    MKMapItem.openMaps(with: [currentLocationMapItem, mapItem], launchOptions: launchOptions)
}

1

Không sử dụng bản đồ, chỉ lập trình bằng hành động UiButton, điều này rất tốt cho tôi.

// Button triggers the map to be presented.

@IBAction func toMapButton(sender: AnyObject) {

//Empty container for the value

var addressToLinkTo = ""

//Fill the container with an address

self.addressToLinkTo = "http://maps.apple.com/?q=111 Some place drive, Oak Ridge TN 37830"

self.addressToLinkTo = self.addressToLinkTo.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)!

let url = NSURL(string: self.addressToLinkTo)
UIApplication.sharedApplication().openURL(url!)

                }

Bạn có thể trải một số mã này ra một chút. Ví dụ, tôi đặt biến là biến cấp độ lớp, có một hàm khác điền vào nó và sau đó khi nhấn nút, chỉ cần lấy những gì có trong biến đó và xóa nó để sử dụng trong URL.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.