刚开始接到这个需求的时候第一感觉就是做不到,怎么可能把自己APP内的账号密码填充到其他APP登录的输入框内,但是客户找出了类似的APP说是别人的APP是可以的,相信你也可以。这时我就有些没有头绪了,我在网上找资料,可是无果。最后拿出我的神器,用谷歌搜,刚开始搜的也是一些没有用的。但是随后还是找到了一些资料。都是一些零零散散的。而且都是一些英文的文档,我一边翻译一边看,还是没有头绪。我想着这是在APP以外用到的,不会启动APP,所以我就想到了用APP拓展。我就按照APP拓展的方式去打开果然真的有账号密码填充。
这里就不多说了,新建完之后有一个文件夹,里面有一个CredentialProviderViewController控制器和一个MainInterface.storyboard,这两个类就是应用拓展的入口,入口也是可以改变的需要在info.plist里面
一般来说在设置点击的时候是需要验证一下,此应用的密码,或者是指纹之类的。但是如果点击了设置里面的选项,弹出APP拓展的验证,这时取消验证,设置里面的选项还是被勾选的,不能被取消。如果读者有更好的方法,可以在下面留言,可以相互学习一下。
接下来先简单的介绍一下CredentialProviderViewController.m里的
- (void)prepareCredentialListForServiceIdentifiers:(NSArray<ASCredentialServiceIdentifier *> *)serviceIdentifiers
这个是如果输入框设置为苹果的账号类型就会有返回,这个方法进入之后就会走这个方法。展示Credentials List让用户选择,系统会触发该方法,并传入serviceIdentifiers数组,以便用户过滤或者对数据排序。如果serviceIdentifiers数组存在多个,那么越靠前的数据价值越大。当然数组也可能是空的。
- (void)provideCredentialWithoutUserInteractionForIdentity:(ASPasswordCredentialIdentity *)credentialIdentity;
这个方法会被触发是点击键盘上面的账号密码,这个账号密码如何显示到键盘上,需要存储到ASCredentialIdentityStore里面,我是在点击具体的密码返回到上一界面的时候
ASPasswordCredentialIdentity * credent = [[ASPasswordCredentialIdentity alloc] initWithServiceIdentifier:self.service
user:accout
recordIdentifier:nil];
[[ASCredentialIdentityStore sharedStore] saveCredentialIdentities:@[credent]
completion:^(BOOL success, NSError * _Nullable error) {
NSLog(@"%@", error);
}];
self.service是prepareCredentialListForServiceIdentifiers:方法返回的,这里会有问题,可以自己创建一个ASCredentialServiceIdentifier类型的对象进行存储。如果用户可信则直接返回数据,否则可以触发ASExtensionErrorCodeUserInteractionRequest让用户进行身份验证。该方法触发时ViewController并没有展示,所以不要做任何的UI操作。
- (void)prepareInterfaceToProvideCredentialForIdentity:(ASPasswordCredentialIdentity *)credentialIdentity;
该方法是验证,比如提供一个解锁页面,当用户输入密码正确则调用[ASCredentialProviderExtensionContext completeRequestWithSelectedCredential:completionHandler:]对外提供数据;如果输入错误,则调用[ASCredentialProviderExtensionContext cancelRequestWithError:]错误类型选用ASExtensionErroCode中的ASExtensionErroDomain,如果Extension无法为外部提供数据则选用ASExtensionErrorCodeCredentialIdentityNotFound。
- (void)prepareInterfaceForExtensionConfiguration;
系统Setting打开Extension时触发。这时会展示ViewController。该方法触发需要配置。
走到这里基本上完成了百分之50。有一个最重要的还没有解决,就是要读取主APP的数据,APP拓展的数据跟主APP的数据是独立的。所以这里就需要的用到APP GROUP https://blog.csdn.net/allangold/article/details/54890555这里介绍的很全面,我这里就不细说了。
我在这里遇到了一个问题,就是主APP中的数据是存储在数据库里面。需要把这些数据存储到共享的空间当中。我的数据库文件是个.db文件。所以我在初始化数据库的时候直接把数据库copy到共享空间,其他的在那个博客里面也写到,这里就不多做解释
- (BOOL)saveDataFromPath:(NSString *)originPath toFile:(NSString *)filename
{
NSURL *url = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"这里是共享空间的ID"];
NSURL *fileURL = [url URLByAppendingPathComponent:filename];
NSFileManager *fileManager =[NSFileManager defaultManager];
return [[NSFileManager defaultManager] copyItemAtPath:originPath toPath:[fileURL path] error:nil];
}
用这个方法
NSURL *url = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:@"这里是共享空间的ID"];
NSURL *fileURL = [url URLByAppendingPathComponent:@"mypass.db"];
_queue = [FMDatabaseQueue databaseQueueWithPath:fileURL.path];
到这里大部分的工作做得差不多了。第一次写写文章,有些地方写的不是很全面。也有些落下的可以多多指正。逻辑可能有些乱,不动的可以留言,或者加我wx: jiangdong00000000,大家共同学习,一起进步,谢谢