您的位置:首页 > 移动开发 > IOS开发

菜鸟:IOS 学习:磨难记 (第五天)

2013-01-19 21:16 281 查看
分析开发者指南源码  GI地址
分析通讯录 模块contact 中model 文件

IAddressBook.h IIAddressBook.m

知识重点:
1、数组 
  不可变  
NSArray*array=[[NSArray alloc] init];  

  对应 
int i = {1, 2,3};

  可变 
NSMutableArray *mutableArray =[[NSMutableArray alloc] init];  
  对应 
int a[10]
= {1};

2、CLASS消息机制 参考文档Cocoa深入检出消息机制
1,首先去该类的方法 cache 中查找,如果找到了就返回它;

2,如果没有找到,就去该类的方法列表中查找。如果在该类的方法列表中找到了,则将 IMP 返回,并将它加入cache中缓存起来。根据最近使用原则,这个方法再次调用的可能性很大,缓存起来可以节省下次调用再次查找的开销。
3,如果在该类的方法列表中没找到对应的 IMP,在通过该类结构中的 super_class指针在其父类结构的方法列表中去查找,直到在某个父类的方法列表中找到对应的IMP,返回它,并加入cache中;

4,如果在自身以及所有父类的方法列表中都没有找到对应的 IMP,则看是不是可以进行动态方法决议;

5,如果动态方法决议没能解决问题,进入消息转发流程

二、分析源码知识重点

1、

ABMultiValueCopyLabelAtIndex 得到手机的多项属性

ABAddressBookCopyLocalizedLabel 得到本地化版本的属性标签

2、CFSTringref 和NSString

CoreFoundation里面的CFStringRef和NSString*是可以直接转换的,两种也都有一个相似的用来直接赋常量的操作。例如:

CFStringRef a = CFSTR("a");

NSString *b = @"b";

CFSTR分配出来的字符串对象是不能自己释放的

b 一个autorelease的对象

3、stringWithString和initWithString

[NSString stringWithString:@""] stringWithString 是类方法,返回一个auto-released的指向NSString的指针,会自动释放,适合临时变量,在一个函数体内部使用

[[NSString alloc] initWithString:@""] initWithString 实例方法,返回一个指向NSString的指针,同时该对象的retain
count为1,需要手动释放

4、stringByReplacingOccurrencesOfString

[s stringByReplacingOccurrencesOfString:@"s"withString:@"x"]; //S替换为X

5、ABRecordCopyValue

(__bridgeNSDate *)ABRecordCopyValue(person, kABPersonModificationDateProperty); //最后一次修改該条记录的时间返回记录数据

6、ABRecordCopyCompositeName 返回名称

7、ABAddressBookGetPersonWithRecordID  返回某个人的记录

8、ABMultiValueCopyValueAtIndex 返回指定位置的多值属性

9、[array addObject:...] : 向可变数组尾部添加数据对象。
[array addObjectsFromArray:..] :向可变数组尾部添加一个数组对象。

10、ABPersonHasImageData  //表示某人是否有图片

11、ABPersonCopyImageData //返回某人图片

12、

NSData  主要用于数据缓冲

[UIImage imageWithData:data]  创建图片数据

13、ABPersonRemoveImageData 删除图片数据

14、ABPersonSetImageData 设置新图片数据

15、

stringWithFormat 格式化字符串

[NSString stringWithFormat:@"%@", stringName]

16、ABMultiValueAddValueAndLabel  //添加多项值到指定标示

17、ABRecordSetValue   //添加记录

18、CFDictionaryCreate  //创建一个不变的字典

IIAddressBook.h

#import <Foundation/Foundation.h>
#import <AddressBook/AddressBook.h>
//地址薄框架提供联系人数据库,通讯数据库等

@interface IIAddressBook : NSObject {

}

// get label of phone number (e.g. Mobile, Home, etc)
/**
+ 代表类方法
**/
//得到手机数据 ABMultiValueRef 某一个可能有多个字段数值的记录
+ (NSString *)getPhoneLabel:(ABMultiValueRef)phones index:(int)index;

