以编程方式/手动创建MKPlacemark/CLPlacemark

12

问题

我有一组地标信息(国家,城市等)和一个纬度/经度对。 我想使用它来创建一个MKPlacemark对象。


讨论

看起来只能通过以下方式创建该类:

- (id)initWithCoordinate:(CLLocationCoordinate2D)coordinate addressDictionary:(NSDictionary *)addressDictionary

文档指出

如果您已经拥有地址信息(例如通讯录中的联系人),可以手动为实体创建标记对象。显式创建一个标记对象可避免需要查询反向地理编码器对象获取相同的信息。

太好了! 我已经进行了反向地理编码并希望避免这样的查询。 我可以添加什么到字典中?

有关可用于此字典键的字符串列表,请参见ABPerson Reference中的“地址属性”常量。 字典中的所有键都应该在顶层。

其中显示相关键

const ABPropertyID kABPersonAddressProperty;
const CFStringRef kABPersonAddressStreetKey;
const CFStringRef kABPersonAddressCityKey;
const CFStringRef kABPersonAddressStateKey;
const CFStringRef kABPersonAddressZIPKey;
const CFStringRef kABPersonAddressCountryKey;
const CFStringRef kABPersonAddressCountryCodeKey;

这远远不足以满足MKPlacemark的基本特性:

访问位置数据

  • location 属性

访问地标属性

  • name 属性
  • addressDictionary 属性
  • ISOcountryCode 属性
  • country 属性
  • postalCode 属性
  • administrativeArea 属性
  • subAdministrativeArea 属性
  • locality 属性
  • subLocality 属性
  • thoroughfare 属性
  • subThoroughfare 属性
  • region 属性

访问地理信息

  • inlandWater 属性
  • ocean 属性

访问地标信息

  • areasOfInterest 属性

幸运的是,MKPlacemark的超类的实际头文件中有关于地址字典的说明:

// address dictionary properties

@property (nonatomic, readonly) NSString *name; // eg. Apple Inc.

@property (nonatomic, readonly) NSString *thoroughfare; // street address, eg. 1 Infinite Loop

@property (nonatomic, readonly) NSString *subThoroughfare; // eg. 1

@property (nonatomic, readonly) NSString *locality; // city, eg. Cupertino

@property (nonatomic, readonly) NSString *subLocality; // neighborhood, common name, eg. Mission District

@property (nonatomic, readonly) NSString *administrativeArea; // state, eg. CA

@property (nonatomic, readonly) NSString *subAdministrativeArea; // county, eg. Santa Clara

@property (nonatomic, readonly) NSString *postalCode; // zip code, eg. 95014

@property (nonatomic, readonly) NSString *ISOcountryCode; // eg. US

@property (nonatomic, readonly) NSString *country; // eg. United States

@property (nonatomic, readonly) NSString *inlandWater; // eg. Lake Tahoe

@property (nonatomic, readonly) NSString *ocean; // eg. Pacific Ocean

@property (nonatomic, readonly) NSArray *areasOfInterest; // eg. Golden Gate Park

那么,我创建了一个字典,然后像这样传递它:

return [[[MKPlacemark alloc] initWithCoordinate:aLocation.coordinate addressDictionary:addressDictionary] autorelease];

不幸的是,经过所有的努力,内省显示信息没有被保留:

NSLog(@"placemark %@ from %@", placemark, addressDictionary);
NSLog(@"has %@", placemark.thoroughfare);

打印

2012-01-31 20:14:22.545 [15450:1403] placemark <+___,-___> +/- 0.00m from {
administrativeArea = __;
postalCode = _____;
subAdministrativeArea = ___;
subThoroughfare = __;
thoroughfare = "_____";
}
2012-01-31 20:14:22.545[15450:1403] has (null)

结论

所以,我在这里接近尾声了。有人知道如何创建自己的MKPlacemark吗?谢谢。


