iCloud服务

iCloud 是苹果提供的云端服务,用户可以将通讯录、备忘录、邮件、照片、音乐、视频等备份到云服务器并在各个苹果设备间直接进行共享而无需关心数据同步问题,甚至 即使你的设备丢失后在一台新的设备上也可以通过Apple ID登录同步。当然这些内容都是iOS内置的功能,那么对于开放者如何利用iCloud呢?苹果已经将云端存储功能开放给开发者,利用iCloud开发者 可以存储两类数据:用户文档和应用数据、应用配置项。前者主要用于一些用户文档、文件的存储,后者更类似于日常开放中的偏好设置,只是这些配置信息会同步 到云端。

要进行iCloud开发同样需要一些准备工作(下面的准备工作主要是针对真机的,模拟器省略Provisioning Profile配置过程):

1、 2步骤仍然是创建App ID启用iCloud服务、生成对应的配置(Provisioning Profile),这个过程中Bundle ID可以使用通配符(Data Protection、iCloud、Inter-App Audio、Passbook服务在创建App ID时其中的Bundle ID是可以使用通配ID的)。

3.在Xcode中创建项目(假设项目名称为“kctest”)并在项目的 Capabilities中找到iCloud并打开。这里需要注意的就是由于在此应用中要演示文档存储和首选项存储,因此在Service中勾选 “Key-value storae”和“iCloud Documents”:

在项目中会自动生成一个”kctest.entitlements”配置文件,这个文档配置了文档存储容器标识、键值对存储容器标识等信息。

4.无论是真机还是模拟器都必须在iOS“设置”中找到iCloud设置登录账户,注意这个账户不必是沙盒测试用户。

A.首先看一下如何进行文档存储。文档存储主要是使用UIDocument类来完成,这个类提供了新建、修改(其实在API中是覆盖操作)、查询文档、打开文档、删除文档的功能。

UIDocument 对文档的新增、修改、删除、读取全部基于一个云端URL来完成(事实上在开发过程中新增、修改只是一步简单的保存操作),对于开发者而言没有本地和云端之 分,这样大大简化了开发过程。这个URL可以通过NSFileManager的URLForUbiquityContainerIdentifier:方 法获取,identifier是云端存储容器的唯一标识,如果传入nil则代表第一个容器(事实上这个容器可以通过前面生成的 “kctest.entiements”中的Ubiquity Container Identifiers来获取。如上图可以看到这是一个数组,可以配置多个容器,例如我们的第一个容器标识是 “iCloud.$(CFBundleIdentifier)”,其中$(CFBundleIdentifier)是Bundle ID,那么根据应用的Bundle ID就可以得知第一个容器的标识是“iCloud.com.cmjstudio.kctest”。)。下面是常用的文档操作方法:

-(void)saveToURL:forSaveOperation:completionHandler::将指定URL的文档保存到iCloud(可以是新增或者覆盖,通过saveOperation参数设定)。

-(void)openWithCompletionHandler::打开当前文档。

注意:删除一个iCloud文档是使用NSFileManager的removeItemAtURL:error:方法来完成的。

由 于实际开发过程中数据的存储和读取情况是复杂的,因此UIDocument在设计时并没有提供统一的存储方式来保存数据,而是希望开发者自己继承 UIDocument类并重写-(id)contentsForType:(NSString *)typeName error:(NSError *__autoreleasing *)outError和-(BOOL)loadFromContents:(id)contents ofType:(NSString *)typeName error:(NSError *__autoreleasing *)outError方法来根据不同的文档类型自己来操作数据(contents)。这两个方法分别在保存文档 (-(void)saveToURL:forSaveOperation:completionHandler:)和打开文档 (-(void)openWithCompletionHandler:)时调用。通常在子类中会定义一个属性A来存储文档数据,当保存文档时,会通过 -(id)contentsForType:(NSString *)typeName error:(NSError *__autoreleasing *)outError方法将A转化为NSData或者NSFileWrapper(UIDocument保存数据的本质就是保存转化得到的NSData或 者NSFileWrapper);当打开文档时,会通过-(BOOL)loadFromContents:(id)contents ofType:(NSString *)typeName error:(NSError *__autoreleasing *)outError方法将云端下载的NSData或者NSFileWrapper数据转化为A对应类型的数据。为了方便演示下面简单定义一个继承自 UIDocument的KCDocument类,在其中定义一个data属性存储数据:

 1 //