// get full name of contact 单个人个名称 ABAddressBookRef 某个通讯录
+ (NSString *)getFullName:(ABAddressBookRef)addressBook personId:(int)personId;

//某个人的名称 ABRecordRef  某一条通讯录记录
+ (NSString *)getFullName:(ABRecordRef)person;

// get all phone numbers of one contact 手机号码
//获取某联系人全部电话  ABRecordRef  某一条通讯录记录
+ (NSArray *)getPhones:(ABRecordRef)person;

// get all emails of one contact 邮箱
//获取某联系人全部邮箱 ABRecordRef  某一条通讯录记录
+ (NSArray *)getEmails:(ABRecordRef)person;

// get image of contact
//获取某联系人头像 ABRecordRef  某一条通讯录记录
+ (UIImage*)getImageByPerson:(ABRecordRef)person;

//获取某联系人小头像 ABRecordRef  某一条通讯录记录
+ (UIImage*)getSmallImage:(ABRecordRef)person size:(CGSize)size;

//设置某联系人名称 ABRecordRef  某一条通讯录记录
+ (NSString*)getShortName:(ABRecordRef)person;

/**
* 类消息 返回最近修改的时间
* ABRecordID 记录的ID int 类型
**/
+ (NSDate*)copyModificationDate:(ABRecordRef)person;

// set address into contact
//设置某联系人地址 ABRecordID 记录的ID int 类型
+ (BOOL)addAddress:(ABRecordRef)person street:(NSString*)street;

// set phones into contact
//设置某联系人电话 ABRecordID 记录的ID int 类型
+ (BOOL)addPhone:(ABRecordRef)person phone:(NSString*)phone;

// set image into contact
//设置某联系人头像 ABRecordID 记录的ID int 类型
+ (BOOL)addImage:(ABRecordRef)person image:(UIImage*)image;

//判断某联系人邮箱数据 ABRecordID 记录的ID int 类型
+ (NSArray *)getEmailsWithAddressBook:(ABRecordID)personId addressBook:(ABAddressBookRef)addressBook;

//判断某联系人电话数据 ABRecordID 记录的ID int 类型
+ (NSArray *)getPhonesWithAddressBook:(ABRecordID)personId addressBook:(ABAddressBookRef)addressBook;

//判断某联系人是否有电话 ABRecordRef  某一条通讯录记录
+ (BOOL)hasPhones:(ABRecordRef)person;

//判断某联系人是否有邮箱 ABRecordRef  某一条通讯录记录
+ (BOOL)hasEmails:(ABRecordRef)person;

@end

IIAddressBook. m

#import "IIAddressBook.h"

@implementation IIAddressBook

/**
*  得到手机数据
*  1、获取手机lable数据
*  2、转化NSString类型
*  3、替换成正常数据,返回
*/
// return label, but remove prefix and suffix in "_$!<Mobile>!$_"
+ (NSString *)getPhoneLabel:(ABMultiValueRef)phones index:(int)index
{
/**
* CFStringRef 赋值常量
*ABMultiValueCopyLabelAtIndex 得到手机的多项属性
ABAddressBookCopyLocalizedLabel 得到本地化版本的属性标签
*/
CFStringRef origLabel = ABMultiValueCopyLabelAtIndex(phones, index);

CFStringRef localizedLabel = ABAddressBookCopyLocalizedLabel(origLabel);

/**
*改进版
* CFStringRef localizedLabel = ABAddressBookCopyLocalizedLabel(CFAutoRelease(ABMultiValueCopyLabelAtIndex(phones, index)));;
**/
//转换为字符串
NSString* finalLabel = [NSString stringWithString:(__bridge NSString *)localizedLabel];

//替换
finalLabel = [finalLabel stringByReplacingOccurrencesOfString:@"_$!<" withString:@""];
finalLabel = [finalLabel stringByReplacingOccurrencesOfString:@">!$_" withString:@""];

//返回处理完的手机数据
return f
9571
inalLabel;
}

