应用开发中的地址簿功能实现
立即解锁
发布时间: 2025-08-24 01:07:05 阅读量: 1 订阅数: 38 


Objective-C编程与应用开发实战
### 应用开发中的地址簿功能实现
在应用开发过程中,涉及到地址簿功能时,会有多个关键环节需要处理,包括发送响应、命令处理、访问远程地址簿等。下面将详细介绍这些方面的实现。
#### 1. 发送响应
在处理传入数据后,发送响应是一个重要步骤。借助`dispatch_io`,发送响应变得相对简单,只需调用一次`dispatch_io_write()`方法即可。以下是发送数据的代码示例:
```objc
- (void) sendData: (NSData *) data
{
// the queue for all blocks here
dispatch_queue_t q = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// we want a dispatch_data_t referencing this NSData object
// the logical thing is to have the dispatch cleanup block reference & release
// the NSData, except we can't call -release on it under ARC. The solution is to
// bridge-cast the NSData to a manually-counted CFDataRef, which we can release.
CFDataRef cfData = CFBridgingRetain(data);
dispatch_data_t ddata = dispatch_data_create(CFDataGetBytePtr(cfData),
CFDataGetLength(cfData),
q, ^{ CFRelease(cfData); });
dispatch_io_write(_io, 0, ddata, q, ^(bool done, dispatch_data_t d, int err) {
if ( err != 0 )
{
NSError * error = [NSError errorWithDomain: NSPOSIXErrorDomain
code: err
userInfo: nil];
NSLog(@"Failed to send data: %@", error);
return;
}
else if ( done )
{
NSLog(@"Sent %lu bytes of data", CFDataGetLength(cfData));
}
});
}
```
这里存在一个小问题,即需要将`NSData`对象转换为`dispatch_data`对象。由于在ARC下无法直接释放`NSData`对象,解决方法是使用免费桥接将`NSData`转换为手动管理的`CFData`对象,然后在清理块中手动释放它。
#### 2. 命令处理
`APAddressBookClient`对象解码后的命令会传递给其委托对象,通常是`APAddressBookBrowser`对象。在实现之前,需要在`APAddressBookBrowser.h`文件中添加相关协议声明:
```objc
#import "APRemoteAddressBookInterface.h"
#import "APAddressBookClient.h"
@interface APRemoteAddressBookBrowser : NSObject
<APRemoteAddressBookBrowser, APAddressBookClientDelegate,
NSNetServiceBrowserDelegate, NSNetServiceDelegate>
@end
```
命令处理方法会提取命令的名称和UUID,根据这些信息向`_localAddressBook`实例发送相应的消息。以下是处理传入命令的代码示例:
```objc
- (void) client: (APAddressBookClient *) client
handleMessage: (NSDictionary *) command
{
void (^dataHandler)(NSArray *, NSError *) = ^(NSArray * values, NSError * error) {
// ...
};
NSString * name = command[APRemoteAddressBookCommandNameKey];
NSString * identifier = command[APRemoteAddressBookCommandPersonIDKey];
if ( [name isEqualToString: APRemoteAddressBookCommandAllPeople] )
{
[_localAddressBook allPeople: dataHandler];
}
else if ( [name isEqualToString: APRemoteAddressBookCommandGetMailingAddresses] )
{
[_localAddressBook mailingAddressesForPersonWithIdentifier: identifier
reply: dataHandler];
}
else if ( [name isEqualToString: APRemoteAddressBookCommandGetEmailAddresses] )
{
[_localAddressBook emailAddressesForPersonWithIdentifier: identifier
reply: dataHandler];
}
else if ( [name isEqualToString: APRemoteAddressBookCommandGetPhoneNumbers] )
{
[_localAddressBook phoneNumbersForPersonWithIdentifier: identifier
reply: dataHandler];
}
else
{
id userInfo = @{ NSLocalizedDescriptionKey : @"Unknown command" };
NSError * error = [NSError errorWithDomain: APRemoteAddressBookErrorDomain
code: 101
userInfo: userInfo];
dataHandler(nil, error);
}
}
- (void) clientDisconnected: (APAddressBookClient *) client withError: (NSError *) error
{
// not doing anything with the error, which has already been logged.
[_clients removeObject: client];
}
```
数据处理程序会将结果打包为JSON数据,并发送回发送命令的客户端。以下是命令数据处理程序的代码:
```objc
NSMutableDictionary * result = [NSMutableDictionary new];
NSUUID * uuid = command[APRemoteAddressBookCommandUUIDKey];
result[APRemoteAddressBookCommandNameKey] = APRemoteAddressBookCommandReply;
result[APRemoteAddressBookCommandUUIDKey] = uuid;
if ( values != nil )
result[APRemoteAddressBookCommandValueKey] = values;
if ( error != nil )
result[APRemoteAddressBookCommandErrorKey] = [error jsonDictionaryRepresentation];
NSError * jsonError = nil;
NSData * jsonData = [NSJSONSerialization dataWithJSONObject: result
options: 0
error: &jsonError];
if ( jsonData == nil )
{
NSLog(@"Error building JSON reply: %@. Message = %@. Reply = %@",
jsonError, command, result);
return;
}
// send the data asynchronously
[client sendData: jsonData];
```
#### 3. 访问远程地址簿
要访问网络上其他应用实例的地址簿,应用需要按以下三个步骤执行:
- 向XPC服务代理对象发送`-availableServiceNames:`消息,获取可用服务列表,并在窗口中显示给用户。
- 用户选择服务后,应用向XPC代理发送`-attachToRemoteAddressBookWithName:handler:`消息以建立连接。
- 连接成功后,显示新的地址簿窗口,并通过向XPC代理发送`-allPeople:`消息异步加载人员列表。
以下是连接服务的方法实现:
```objc
- (void) connectToServiceWithName: (NSString *) name
replyHandler: (void (^)(id<APRemoteAddressBook>, NSError *)) replyHandler
{
NSLog(@"Connecting to service named '%@'", name);
__block NSNetService * selected = nil;
// search individual domains -- look in "local" domain first, then any others
NSMutableArray * localServices = _servicesByDomain[@"local."];
NSLog(@"Searching local services: %@", localServices);
for ( NSNetService * service in localServices )
{
if ( [[service name] isEqualToString: name] )
{
NSLog(@"Found local service: %@", service);
selected = service;
break;
}
}
// if no local services were found, look in the other domains
if ( selected == nil )
{
[_servicesByDomain enumerateKeysAndObjectsUsingBlock: ^(id key, id obj, BOOL *stop) {
if ( [key isEqualToString: @"local."] )
return; // skip local domain, we've already looked there
NSLog(@"Searching services in domain '%@': %@", key, obj);
for ( NSNetService * service in obj )
{
if ( [[service name] isEqualToString: name] )
{
NSLog(@"Found service: %@", service);
selected = service;
*stop = YES;
break;
}
}
}];
}
// if none were found at all, send back an error
if ( selected == nil )
{
NSDictionary * info = @{ NSLocalizedDescriptionKey : NSLocalizedString(@"An address book service with the provided name could not be found.", @"error") };
```
0
0
复制全文
相关推荐