2 // KCDocument.m
3 // kctest
4 //
5 // Created by Kenshin Cui on 14/4/5.
6 // Copyright (c) 2015年 cmjstudio. All rights reserved.
7 //
8 #import "KCDocument.h"
9 @interface KCDocument()
10 @end
11 @implementation KCDocument
12 #pragma mark - 重写父类方法
13 /**
14 * 保存时调用
15 *
16 * @param typeName
17 * @param outError
18 *
19 * @return
20 */
21 -(id)contentsForType:(NSString *)typeName error:(NSError *__autoreleasing *)outError{
22 if (self.data) {
23 return [self.data copy];
24 }
25 return [NSData data];
26 }
27 /**
28 * 读取数据时调用
29 *
30 * @param contents
31 * @param typeName
32 * @param outError
33 *
34 * @return
35 */
36 -(BOOL)loadFromContents:(id)contents ofType:(NSString *)typeName error:(NSError *__autoreleasing *)outError{
37 self.data=[contents copy];
38 return true;
39 }
40 @end

如 果要加载iCloud中的文档列表就需要使用另一个类NSMetadataQuery,通常考虑到网络的原因并不会一次性加载所有数据,而利用 NSMetadataQuery并指定searchScopes为NSMetadataQueryUbiquitousDocumentScope来限制 查找iCloud文档数据。使用NSMetadataQuery还可以通过谓词限制搜索关键字等信息,并在搜索完成之后通过通知的形式通知客户端搜索的情 况。

大家都知道微软的OneNote云笔记本软件,通过它可以实现多种不同设置间的笔记同步,这里就简单实现一个基于iCloud服务的 笔 记软件。在下面的程序中实现笔记的新增、修改、保存、读取等操作。程序界面大致如下,点击界面右上方增加按钮增加一个笔记,点击某个笔记可以查看并编辑。

在主视图控制器首先查询所有iCloud保存的文档并在查询通知中遍历查询结果保存文档名称和创建日期到UITableView展示;其次当用户点击了增加按钮会调用KCDocument完成文档添加并导航到文档详情界面编辑文档内容。

  1 //