/**
* 返回 最近修改的时间
**/
+ (NSDate*)copyModificationDate:(ABRecordRef)person
{
//最后一次修改該条记录的时间
NSDate* date = (__bridge NSDate *)ABRecordCopyValue(person, kABPersonModificationDateProperty);

return date;
}

/**
*  获取某联系人的名称
*  1、获取某个人的记录
*  2、如果存在数据,调用类消息getFullName处理
*/
+ (NSString *)getFullName:(ABAddressBookRef)addressBook personId:(int)personId
{
//ABAddressBookGetPersonWithRecordID 返回某个人的记录
ABRecordRef personRef = ABAddressBookGetPersonWithRecordID(addressBook, personId);
//如果没有数据,跳出
if (!personRef)
return nil;
else { //如果有数据,调用类消息处理
return [IIAddressBook getFullName:personRef];
}
}

/**
*  获取某联系人名称
*  1、从某个人的记录提取名称
*  2、如果存在数据,转化字符串后返回
*/
+ (NSString *)getFullName:(ABRecordRef)person
{
//ABRecordCopyCompositeName 返回名称
CFStringRef name = ABRecordCopyCompositeName(person);
if (name == NULL){ //如果名字为空,跳出
return [NSString stringWithString:@""];
}
//转化微字符串
NSString* ret = [NSString stringWithString:(__bridge NSString*)name];

//释放内存
CFRelease(name);

//返回名称
return ret;
}

/**
*  获取某联系人全部电话
*  1、取出某个人的记录
*  2、如果存在数据,调用处理电话的类消息getPhones
*/
+ (NSArray *)getPhonesWithAddressBook:(ABRecordID)personId addressBook:(ABAddressBookRef)addressBook
{
//ABAddressBookGetPersonWithRecordID 返回某个人的记录
ABRecordRef person = ABAddressBookGetPersonWithRecordID(addressBook, personId);
if (person){ //有则调用处理电话消息
return [IIAddressBook getPhones:person];
}
else {
return nil;
}
}
/**
*  判断某联系人是否有电话
*  1、调用处理电话消息 getPhones
*  2、存在数据,返回YES ,没有返回NO
*/
// get the first phone number to display
+ (BOOL)hasPhones:(ABRecordRef)person
{
//调用处理电话消息
NSArray* phones = [IIAddressBook getPhones:person];
if (phones != nil && [phones count] > 0){ //返回BOOL
return YES;
}
else {
return NO;
}
}

/**
*  判断某联系人是否有邮箱
*  1、调用处理邮箱消息 getEmails
*  2、存在数据,返回YES ,没有返回NO
*/
+ (BOOL)hasEmails:(ABRecordRef)person
{
NSArray* emails = [IIAddressBook getEmails:person];
if (emails != nil && [emails count] > 0){
return YES;
}
else {
return NO;
}

}
/**
*  获取某联系人全部电话
*  1、取出某个人的记录
*  2、如果存在数据,循环把转化后字符串电话数据压入数组
*  3、返回数据
*/
+ (NSArray *)getPhones:(ABRecordRef)person
{
//可变数组初始化
NSMutableArray* phoneList = [[NSMutableArray alloc] init];

//读取电话多值
ABMultiValueRef phones = ABRecordCopyValue(person, kABPersonPhoneProperty);
if (phones){ //如果数据存在
int count = ABMultiValueGetCount(phones); //返回电话总数
for (CFIndex i = 0; i < count; i++) {
//NSString *phoneLabel       = (__bridge NSString *)ABMultiValueCopyLabelAtIndex(phones, i);
//转化为多个电话数据为字符串
NSString *phoneNumber      = (__bridge NSString *)ABMultiValueCopyValueAtIndex(phones, i);

//NSLog(@"phone label (%@), number (%@)", phoneLabel, phoneNumber);
//电话数据压入数组 addObject 向可变数组尾部添加数据对象
[phoneList addObject:phoneNumber];

}
}
//释放内存,返回数据
CFRelease(phones);
return phoneList;
}

