ios實(shí)現(xiàn)搜索關(guān)鍵字高亮效果

一. 需求要求實(shí)現(xiàn)的效果
漢字支持漢字直接搜索、拼音全拼搜索、拼音簡(jiǎn)拼搜索
搜索匹配到的關(guān)鍵字高亮顯示
搜索結(jié)果優(yōu)先顯示全部匹配、其次是拼音全拼匹配、拼音簡(jiǎn)拼匹配;關(guān)鍵字在結(jié)果字符串中位置越靠前,優(yōu)先顯示
支持搜索英文、漢字、電話號(hào)碼及混合搜索
二. 需求分析
英文名稱及電話號(hào)碼的搜索直接使用完全匹配的方式即可
重難點(diǎn)是漢字的拼音相關(guān)的拼音全拼、簡(jiǎn)拼搜索,比如 “劉亦菲” 對(duì)應(yīng)的搜索關(guān)鍵字有且只有以下三大類總計(jì) 25 種匹配漢字:“劉”、“亦”、“菲”、“劉亦”、“亦菲”、“劉亦菲”
簡(jiǎn)拼相關(guān):"l"、"y"、"f"、"ly"、"yf"、"lyf"
全拼相關(guān):"li"、"liu"、"liuy"、"liuyi"、"liuyif"、"liuyife"、"liuyifei"、"yi"、"yif"、"yife"、"yifei"、"fe"、"fei"
拼音的重難點(diǎn)還包括:比如搜索關(guān)鍵字為“xian”,既要匹配出“先”,也要匹配出“西安”
三. 代碼設(shè)計(jì)
1. 整體流程
首先初始化原始的數(shù)據(jù)(包含漢語(yǔ)、英文、數(shù)字及隨意組合),主要是將一個(gè)漢語(yǔ)字符串轉(zhuǎn)化為漢語(yǔ)全拼拼音及每個(gè)拼音字母所對(duì)應(yīng)漢字的位置 和 漢語(yǔ)簡(jiǎn)拼拼音和每個(gè)拼音字母對(duì)應(yīng)漢字的位置,將初始化之后的信息緩存起來(lái)
+ (instancetype)personWithName:(NSString *)name hanyuPinyinOutputFormat:(HanyuPinyinOutputFormat *)pinyinFormat {
WPFPerson *person = [[WPFPerson alloc] init];
/** 將漢字轉(zhuǎn)化為拼音的類方法
* name : 需要轉(zhuǎn)換的漢字
* pinyinFormat : 拼音的格式化器
* @"" : seperator 分隔符
*/
NSString *completeSpelling = [PinyinHelper toHanyuPinyinStringWithNSString:name withHanyuPinyinOutputFormat:pinyinFormat withNSString:@""];
// 首字母所組成的字符串
NSString *initialString = @"";
// 全拼拼音數(shù)組
NSMutableArray *completeSpellingArray = [[NSMutableArray alloc] init];
// 拼音首字母的位置數(shù)組
NSMutableArray *pinyinFirstLetterLocationArray = [[NSMutableArray alloc] init];
// 遍歷每一個(gè)字符
for (NSInteger x =0; x
根據(jù) UISearchResultsUpdating 代理方法 - (void)updateSearchResultsForSearchController:(UISearchController *)searchController 來(lái)實(shí)時(shí)獲取輸入的最新關(guān)鍵字,并遍歷數(shù)據(jù)源,將匹配到的結(jié)果顯示出來(lái)
// 更新搜索結(jié)果
- (void)updateSearchResultsForSearchController:(UISearchController *)searchController {
NSLog(@"%@", searchController.searchBar.text);
[self.searchResultVC.resultDataSource removeAllObjects];
for (WPFPerson *person in self.dataSource) {
WPFSearchResultModel *resultModel = [WPFPinYinTools
searchEffectiveResultWithSearchString:searchController.searchBar.text.lowercaseString
nameString:person.name
completeSpelling:person.completeSpelling
initialString:person.initialString
pinyinLocationString:person.pinyinLocationString
initialLocationString:person.initialLocationString];
if (resultModel.highlightRang.length) {
person.highlightLoaction = resultModel.highlightRang.location;
person.textRange = resultModel.highlightRang;
person.matchType = resultModel.matchType;
[self.searchResultVC.resultDataSource addObject:person];
}
};
// 將匹配結(jié)果按照產(chǎn)品規(guī)則進(jìn)行排序
[self.searchResultVC.resultDataSource sortUsingDescriptors:[WPFPinYinTools sortingRules]];
// 刷新tableView
dispatch_async(dispatch_get_main_queue(), ^{
[self.searchResultVC.tableView reloadData];
});
}
匹配的過(guò)程是一個(gè)重難點(diǎn),分別進(jìn)行漢字直接匹配、拼音全拼匹配、拼音簡(jiǎn)拼匹配
+ (WPFSearchResultModel *)searchEffectiveResultWithSearchString:(NSString *)searchStrLower
nameString:(NSString *)nameStrLower
completeSpelling:(NSString *)completeSpelling
initialString:(NSString *)initialString
pinyinLocationString:(NSString *)pinyinLocationString
initialLocationString:(NSString *)initialLocationString {
WPFSearchResultModel *searchModel = [[WPFSearchResultModel alloc] init];
NSArray *completeSpellingArray = [pinyinLocationString componentsSeparatedByString:@","];
NSArray *pinyinFirstLetterLocationArray = [initialLocationString componentsSeparatedByString:@","];
// 完全中文匹配范圍
NSRange chineseRange = [nameStrLower rangeOfString:searchStrLower];
// 拼音全拼匹配范圍
NSRange complateRange = [completeSpelling rangeOfString:searchStrLower];
// 拼音首字母匹配范圍
NSRange initialRange = [initialString rangeOfString:searchStrLower];
// 漢字直接匹配
if (chineseRange.length!=0) {
searchModel.highlightedRange = chineseRange;
searchModel.matchType = MatchTypeChinese;
return searchModel;
}
NSRange highlightedRange = NSMakeRange(0, 0);
// MARK: 拼音全拼匹配
if (complateRange.length != 0) {
if (complateRange.location == 0) {
// 拼音首字母匹配從0開(kāi)始,即搜索的關(guān)鍵字與該數(shù)據(jù)源第一個(gè)漢字匹配到,所以高亮范圍從0開(kāi)始
highlightedRange = NSMakeRange(0, [completeSpellingArray[complateRange.length-1] integerValue] +1);
} else {
/** 如果該拼音字符是一個(gè)漢字的首個(gè)字符,如搜索“g”,
* 就要匹配出“gai”、“ge”等“g”開(kāi)頭的拼音對(duì)應(yīng)的字符,
* 而不應(yīng)該匹配到“wang”、“feng”等非”g“開(kāi)頭的拼音對(duì)應(yīng)的字符
*/
NSInteger currentLocation = [completeSpellingArray[complateRange.location] integerValue];
NSInteger lastLocation = [completeSpellingArray[complateRange.location-1] integerValue];
if (currentLocation != lastLocation) {
// 高亮范圍從匹配到的第一個(gè)關(guān)鍵字開(kāi)始
highlightedRange = NSMakeRange(currentLocation, [completeSpellingArray[complateRange.length+complateRange.location -1] integerValue] - currentLocation +1);
}
}
searchModel.highlightedRange = highlightedRange;
searchModel.matchType = MatchTypeComplate;
if (highlightedRange.length!=0) {
return searchModel;
}
}
// MARK: 拼音首字母匹配
if (initialRange.length!=0) {
NSInteger currentLocation = [pinyinFirstLetterLocationArray[initialRange.location] integerValue];
NSInteger highlightedLength;
if (initialRange.location ==0) {
highlightedLength = [pinyinFirstLetterLocationArray[initialRange.length-1] integerValue]-currentLocation +1;
// 拼音首字母匹配從0開(kāi)始,即搜索的關(guān)鍵字與該數(shù)據(jù)源第一個(gè)漢字匹配到,所以高亮范圍從0開(kāi)始
highlightedRange = NSMakeRange(0, highlightedLength);
} else {
highlightedLength = [pinyinFirstLetterLocationArray[initialRange.length+initialRange.location-1] integerValue]-currentLocation +1;
// 高亮范圍從匹配到的第一個(gè)關(guān)鍵字開(kāi)始
highlightedRange = NSMakeRange(currentLocation, highlightedLength);
}
searchModel.highlightedRange = highlightedRange;
searchModel.matchType = MatchTypeInitial;
if (highlightedRange.length!=0) {
return searchModel;
}
}
searchModel.highlightedRange = NSMakeRange(0, 0);
searchModel.matchType = NSIntegerMax;
return searchModel;
}
2. 第三方依賴
首先篩選出一個(gè)比較全的第三方庫(kù) PinYin4Objc用于漢語(yǔ)轉(zhuǎn)拼音,拼音的 unicode 庫(kù)比較全,一些新的漢字也都能轉(zhuǎn)成拼音
但是由于該庫(kù)好久沒(méi)有更新,獲取拼音文件部分代碼不適合組件化的直接開(kāi)發(fā),因此我直接合到源文件里面了
漢語(yǔ)轉(zhuǎn)拼音的格式
// 獲取格式化器
+ (HanyuPinyinOutputFormat *)getOutputFormat {
HanyuPinyinOutputFormat *pinyinFormat = [[HanyuPinyinOutputFormat alloc] init];
/** 設(shè)置大小寫(xiě)
* CaseTypeLowercase : 小寫(xiě)
* CaseTypeUppercase : 大寫(xiě)
*/
[pinyinFormat setCaseType:CaseTypeLowercase];
/** 聲調(diào)格式 :如 王鵬飛
* ToneTypeWithToneNumber : 用數(shù)字表示聲調(diào) wang2 peng2 fei1
* ToneTypeWithoutTone : 無(wú)聲調(diào)表示 wang peng fei
* ToneTypeWithToneMark : 用字符表示聲調(diào) wáng péng fēi
*/
[pinyinFormat setToneType:ToneTypeWithoutTone];
/** 設(shè)置特殊拼音ü的顯示格式:
* VCharTypeWithUAndColon : 以U和一個(gè)冒號(hào)表示該拼音,例如:lu:
* VCharTypeWithV : 以V表示該字符,例如:lv
* VCharTypeWithUUnicode : 以ü表示
*/
[pinyinFormat setVCharType:VCharTypeWithV];
return pinyinFormat;
}
3. 其他細(xì)節(jié)
排序規(guī)則
+ (NSArray *)sortingRules {
// 按照 matchType 順序排列,即優(yōu)先展示 中文,其次是全拼匹配,最后是拼音首字母匹配
NSSortDescriptor *desType = [NSSortDescriptor sortDescriptorWithKey:@"matchType" ascending:YES];
// 優(yōu)先顯示 高亮位置索引靠前的搜索結(jié)果
NSSortDescriptor *desLocation = [NSSortDescriptor sortDescriptorWithKey:@"highlightLoaction" ascending:YES];
return @[desType,desLocation];
}
四. 循環(huán)方法測(cè)試及優(yōu)化選擇過(guò)程
在優(yōu)化遍歷方法的過(guò)程中,測(cè)試了幾種遍歷方法,這里以輸入關(guān)鍵字“wang”為測(cè)試數(shù)據(jù),測(cè)試真機(jī)機(jī)型為iPhone SE 10.3
常規(guī) for 循環(huán)
/**
2017-12-06 12:02:51.943006 HighlightedSearch[4459:1871193] w
2017-12-06 12:02:51.943431 HighlightedSearch[4459:1871193] 開(kāi)始匹配,開(kāi)始時(shí)間:2017-12-06 04:02:51 +0000
2017-12-06 12:02:51.980588 HighlightedSearch[4459:1871193] 匹配結(jié)束,結(jié)束時(shí)間:2017-12-06 04:02:51 +0000,耗時(shí):0.0372
2017-12-06 12:02:52.284488 HighlightedSearch[4459:1871193] wa
2017-12-06 12:02:52.284771 HighlightedSearch[4459:1871193] 開(kāi)始匹配,開(kāi)始時(shí)間:2017-12-06 04:02:52 +0000
2017-12-06 12:02:52.316536 HighlightedSearch[4459:1871193] 匹配結(jié)束,結(jié)束時(shí)間:2017-12-06 04:02:52 +0000,耗時(shí):0.0318
2017-12-06 12:02:52.516826 HighlightedSearch[4459:1871193] wan
2017-12-06 12:02:52.517121 HighlightedSearch[4459:1871193] 開(kāi)始匹配,開(kāi)始時(shí)間:2017-12-06 04:02:52 +0000
2017-12-06 12:02:52.545542 HighlightedSearch[4459:1871193] 匹配結(jié)束,結(jié)束時(shí)間:2017-12-06 04:02:52 +0000,耗時(shí):0.0285
2017-12-06 12:02:52.838220 HighlightedSearch[4459:1871193] wang
2017-12-06 12:02:52.838602 HighlightedSearch[4459:1871193] 開(kāi)始匹配,開(kāi)始時(shí)間:2017-12-06 04:02:52 +0000
2017-12-06 12:02:52.880200 HighlightedSearch[4459:1871193] 匹配結(jié)束,結(jié)束時(shí)間:2017-12-06 04:02:52 +0000,耗時(shí):0.0417
*/
for (NSInteger i = 0; i < self.dataSource.count; i++) {
GCD 多線程循環(huán)
/**
2017-12-06 11:56:55.565738 HighlightedSearch[4419:1869486] w
2017-12-06 11:56:55.566287 HighlightedSearch[4419:1869486] 開(kāi)始匹配,開(kāi)始時(shí)間:2017-12-06 03:56:55 +0000
2017-12-06 11:56:55.626184 HighlightedSearch[4419:1869486] 匹配結(jié)束,結(jié)束時(shí)間:2017-12-06 03:56:55 +0000,耗時(shí):0.0601
2017-12-06 11:56:55.937535 HighlightedSearch[4419:1869486] wa
2017-12-06 11:56:55.937842 HighlightedSearch[4419:1869486] 開(kāi)始匹配,開(kāi)始時(shí)間:2017-12-06 03:56:55 +0000
2017-12-06 11:56:55.983074 HighlightedSearch[4419:1869486] 匹配結(jié)束,結(jié)束時(shí)間:2017-12-06 03:56:55 +0000,耗時(shí):0.0452
2017-12-06 11:56:56.344808 HighlightedSearch[4419:1869486] wan
2017-12-06 11:56:56.347350 HighlightedSearch[4419:1869486] 開(kāi)始匹配,開(kāi)始時(shí)間:2017-12-06 03:56:56 +0000
2017-12-06 11:56:56.414215 HighlightedSearch[4419:1869486] 匹配結(jié)束,結(jié)束時(shí)間:2017-12-06 03:56:56 +0000,耗時(shí):0.0690
2017-12-06 11:56:56.711174 HighlightedSearch[4419:1869486] wang
2017-12-06 11:56:56.712013 HighlightedSearch[4419:1869486] 開(kāi)始匹配,開(kāi)始時(shí)間:2017-12-06 03:56:56 +0000
2017-12-06 11:56:56.774761 HighlightedSearch[4419:1869486] 匹配結(jié)束,結(jié)束時(shí)間:2017-12-06 03:56:56 +0000,耗時(shí):0.0632
*/
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_apply(self.dataSource.count, queue, ^(size_t index) {
enumerateObjectsWithOptions 多線程循環(huán)
/**
2017-12-06 11:58:12.716606 HighlightedSearch[4428:1869917] w
2017-12-06 11:58:12.717005 HighlightedSearch[4428:1869917] 開(kāi)始匹配,開(kāi)始時(shí)間:2017-12-06 03:58:12 +0000
2017-12-06 11:58:12.780168 HighlightedSearch[4428:1869917] 匹配結(jié)束,結(jié)束時(shí)間:2017-12-06 03:58:12 +0000,耗時(shí):0.0633
2017-12-06 11:58:13.058590 HighlightedSearch[4428:1869917] wa
2017-12-06 11:58:13.058841 HighlightedSearch[4428:1869917] 開(kāi)始匹配,開(kāi)始時(shí)間:2017-12-06 03:58:13 +0000
2017-12-06 11:58:13.116964 HighlightedSearch[4428:1869917] 匹配結(jié)束,結(jié)束時(shí)間:2017-12-06 03:58:13 +0000,耗時(shí):0.0581
2017-12-06 11:58:13.397052 HighlightedSearch[4428:1869917] wan
2017-12-06 11:58:13.397338 HighlightedSearch[4428:1869917] 開(kāi)始匹配,開(kāi)始時(shí)間:2017-12-06 03:58:13 +0000
2017-12-06 11:58:13.460298 HighlightedSearch[4428:1869917] 匹配結(jié)束,結(jié)束時(shí)間:2017-12-06 03:58:13 +0000,耗時(shí):0.0630
2017-12-06 11:58:13.763888 HighlightedSearch[4428:1869917] wang
2017-12-06 11:58:13.764263 HighlightedSearch[4428:1869917] 開(kāi)始匹配,開(kāi)始時(shí)間:2017-12-06 03:58:13 +0000
2017-12-06 11:58:13.833888 HighlightedSearch[4428:1869917] 匹配結(jié)束,結(jié)束時(shí)間:2017-12-06 03:58:13 +0000,耗時(shí):0.0697
*/
dispatch_queue_t queue = dispatch_queue_create("wpf.updateSearchResults.test", DISPATCH_QUEUE_SERIAL);
[self.dataSource enumerateObjectsWithOptions:NSEnumerationConcurrent usingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
forin 循環(huán)
/**
2017-12-06 12:00:38.217187 HighlightedSearch[4439:1870645] w
2017-12-06 12:00:38.217575 HighlightedSearch[4439:1870645] 開(kāi)始匹配,開(kāi)始時(shí)間:2017-12-06 04:00:38 +0000
2017-12-06 12:00:38.253997 HighlightedSearch[4439:1870645] 匹配結(jié)束,結(jié)束時(shí)間:2017-12-06 04:00:38 +0000,耗時(shí):0.0364
2017-12-06 12:00:38.616430 HighlightedSearch[4439:1870645] wa
2017-12-06 12:00:38.616807 HighlightedSearch[4439:1870645] 開(kāi)始匹配,開(kāi)始時(shí)間:2017-12-06 04:00:38 +0000
2017-12-06 12:00:38.654969 HighlightedSearch[4439:1870645] 匹配結(jié)束,結(jié)束時(shí)間:2017-12-06 04:00:38 +0000,耗時(shí):0.0383
2017-12-06 12:00:38.948700 HighlightedSearch[4439:1870645] wan
2017-12-06 12:00:38.949453 HighlightedSearch[4439:1870645] 開(kāi)始匹配,開(kāi)始時(shí)間:2017-12-06 04:00:38 +0000
2017-12-06 12:00:38.986892 HighlightedSearch[4439:1870645] 匹配結(jié)束,結(jié)束時(shí)間:2017-12-06 04:00:38 +0000,耗時(shí):0.0378
2017-12-06 12:00:39.280979 HighlightedSearch[4439:1870645] wang
2017-12-06 12:00:39.281563 HighlightedSearch[4439:1870645] 開(kāi)始匹配,開(kāi)始時(shí)間:2017-12-06 04:00:39 +0000
2017-12-06 12:00:39.317743 HighlightedSearch[4439:1870645] 匹配結(jié)束,結(jié)束時(shí)間:2017-12-06 04:00:39 +0000,耗時(shí):0.0365
*/
for (WPFPerson *person in self.dataSource) {
最終選擇的是forin循環(huán),因?yàn)橐话闱闆r下 enumerateObjectsWithOptions 多線程是最快的,并且稍快于 dispatch_apply 方法,但是因?yàn)檫@個(gè)方法需要操作數(shù)組,因此必須將操作數(shù)據(jù)的那行代碼加鎖或者在指定線程進(jìn)行,進(jìn)行這個(gè)操作后效率反而不如其他單線程循環(huán),考慮到搜索結(jié)果本來(lái)還要再次根據(jù)規(guī)則排序,就選擇了 forin 循環(huán)
五. 為什么沒(méi)有選擇hash
首先最重要的一條是當(dāng)前循環(huán)的方式也能滿足需求(線上大概四千多條數(shù)據(jù),使用過(guò)程中基本實(shí)時(shí)展現(xiàn))
上文在需求分析中已舉例,一個(gè)三個(gè)字的漢字對(duì)應(yīng)的key值就有20多個(gè)甚至更多,在解析過(guò)程中是十分耗時(shí)的,但需求往往還存在類似微信的“群名稱”匹配,每多一個(gè)字,對(duì)應(yīng)的key值就多幾個(gè)數(shù)量級(jí)
MapTable在高并發(fā)情況下,需要不斷進(jìn)行Resize(擴(kuò)容 & Rehash),并且在Rehash 并發(fā)的情況下還可能形成鏈表環(huán)有個(gè)優(yōu)化的思路,考慮到遍歷的方式解析快,搜索匹配慢;hash的方式解析慢,搜索匹配快
通過(guò)遍歷的方式先快速解析數(shù)據(jù),此時(shí)搜索使用遍歷的方式
然后再用hash的方式再次解析數(shù)據(jù)(考慮到hash表的擴(kuò)容會(huì)使得瞬時(shí)效率的降低,為了避免頻繁的擴(kuò)容,先使用桶排序的方法將10個(gè)數(shù)字、26個(gè)英文字母、以及特殊符號(hào)開(kāi)頭的key分別放在37個(gè)字典里面,整體是一個(gè)數(shù)組。每個(gè)字典里面存放對(duì)應(yīng)key和value),解析完成之后做個(gè)標(biāo)記就采用hash的方式直接使用輸入的key值去查詢
配合DB緩存,效果應(yīng)該是很棒的
六. 多音字
簡(jiǎn)單測(cè)了一下?lián)碛性摴δ艿漠a(chǎn)品:
微信搜索(就是文中講的該類型搜索)是在本地做的,不支持多音字
釘釘?shù)乃阉魇欠?wù)器做的,支持多音字(但是簡(jiǎn)單測(cè)了一下一些基本的多音字存在bug)
七. 實(shí)際項(xiàng)目還要做哪些工作?
正常情況下不會(huì)將所有的匹配結(jié)果在第一時(shí)間全部顯示,一般產(chǎn)品需求顯示三五個(gè)即可,因此可以匹配出若干個(gè)結(jié)果后停止循環(huán),點(diǎn)擊更多再匹配剩余數(shù)據(jù)源
配合DB和hashTable,每次只解析新增的數(shù)據(jù)源,解析一次后就緩存起來(lái)
八. 使用方法
1. 事例工程
git clone git@github.com:PengfeiWang666/HighlightedSearch.git cd Example open HighlightedSearch.xcworkspace
2. Install
pod "HighlightedSearch"
3. Usage
// WPFPinYinDataManager 依次添加數(shù)據(jù)源(標(biāo)識(shí)符為了防止重名現(xiàn)象)
+ (void)addInitializeString:(NSString *)string identifer:(NSString *)identifier
// 更新搜索結(jié)果
- (void)updateSearchResultsForSearchController:(UISearchController *)searchController {
...
...
for (WPFPerson *person in [WPFPinYinDataManager getInitializedDataSource]) {
WPFSearchResultModel *resultModel = [WPFPinYinTools searchEffectiveResultWithSearchString:keyWord Person:person];
if (resultModel.highlightedRange.length) {
person.highlightLoaction = resultModel.highlightedRange.location;
person.textRange = resultModel.highlightedRange;
person.matchType = resultModel.matchType;
[resultDataSource addObject:person];
}
}
相關(guān)文章
Swift 進(jìn)階 —— map 和 flatMap的使用
這篇文章主要介紹了Swift map和flatMap的相關(guān)資料,幫助大家更好的理解和使用Swift,感興趣的朋友可以了解下2020-09-09
iOS10 widget實(shí)現(xiàn)3Dtouch 彈出菜單
這篇文章主要介紹了 iOS10 widget實(shí)現(xiàn)3Dtouch 彈出菜單的相關(guān)資料,需要的朋友可以參考下2016-12-12
iOS實(shí)現(xiàn)貝塞爾曲線動(dòng)畫(huà)
這篇文章主要為大家詳細(xì)介紹了iOS實(shí)現(xiàn)貝塞爾曲線動(dòng)畫(huà),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-08-08
iOS 生成plist文件,在項(xiàng)目中代碼創(chuàng)建plist的實(shí)例
下面小編就為大家分享一篇iOS 生成plist文件,在項(xiàng)目中代碼創(chuàng)建plist的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-02-02
使用Reachability類判斷iOS設(shè)備的當(dāng)前網(wǎng)絡(luò)連接類型
這篇文章主要介紹了使用Reachability類判斷iOS設(shè)備的當(dāng)前網(wǎng)絡(luò)連接類型,這里開(kāi)發(fā)語(yǔ)言為傳統(tǒng)的Objectice-C,需要的朋友可以參考下2016-02-02
iOS實(shí)現(xiàn)自動(dòng)循環(huán)播放的banner實(shí)例詳解
輪播視圖通常也叫Banner,90%以上App都會(huì)用到的一個(gè)控件,網(wǎng)上有很多開(kāi)源代碼,下面這篇文章主要給大家介紹了關(guān)于利用iOS如何實(shí)現(xiàn)自動(dòng)循環(huán)播放的banner的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下。2017-12-12
深入學(xué)習(xí)iOS7自定義導(dǎo)航轉(zhuǎn)場(chǎng)動(dòng)畫(huà)
這篇文章主要為大家詳細(xì)介紹了iOS7自定義導(dǎo)航轉(zhuǎn)場(chǎng)動(dòng)畫(huà)的相關(guān)資料,感興趣的小伙伴們可以參考一下2016-02-02
iOS利用Label實(shí)現(xiàn)的簡(jiǎn)單高性能標(biāo)簽TagView
這篇文章主要給大家介紹了關(guān)于iOS利用Label實(shí)現(xiàn)的簡(jiǎn)單高性能標(biāo)簽TagView的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2018-03-03