你的addressDictionary看起来是空的。如果在return语句之前NSLog一下会怎么样呢?(顺便说一下,我通常不会在同一个语句中alloc、init、autorelease和return。如果你将它们分成单独的语句,调试会更容易。) - Rayfleck
请再次查看调试输出 - 字典肯定显示了5个值(我已经编辑了这些值)。如何将值放入MKPlacemark是核心问题。谢谢! - SG1
啊,我明白了。你也删除了地标吗?在返回方法之前,在调试器中它看起来像什么? - Rayfleck
仅有GPS坐标。重要的内容应该是明显的:创建了一个地标。字典包含值。结果地标为空。也许这个字典需要特殊的键?或者还有其他方法来创建这个地标? - SG1
哇,我正试图做完全相同的事情,并遇到了同样的问题!在我的情况下,我有一个BSKmlResult(由于出色的BSForwardGeocoder提供支持,因为我仍然需要支持iOS 4,否则我会使用CLGeocoder)。我在MKPlacemark上进行了类扩展,并尝试着做基本相同的事情,但是没有成功。:( - Joe D'Andrea
1个回答

4
您可以创建MKPlacemark的子类:
MyPlacemark.h中:
@interface MyPlacemark : MKPlacemark

extern NSString * const kCustomPlacemarkAddressThoroughfareKey;
extern NSString * const kCustomPlacemarkAddressSubThoroughfareKey;
extern NSString * const kCustomPlacemarkAddressLocalityKey;
extern NSString * const kCustomPlacemarkAddressSubLocalityKey;
extern NSString * const kCustomPlacemarkAddressAdministrativeAreaKey;
extern NSString * const kCustomPlacemarkAddressSubAdministrativeAreaKey;
extern NSString * const kCustomPlacemarkAddressPostalCodeKey;
extern NSString * const kCustomPlacemarkAddressCountryKey;
extern NSString * const kCustomPlacemarkAddressCountryCodeKey;

@end

在 MyPlacemark.m 文件中:
#import "MyPlacemark.h"

@implementation MyPlacemark

NSString * const kCustomPlacemarkAddressThoroughfareKey = @"thoroughfare";
NSString * const kCustomPlacemarkAddressSubThoroughfareKey = @"subThoroughfare";
NSString * const kCustomPlacemarkAddressLocalityKey = @"locality";
NSString * const kCustomPlacemarkAddressSubLocalityKey = @"subLocality";
NSString * const kCustomPlacemarkAddressAdministrativeAreaKey = @"administrativeArea";
NSString * const kCustomPlacemarkAddressSubAdministrativeAreaKey = @"subAdministrativeArea";
NSString * const kCustomPlacemarkAddressPostalCodeKey = @"postalCode";
NSString * const kCustomPlacemarkAddressCountryKey = @"country";
NSString * const kCustomPlacemarkAddressCountryCodeKey = @"countryCode";

- (NSString *)thoroughfare
{
    return [self.addressDictionary objectForKey:kCustomPlacemarkAddressThoroughfareKey];
}

- (NSString *)subThoroughfare
{
    return [self.addressDictionary objectForKey:kCustomPlacemarkAddressSubThoroughfareKey];
}

- (NSString *)locality
{
    return [self.addressDictionary objectForKey:kCustomPlacemarkAddressLocalityKey];
}

- (NSString *)subLocality
{
    return [self.addressDictionary objectForKey:kCustomPlacemarkAddressSubLocalityKey];
}

- (NSString *)administrativeArea
{
    return [self.addressDictionary objectForKey:kCustomPlacemarkAddressAdministrativeAreaKey];
}

- (NSString *)subAdministrativeArea
{
    return [self.addressDictionary objectForKey:kCustomPlacemarkAddressSubAdministrativeAreaKey];
}

- (NSString *)postalCode
{
    return [self.addressDictionary objectForKey:kCustomPlacemarkAddressPostalCodeKey];
}

- (NSString *)country
{
    return [self.addressDictionary objectForKey:kCustomPlacemarkAddressCountryKey];    
}

- (NSString *)countryCode
{
    return [self.addressDictionary objectForKey:kCustomPlacemarkAddressCountryCodeKey];
}

@end

这看起来很丑,但这是我目前找到的唯一可行的方法。


丑陋,但如果这是唯一明智的方法...你会怎么做?在我的情况下,如果我真的在使用BSKmlResult(来自BSForwardGeocoder),那么它可能会正常工作,所以我将把我的类扩展转换为子类,并在我的子类中调用超类,如果BSKmlResult未在我的子类中设置。 - Joe D'Andrea

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