/**
*  获取某联系人全部电话
*  1、取出某个人的记录
*  2、如果存在数据,循环把转化后字符串电话数据压入数组
*  3、返回数据
*/
+ (NSArray *)getEmailsWithAddressBook:(ABRecordID)personId addressBook:(ABAddressBookRef)addressBook
{
//返回某个人的记录
ABRecordRef person = ABAddressBookGetPersonWithRecordID(addressBook, personId);
if (person){ //存在回调邮箱处理消息 getEmails
return [IIAddressBook getEmails:person];
}
else { //没有数据跳出
return nil;
}
}

/**
*  获取某联系人全部电话
*  1、取出某个人的记录
*  2、如果存在数据,循环把转化后字符串邮箱数据压入数组
*  3、返回数据
*/
// can be refactored to the same implementation later
+ (NSArray *)getEmails:(ABRecordRef)person
{
//可变数组
NSMutableArray* emailList = [[NSMutableArray alloc] init];

//读取邮箱多值
ABMultiValueRef emails = ABRecordCopyValue(person, kABPersonEmailProperty);

if (emails){ //如果有邮箱数据
int emailCount = ABMultiValueGetCount(emails);
for (CFIndex i = 0; i < emailCount; i++) {
//转化为多个邮箱数据为字符串
NSString *label       = (__bridge NSString *)ABMultiValueCopyLabelAtIndex(emails, i);
NSString *value      = (__bridge NSString *)ABMultiValueCopyValueAtIndex(emails, i);

// NSLog(@"email label (%@), number (%@)", label, value);

[emailList addObject:value];

}
}
//释放内存,返回数据
CFRelease(emails);

return emailList;
}

/**
*  获取某联系人头像
*  1、初始化图片类型
*  2、判断是否有图片,如果有先读入换缓冲区,在转化微图片类型
*  3、返回图片数据
*/
+ (UIImage*)getImageByPerson:(ABRecordRef)person
{
UIImage* image = nil;//初始化图片类型

if (ABPersonHasImageData(person)){ //表示一人是否有图片

//返回图片到缓冲
NSData* data = (__bridge NSData *)ABPersonCopyImageData(person);
image = [UIImage imageWithData:data];//转化图片类型

}

return image;
}

/**
*  获取某联系人小头像
*  1没完工
*/
+ (UIImage*)getSmallImage:(ABRecordRef)person size:(CGSize)size
{
UIImage* image = [IIAddressBook getImageByPerson:person];

if (image != nil){
// resize image
//return [image imageByScalingAndCroppingForSize:size];
}

return nil;
}

/**
*  设置某联系人名称
*  1、读取名,和姓
*  2、设置姓名完整标示,姓,名完整行处理
*  3、根据标示,组合姓名
*/
+ (NSString*)getShortName:(ABRecordRef)person
{
//返回名
NSString* firstName = (__bridge NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty);
//返回姓
NSString* lastName  = (__bridge NSString *)ABRecordCopyValue(person, kABPersonLastNameProperty);
//返回公司
NSString* orgName = (__bridge NSString *)ABRecordCopyValue(person, kABPersonOrganizationProperty);

BOOL useOrgName = NO; //姓名是否完整标示

if (firstName == nil && lastName == nil) //如果姓名都有,设置YES
useOrgName = YES;

if (firstName == nil) // 处理名
firstName = @"";

if (lastName == nil) //处理姓
lastName = @"";

NSString* fullName; //姓名

if (useOrgName == NO){ //如果姓名完整
NSString* countryCode; //是否多国判断
//NSString* countryCode = [LocaleUtils getCountryCode];
if (countryCode != nil && ( [countryCode isEqualToString:@"CN"] == YES ||
[countryCode isEqualToString:@"TW"] == YES ||
[countryCode isEqualToString:@"KR"] == YES ||
[countryCode isEqualToString:@"JP"] == YES)
)
{
if ([lastName length] > 0){  //如果姓,名有数据,则把姓,名设置给全名变量
fullName = [NSString stringWithFormat:@"%@ %@", lastName, firstName];
}
else { //否则把名设置给全名变量
fullName = [NSString stringWithString:firstName];
}

}//默认不区分国际
else {
if ([firstName length] > 0){ //如果名有数据,则把名设置给全名变量
fullName = [NSString stringWithFormat:@"%@", firstName];
}
else { //否则把姓设置给全名变量
fullName = [NSString stringWithString:lastName];
}

}
} //如果姓名不完整
else {

if (orgName == nil) //标示为空
orgName = @"";
//格式化标示
fullName = [NSString stringWithFormat:@"%@", orgName];
}

//返回姓名
return fullName;

}