2 // KCMainTableViewController.m
3 // kctest
4 //
5 // Created by Kenshin Cui on 14/4/5.
6 // Copyright (c) 2015年 cmjstudio. All rights reserved.
7 //
8 #import "KCMainTableViewController.h"
9 #import "KCDocument.h"
10 #import "KCDetailViewController.h"
11 #define kContainerIdentifier @"iCloud.com.cmjstudio.kctest" // 容器id,可以从生产的entitiements文件中查看Ubiquity Container Identifiers(注意其中 的$(CFBundleIdentifier)替换为BundleID)
12 @interface KCMainTableViewController ()
13 @property (strong,nonatomic) KCDocument *document;//当前选中的管理对象
14 @property (strong,nonatomic) NSMutableDictionary *files; //现有文件名、创建日期集合
15 @property (strong,nonatomic) NSMetadataQuery *dataQuery;//数据查询对象,用于查询iCloud文档
16 @end
17 @implementation KCMainTableViewController
18 #pragma mark - 控制器视图方法
19 - (void)viewDidLoad {
20 [super viewDidLoad];
21
22 [self loadDocuments];
23 }
24 #pragma mark - UI事件
25 //新建文档
26 - (IBAction)addDocumentClick:(UIBarButtonItem *)sender {
27 UIAlertController *promptController=[UIAlertController alertControllerWithTitle:@"KCTest" message:@"请输入笔记名称" preferredStyle:UIAlertControllerStyleAlert];
28 [promptController addTextFieldWithConfigurationHandler:^(UITextField *textField) {
29 textField.placeholder=@"笔记名称";
30 }];
31 UIAlertAction *okAction=[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
32 UITextField *textField= promptController.textFields[0];
33 [self addDocument:textField.text];
34 }];
35 [promptController addAction:okAction];
36 UIAlertAction *cancelAction=[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
37
38 }];
39 [promptController addAction:cancelAction];
40 [self presentViewController:promptController animated:YES completion:nil];
41 }
42 #pragma mark - 导航
43 - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
44 if ([segue.identifier isEqualToString:@"noteDetail"]) {
45 KCDetailViewController *detailController= segue.destinationViewController;
46 detailController.document=self.document;
47 }
48 }
49 #pragma mark - 属性
50 -(NSMetadataQuery *)dataQuery{
51 if (!_dataQuery) {
52 //创建一个iCloud查询对象
53 _dataQuery=[[NSMetadataQuery alloc]init];
54 _dataQuery.searchScopes=@[NSMetadataQueryUbiquitousDocumentsScope];
55 //注意查询状态是通过通知的形式告诉监听对象的
56 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(metadataQueryFinish:) name:NSMetadataQueryDidFinishGatheringNotification object:_dataQuery];//数据获取完成通知
57 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(metadataQueryFinish:) name:NSMetadataQueryDidUpdateNotification object:_dataQuery];//查询更新通知
58 }
59 return _dataQuery;
60 }
61 #pragma mark - 私有方法
62 /**
63 * 取得云端存储文件的地址
64 *
65 * @param fileName 文件名,如果文件名为nil则重新创建一个url
66 *
67 * @return 文件地址
68 */
69 -(NSURL *)getUbiquityFileURL:(NSString *)fileName{
70 //取得云端URL基地址(参数中传入nil则会默认获取第一个容器)
71 NSURL *url= [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:kContainerIdentifier];
72 //取得Documents目录
73 url=[url URLByAppendingPathComponent:@"Documents"];
74 //取得最终地址
75 url=[url URLByAppendingPathComponent:fileName];
76 return url;
77 }
78 /**
79 * 添加文档到iCloud
80 *
81 * @param fileName 文件名称(不包括后缀)
82 */
83 -(void)addDocument:(NSString *)fileName{
84 //取得保存URL
85 fileName=[NSString stringWithFormat:@"%@.txt",fileName];
86 NSURL *url=[self getUbiquityFileURL:fileName];
87
88 /**
89 创建云端文档操作对象
90 */
91 KCDocument *document= [[KCDocument alloc]initWithFileURL:url];
92 [document saveToURL:url forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success) {
93 if (success) {
94 NSLog(@"保存成功.");
95 [self loadDocuments];
96 [self.tableView reloadData];
97 self.document=document;
98 [self performSegueWithIdentifier:@"noteDetail" sender:self];
99 }else{
100 NSLog(@"保存失败.");
101 }
102
103 }];
104 }
105 /**
106 * 加载文档列表
107 */
108 -(void)loadDocuments{
109 [self.dataQuery startQuery];
110 }
111 /**
112 * 获取数据完成后的通知执行方法
113 *
114 * @param notification 通知对象
115 */
116 -(void)metadataQueryFinish:(NSNotification *)notification{
117 NSLog(@"数据获取成功!");
118 NSArray *items=self.dataQuery.results;//查询结果集
119 self.files=[NSMutableDictionary dictionary];
120 //变量结果集,存储文件名称、创建日期
121 [items enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
122 NSMetadataItem *item=obj;
123 NSString *fileName=[item valueForAttribute:NSMetadataItemFSNameKey];
124 NSDate *date=[item valueForAttribute:NSMetadataItemFSContentChangeDateKey];
125 NSDateFormatter *dateformate=[[NSDateFormatter alloc]init];
126 dateformate.dateFormat=@"YY-MM-dd HH:mm";
127 NSString *dateString= [dateformate stringFromDate:date];
128 [self.files setObject:dateString forKey:fileName];
129 }];
130 [self.tableView reloadData];
131 }
132 -(void)removeDocument:(NSString *)fileName{
133 NSURL *url=[self getUbiquityFileURL:fileName];
134 NSError *error=nil;
135 //删除文件
136 [[NSFileManager defaultManager] removeItemAtURL:url error:&error];
137 if (error) {
138 NSLog(@"删除文档过程中发生错误,错误信息:%@",error.localizedDescription);
139 }
140 [self.files removeObjectForKey:fileName];//从集合中删除
141 }
142 #pragma mark - Table view data source
143 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
144 return 1;
145 }
146 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
147 return self.files.count;
148 }
149 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
150 static NSString *identtityKey=@"myTableViewCellIdentityKey1";
151 UITableViewCell *cell=[self.tableView dequeueReusableCellWithIdentifier:identtityKey];
152 if(cell==nil){
153 cell=[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:identtityKey];
154 cell.accessoryType=UITableViewCellAccessoryDisclosureIndicator;
155 }
156 NSArray *fileNames=self.files.allKeys;
157 NSString *fileName=fileNames[indexPath.row];
158 cell.textLabel.text=fileName;
159 cell.detailTextLabel.text=[self.files valueForKey:fileName];
160 return cell;
161 }
162 - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
163 if (editingStyle == UITableViewCellEditingStyleDelete) {
164 UITableViewCell *cell=[self.tableView cellForRowAtIndexPath:indexPath];
165 [self removeDocument:cell.textLabel.text];
166 [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
167 } else if (editingStyle == UITableViewCellEditingStyleInsert) {
168 // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
169 }
170 }
171 #pragma mark - UITableView 代理方法
172 -(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
173 UITableViewCell *cell=[self.tableView cellForRowAtIndexPath:indexPath];
174 NSURL *url=[self getUbiquityFileURL:cell.textLabel.text];
175 self.document=[[KCDocument alloc]initWithFileURL:url];
176 [self performSegueWithIdentifier:@"noteDetail" sender:self];
177 }
178 @end

当新增一个笔记或选择一个已存在的笔记后可以查看、保存笔记内容。

 1 /
2 // ViewController.m
3 // kctest
4 //
5 // Created by Kenshin Cui on 14/4/5.
6 // Copyright (c) 2015年 cmjstudio. All rights reserved.
7 //
8 #import "KCDetailViewController.h"
9 #import "KCDocument.h"
10 #define kSettingAutoSave @"com.cmjstudio.kctest.settings.autosave"
11 @interface KCDetailViewController ()
12 @property (weak, nonatomic) IBOutlet UITextView *textView;
13 @end
14 @implementation KCDetailViewController
15 #pragma mark - 控制器视图方法
16 - (void)viewDidLoad {
17 [super viewDidLoad];
18 [self setupUI];
19 }
20 -(void)viewWillDisappear:(BOOL)animated{
21 [super viewWillDisappear:animated];
22 //根据首选项来确定离开当前控制器视图是否自动保存
23 BOOL autoSave=[[NSUbiquitousKeyValueStore defaultStore] boolForKey:kSettingAutoSave];
24 if (autoSave) {
25 [self saveDocument];
26 }
27 }
28 #pragma mark - 私有方法
29 -(void)setupUI{
30 UIBarButtonItem *rightButtonItem=[[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemSave target:self action:@selector(saveDocument)];
31 self.navigationItem.rightBarButtonItem=rightButtonItem;
32
33 if (self.document) {
34 //打开文档,读取文档
35 [self.document openWithCompletionHandler:^(BOOL success) {
36 if(success){
37 NSLog(@"读取数据成功.");
38 NSString *dataText=[[NSString alloc]initWithData:self.document.data encoding:NSUTF8StringEncoding];
39 self.textView.text=dataText;
40 }else{
41 NSLog(@"读取数据失败.");
42 }
43 }];
44 }
45 }
46 /**
47 * 保存文档
48 */
49 -(void)saveDocument{
50 if (self.document) {
51 NSString *dataText=self.textView.text;
52 NSData *data=[dataText dataUsingEncoding:NSUTF8StringEncoding];
53 self.document.data=data;
54 [self.document saveToURL:self.document.fileURL forSaveOperation:UIDocumentSaveForOverwriting completionHandler:^(BOOL success) {
55 NSLog(@"保存成功!");
56 }];
57 }
58 }
59 @end

到 目前为止都是关于如何使用iCloud来保存文档的内容,上面也提到过还可以使用iCloud来保存首选项,这在很多情况下通常很有用,特别是对于开发了 iPhone版又开发了iPad版的应用,如果用户在一台设备上进行了首选项配置之后到另一台设备上也能使用是多么优秀的体验啊。相比文档存储,首选项存 储要简单的多,在上面“kctest.entitlements”中可以看到首选项配置并非像文档一样可以包含多个容器,这里只有一个Key-Value Store,通常使用NSUbiquitousKeyValueStore的defaultStore来获取,它的使用方法和 NSUserDefaults几乎完全一样,当键值对存储发生变化后可以通过 NSUbiquitousKeyValueStoreDidChangeExternallyNotification等获得对应的通知。在上面的笔记应 用中有一个”设置“按钮用于设置退出笔记详情视图后是否自动保存,这个选项就是通过iCloud的首选项来存储的。

 1 //  KCSettingTableViewController.m
2 // kctest
3 //
4 // Created by Kenshin Cui on 14/4/5.
5 // Copyright (c) 2015年 cmjstudio. All rights reserved.
6 //
7 #import "KCSettingTableViewController.h"
8 #define kSettingAutoSave @"com.cmjstudio.kctest.settings.autosave"
9 @interface KCSettingTableViewController ()
10 @property (weak, nonatomic) IBOutlet UISwitch *autoSaveSetting;
11 @end
12 @implementation KCSettingTableViewController
13 - (void)viewDidLoad {
14 [super viewDidLoad];
15 [self setupUI];
16 }
17 #pragma mark - UI事件
18 - (IBAction)autoSaveClick:(UISwitch *)sender {
19 [self setSetting:sender.on];
20 }
21 #pragma mark - 私有方法
22 -(void)setupUI{
23 //设置iCloud中的首选项值
24 NSUbiquitousKeyValueStore *defaults=[NSUbiquitousKeyValueStore defaultStore];
25 self.autoSaveSetting.on= [defaults boolForKey:kSettingAutoSave];
26 //添加存储变化通知
27 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(
28 keyValueStoreChange:) name:NSUbiquitousKeyValueStoreDidChangeExternallyNotification object:defaults];
29 }
30 /**
31 * key-value store发生变化或存储空间不足
32 *
33 * @param notification 通知对象
34 */
35 -(void)keyValueStoreChange:(NSNotification *)notification{
36 NSLog(@"Key-value store change...");
37 }
38 /**
39 * 设置首选项
40 *
41 * @param value 是否自动保存
42 */
43 -(void)setSetting:(BOOL)value{
44 //iCloud首选项设置
45 NSUbiquitousKeyValueStore *defaults=[NSUbiquitousKeyValueStore defaultStore];
46 [defaults setBool:value forKey:kSettingAutoSave];
47 [defaults synchronize];//同步
48 }
49 @end

运行效果:

注意:所有的存储到iCloud的文档、首选项都是首先存储到本地,然后通过daemon进程同步到iCloud的,保存、读取的文件都是本地同步副本并不一定是真实的iCloud存储文件。

iOS开发——高级技术&iCloud服务的更多相关文章

  1. iOS开发——高级技术&蓝牙服务

    蓝牙服务 蓝牙 随着蓝牙低功耗技术BLE(Bluetooth Low Energy)的发展,蓝牙技术正在一步步成熟,如今的大部分移动设备都配备有蓝牙4.0,相比之前的蓝牙技术耗电量大大降低.从iOS的 ...

  2. iOS开发——高级技术&PassBook服务

    PassBook服务 Passbook是苹果推出的一个管理登机牌.会员卡.电影票.优惠券等信息的 工具.Passbook就像一个卡包,用于存放你的购物卡.积分卡.电影票.礼品卡等,而这些票据就是一个“ ...

  3. iOS开发——高级技术&通讯录服务

    通讯录服务 AddressBook iOS中带有一 个Contacts应用程序来管理联系人,但是有些时候我们希望自己的应用能够访问或者修改这些信息,这个时候就要用到 AddressBook.frame ...

  4. iOS开发——高级技术&社交服务

    社交服务 Social 现 在很多应用都内置“社交分享”功能,可以将看到的新闻.博客.广告等内容分享到微博.微信.QQ.空间等,其实从iOS6.0开始苹果官方就内置了 Social.framework ...

  5. iOS开发——高级技术&GameCenter服务

    GameCenter服务 Game Center是由苹果发布的在线多人游戏社交网络,通过它游戏玩家可以邀请好友进行多人游戏,它也会记录玩家的成绩并在排行榜中展示,同时玩家每经过一定 的阶段会获得不同的 ...

  6. iOS开发——高级技术&内购服务

    内购服务 大家都知道做iOS开发本身的收入有三种来源:出售应用.内购和广告.国内用户通常很少直接 购买应用,因此对于开发者而言(特别是个人开发者),内购和广告收入就成了主要的收入来源.内购营销模式,通 ...

  7. iOS开发——高级技术OC篇&运行时(Runtime)机制

    运行时(Runtime)机制 本文将会以笔者个人的小小研究为例总结一下关于iOS开发中运行时的使用和常用方法的介绍,关于跟多运行时相关技术请查看笔者之前写的运行时高级用法及相关语法或者查看响应官方文档 ...

  8. iOS开发——高级技术精选OC篇&Runtime之字典转模型实战

    Runtime之字典转模型实战 如果您还不知道什么是runtime,那么请先看看这几篇文章: http://www.cnblogs.com/iCocos/p/4734687.html http://w ...

  9. iOS开发——高级技术&广告服务

    广告服务 上 面也提到做iOS开发另一收益来源就是广告,在iOS上有很多广告服务可以集成,使用比较多的就是苹果的iAd.谷歌的Admob,下面简单演示一下如何 使用iAd来集成广告.使用iAd集成广告 ...

随机推荐

  1. 极客DIY:使用树莓派制作一套“NAS+私有云盘+下载机”

    原创作者:HackLiu 0×00 前言 ‍ ‍ 如果你家里有多台设备需要联网需要娱乐,你一定会或多或少遇到设备碎片化带来的烦恼.当然,已经有很多厂商包括新晋的小米.360在内的互联网公司做了这个事情 ...

  2. [整理][LaTex]小技巧之——首行缩进

    0. 简介 在LaTex编辑时,有时会遇到这样一个有关于首行缩进的问题.在汉语环境的编辑下,习惯上每段会进行一个两个字的缩进.但是在默认编辑模式下,一个章节下的首段是没有首行缩进的,本文的目的主要是解 ...

  3. 项目Windows服务安装命令:

    sc create YY.SmsPlatform.RemoteDataCenter binPath= "E:\YY.SmsPlatform\YY.SmsPlatform.RemoteData ...

  4. Selenium2+python自动化15-select下拉框

    前言 最近由于工作原因,更新慢了一点,今天终于抽出一点时间给大家继续更新selenium系列,学习的脚本不能停止,希望小伙伴能多多支持. 本篇以百度设置下拉选项框为案例,详细介绍select下拉框相关 ...

  5. python在不同层级目录import模块的方法

    使用python进行程序编写时,经常会使用第三方模块包.这种包我们可以通过python setup install 进行安装后,通过import XXX或from XXX import yyy 进行导 ...

  6. DP总结

    最长回文子序列 int lpsDp(char * str,int n){ int dp[n][n], tmp; memset(dp,0,sizeof(dp)); for(int i=0; i<n ...

  7. 快速排序(java实现)

    快速排序 算法思想:基于分治的思想,是冒泡排序的改进型.首先在数组中选择一个基准点(该基准点的选取可能影响快速排序的效率,后面讲解选取的方法),然后分别从数组的两端扫描数组,设两个指示标志(lo指向起 ...

  8. Java如何将html转以后的字符转化成正常显示的字符

    String str = "“!@#¥%……&——+”";//“!@#¥%……&——+”  中文状态下的标点符号,进过html转换了 String convStr ...

  9. IOS 进度条与手势

    //进度条#import "ViewController.h" @interface ViewController () { UIImageView* _animaImageV; ...

  10. c# 身份证证号验证方法

    #region 验证身份证是否有效        /// <summary>        /// 验证身份证是否有效        /// </summary>        ...