/**
*  设置电话
*  1、初始化一些参数
*  2、添加多项值到指定标示
*  3、添加多条记录
*/
+ (BOOL)addPhone:(ABRecordRef)person phone:(NSString*)phone
{
//创建一个新的,空的,可变的多值属性
ABMutableMultiValueRef multi = ABMultiValueCreateMutable(kABMultiStringPropertyType);

CFErrorRef anError = NULL;

// The multivalue identifier of the new value isn't used in this example,
// multivalueIdentifier is just for illustration purposes.  Real-world
// code can use this identifier to do additional work with this value.
ABMultiValueIdentifier multivalueIdentifier;//多项标示符

//添加多项值到指定标示
if (!ABMultiValueAddValueAndLabel(multi, (__bridge CFStringRef)phone, kABPersonPhoneMainLabel, &multivalueIdentifier)){
CFRelease(multi);
return NO;
}

//添加记录
if (!ABRecordSetValue(person, kABPersonPhoneProperty, multi, &anError)){
CFRelease(multi);
return NO;
}
//释放内存,返回BOOL
CFRelease(multi);
return YES;
}

/**
*  设置地址
*  1、初始化一些参数
*  2、添加多项值到指定标示
*  3、添加多条记录
*/
+ (BOOL)addAddress:(ABRecordRef)person street:(NSString*)street
{
//创建一个新的,空的,可变的多值属性
ABMutableMultiValueRef address = ABMultiValueCreateMutable(kABDictionaryPropertyType);

static int  homeLableValueCount = 5;

// Set up keys and values for the dictionary.
CFStringRef keys[homeLableValueCount];//键数组
CFStringRef values[homeLableValueCount];//值数组
keys[0]      = kABPersonAddressStreetKey; //街道
keys[1]      = kABPersonAddressCityKey; //城市标示
keys[2]      = kABPersonAddressStateKey;//州
keys[3]      = kABPersonAddressZIPKey; //邮编
keys[4]      = kABPersonAddressCountryKey; //国家
values[0]    = (__bridge CFStringRef)street;
values[1]    = CFSTR("");
values[2]    = CFSTR("");
values[3]    = CFSTR("");
values[4]    = CFSTR("");

//CFDictionaryCreate 创建一个不变的字典
CFDictionaryRef aDict = CFDictionaryCreate(
kCFAllocatorDefault,
(void *)keys,
(void *)values,
homeLableValueCount,
&kCFCopyStringDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks
);

// Add the street address to the person record.
ABMultiValueIdentifier identifier; //标示

//添加多项值到指定标示
BOOL result = ABMultiValueAddValueAndLabel(address, aDict, kABHomeLabel, &identifier);
CFErrorRef error = NULL;
//添加记录
result = ABRecordSetValue(person, kABPersonAddressProperty, address, &error);

//释放内存,返回数据
CFRelease(aDict);
CFRelease(address);

return result;
}

/**
*  设置某联系人头像
*  1、删除旧图片
*  2、设置新的图片,返回图片数据
*/
+ (BOOL)addImage:(ABRecordRef)person image:(UIImage*)image
{
CFErrorRef error = NULL; //错误类型记录

// remove old image data firstly
ABPersonRemoveImageData(person, NULL); //删除旧的图片数据

// add new image data 设置新图片数据
BOOL result = ABPersonSetImageData (
person,
(__bridge CFDataRef)UIImagePNGRepresentation(image),
&error
);

//    CFRelease(error);

return result;
}

@end
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: