测试已测试 | ✗ |
语言语言 | Obj-CObjective C |
许可证 | MIT |
发布最新发布 | 2014年12月 |
由Alex Novosad维护。
依赖关系 | |
Mantle | < 2.0 |
Reachability | ~> 3.1 |
如果您觉得这很酷,请分享/收藏/发送爱心 - 这样做的唯一目的是提高平均用户iOS体验,而这完全取决于有多少第三方开发者实施此功能。 <3 Twitter: @choosyios.
Choosy是一个让您的用户在您发送他们到Twitter链接/编辑视图/网页链接/地图地址等时选择他们最喜欢的Twitter/Email/浏览器/地图等应用的超简单方法。但它不仅限于这些类别;它与暴露URL方案的所有应用一起工作。
例如,使用Choosy您可以写一行代码
- (void)viewDidLoad:
{
self.choosy = [Choosy new];
[self.choosy registerUIElement:self.myTwitterButton
forAction:[ChoosyActionContext actionContextWithAppType:@"Twitter"
action:@"show_profile"
parameters:@{@"profile_screenname" : @"KarlTheFog",
@"callback_url" : @"yourappurl:"]];
}
来为流行的Twitter客户端获取自动支持
点击此处查看Choosy执行的动作的gif。截图来自包含的演示应用。
以前,您必须为要支持的应用编写特定的代码。有了Choosy,您只需传递一次通用参数,就可以为所有应用获取支持。Choosy检测已安装的应用,并知道每个应用支持哪些参数,只将支持的参数传递给每个应用。
(点击此处查看显示“选择默认应用”手势的gif。) }
要查看支持的URL方案或做出URL方案贡献,请查看choosy-data。
要运行演示应用,请克隆此仓库,并在此Podfile所在目录中运行pod update
。完成后,打开.xcworkspace
文件(不是项目文件)。它应该能够构建并部署到您的设备上。
注意:在模拟器中运行:由于模拟器中几乎没有应用(并且您不能安装任何应用),在模拟器中查看Choosy的操作很困难。因此,链接通常会启动已安装的一个应用。但是,您可以长时间按住链接来强制UI出现。
将此添加到您项目Podfile中
pod 'Choosy', '< 2.0'
如果您尚未使用CocoaPods,请从遵循该指南开始(除了将pod 'AFNetworking' ...
替换为上面的行)。
使用Choosy就像在视图控制器中导入Choosy.h
头文件一样简单,声明一个属性来持有对象。
@property (nonatomic) Choosy *choosy;
然后注册一个UI组件,例如链接到某人Twitter资料的UIButton。
- (void)viewDidLoad:
{
self.choosy = [Choosy new];
[self.choosy registerUIElement:self.elonMuskTwitterButton
forAction:[ChoosyActionContext actionContextWithAppType:@"Twitter"
action:@"show_profile"
parameters:@{ @"profile_screenname" : @"elonmusk"]];
}
默认情况下,Choosy将为按钮附加单击和长按手势识别器。单击时如果未选择喜欢的应用,则向用户呈现应用选择;否则,启动喜欢的应用。长按允许用户重置喜欢的应用设置,再次从已安装的应用中挑选。
当然,您可能希望在单击或长按时执行自己的代码。在这种情况下,首先注册您打算使用的所有应用类型
- (void)viewDidLoad
{
...
[Choosy registerAppTypes:@[@"Twitter"]];
}
然后,在您的单击手势处理代码之后,明确告诉Choosy开始工作
[self.choosy handleAction:[ChoosyActionContext actionContextWithAppType:@"Twitter"
action:@"show_profile"
parameters:@{ @"profile_screenname" : @"elonmusk"]];
在您的长按手势处理代码之后,您需要调用不同的方法
[self.choosy resetAppSelectionAndHandleAction:[ChoosyActionContext actionContextWithAppType:@"Twitter"
action:@"show_profile"
parameters:@{ @"profile_screenname" : @"elonmusk"]];
这将重置Twitter应用类型的默认应用选择,并显示应用选择界面。
Choosy第一次了解某个应用类型时,它会去下载有关该应用类型的信息。在任何可靠的网络连接下,这几乎是瞬间的,数据在初始下载后将被缓存,但是如果新用户正在体验慢速连接怎么办?因此,最好尽早在应用生命周期中告诉Choosy您将链接到的所有各种应用类型的详细信息,例如在应用代理中。这将不会阻塞主线程
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
...
[Choosy registerAppTypes:@[@"Twitter", @"Email", @"Browser", @"Maps"]];
return YES;
}
这样,当您的用户打开例如具有Twitter链接的屏幕时,Choosy将已接收到关于Twitter应用类型和应用程序的信息,检查哪些应用已安装,并为已安装的应用程序下载图标。
您可以根据需要混合使用registerUiElement:forAction:
和handleAction:
调用。只需记住,registerUiElement:forAction:
会注册UI元素的双重操作(单击和长按)。所以,如果您在手动处理其中一种手势并调用任一handleAction:
或resetAppSelectionAndHandleAction:
,则需要同时覆盖另一种手势,并在那里调用另一个方法。很容易忘记处理长按,从而让用户没有重置默认设置的权限!
使用ChoosyActionContext
对象传递您想要执行的所有操作的信息。我们在这里所说的“操作”也可以被视作“外部链接”,因为您实际上正在打开(链接)外部应用。我们更喜欢使用“操作”这个词有两个原因。一方面,通常不仅仅是链接到一个应用,而是希望使用它执行某些操作,例如显示特定的Twitter资料。另一方面,我们有计划实现一些长期功能,这些功能不止是打开应用;)
对于原生应用,您可以使用任一actionContextWithAppType...
便捷初始化器。如果您通过actionContextWithAppType:
只传递应用类型,Choosy将显示该类型的应用并直接打开它们,不传递任何参数。
让我们看看最复杂的初始化器
+ (instancetype)actionContextWithAppType:(NSString *)appTypeKey
action:(NSString *)actionKey
parameters:(NSDictionary *)parameters
appPickerTitle:(NSString *)appPickerTitle;
appTypeKey
是一个类似于 @"Twitter"
、@"Email"
、@"Browser"
、@"Maps"
、@"Music"
、@"RSS"
、@"Contacts"
、@"Weather"
等的字符串。actionKey
是一个类似 @"show_profile"
、@"compose"
、@"directions"
、@"browse"
的字符串。parameters
是该操作的参数列表。无应用特定性意味着所有键都是 Choosy 特定的,尽管我们尽可能地利用最普遍的应用的 URL 方案。例如,我们一些关于 Twitter 操作的参数名称和 Tweetbot 的一致,但这只是因为我们喜欢他们的名称,并且他们有着最好的文档化的 URL 方案 :) appPickerTitle
是要在 Choosy UI 顶部显示的文本。这是可选的;如果您想覆盖默认值,请使用它。目前,默认文本只是应用的类型名称,但我们计划在不久的将来让它变得更智能,例如显示请求的操作名称甚至与操作相关的某些关键参数值,例如即将打开的个人资料的工具提示。
您要做的是传递所有您在最理想情况下所需的参数。例如,即使您不确定是否有任何应用支持,也要包含回调 URL。Choosy 将处理为不支持这些参数的应用跳过参数。
第一次将 Choosy 连接起来时,您可能会觉得这是一种黑魔法。您编写了一行代码,砰!您的应用支持链接到所有主要的 Twitter 客户端 并且 用户可以选择他们最喜欢的应用!它是怎么知道所有应用的?它是怎么立即知道当用户删除应用或安装新应用时?(哦-剧透警告!)
这个概念非常简单-结合一个知道所有应用的网页服务以及下载这些信息并调用每个应用的 UIApplication.canOpenURL
的客户端代码来创建一个已安装应用的列表。添加一些多线程、缓存、图标下载、默认 UI、选择默认应用的能力以及记住之前安装的应用列表以便知道何时出现新应用,您就得到了 Choosy。
Choosy 内置的数据涵盖了所有支持的内置应用以及与内置服务(邮件、Safari、地图、Twitter 等)相关的应用。这意味着 Choosy 至少和今天的 URL 一样好使用,无需连接;所以如果点击了一个网页链接,Choosy 将只打开 Safari。也就是说,最坏的行为和在 Choosy 不存在时一样。然而,当下载附加数据并且安装了多个给定应用类型的应用时,Choosy 允许用户选择应用。
交互
对于测试,您可以在
ChoosyGlobals.h
文件中将CHOOSY_ALWAYS_DISPLAY_PICKER
标志设置为 1 - 这确保了每次都会打开 UI,不受(即使默认应用设置了)约束。确保在发布之前将其设置回 0!
目前,Choosy只在缓存超过24小时或者CHOOSY_DEVELOPMENT_MODE
标志设置为1时检查新数据。缓存期度在未来可能可配置。
为了尽可能减少您需要编写的代码行数,Choosy在自身更新方面是完全自动的。每次您使用Choosy注册一个应用程序类型或一个UI元素时,它就会启动一个更新过程。但是,即使您同时注册了多个Twitter链接,Choosy也只会下载一次Twitter应用程序类型数据。它将以类似的方式为同一应用程序仅下载一次应用图标,无论应用程序属于多少个类型(例如,Safari既是浏览器又是Twitter应用程序类型的一部分)。如果连接断开,Choosy将在重新建立连接后继续下载。
对于测试,您可以方便地将
ChoosyGlobals.h
中的CHOOSY_DEVELOPMENT_MODE
标志设置为1,这样Choosy将忽略缓存期度,并在应用程序启动时(确切地说是每次通过registerAppTypes:
或registerUIElement:
指定应用程序类型时)尝试下载最新URL方案。
Choosy是为未越狱的设备打造的。因此,它受应用程序沙盒规则所限制。在我们找到解决方案之前,用户的默认设置以每个应用程序为基础存储。如果在您的应用程序中他们选择了Tweetbot作为默认的Twitter客户端,他们将在另一个应用程序中再次选择它作为默认设置。这是我们希望实现最干净、最简单的UI和操作的一个主要原因;如果用户需要多次(可能)选择默认应用程序,那么这个过程应该尽可能无痛和一致。
同样由于沙盒限制,Choosy必须在实现它的每个应用程序中存储一组应用程序图标。我们确实尝试成为勤奋的iOS公民,并将所有图标(和其他应用程序的所有信息)保存在Cache文件夹中。所以如果手机空间不足的情况发生,我们可以安心入睡,因为我们没有对这个问题的发生做出实质性的贡献。
我们来看看iOS 8是否能缓解我们的数据共享问题!:)
我们有一个包含代码的简短视频。有关受支持的应用程序、动作和参数的原始、最新信息,请查看choosy-data仓库。我们希望在1.0版之前上线一个能够基于原始文件自动生成文档的网站。
更多示例将很快出现在本节中!
默认UI遵循Apple的美学,一致性是金(有时多达1400亿美元的黄金价值)。当这种框架在整个应用程序中工作方式一时非常有用。所以如果您提出了一种具有更好操作等的UI - 请提交一个pull请求或只是联系我们交流想法。
但是如果您迫不及待要开发自己的UI,你可以完全这样做。只是确保根据ChoosyPickerDelegate
在应用程序被选中等情况下通知Choosy。实现可以有多种形式,但这里是一个示例实现的框架
创建您的自定义UI视图控制器。头文件
#import "ChoosyPickerDelegate.h"
@interface MyCustomAppPickerViewController : UIViewController
@property (nonatomic, weak) id<ChoosyPickerDelegate> delegate;
@property (nonatomic) ChoosyPickerViewModel *choosyViewModel;
@end
实现文件
@implementation MyCustomAppPickerViewController
...
// let's say you have these methods hooked up to gesture recognizers
// and you're using collection view with MyAppCell objects to represent each cell
- (void)appTapped:(UITapGestureRecognizer *)gesture
{
MyAppCell *cell = (MyAppCell *)gesture.view;
NSString *appKey = cell.appKey;
[self.delegate didSelectApp:appKey];
}
- (void)appLongPressed:(UILongPressGestureRecognizer *)gesture
{
MyAppCell *cell = (MyAppCell *)gesture.view;
NSString *appKey = cell.appKey;
switch (gesture.state) {
case UIGestureRecognizerStateBegan:
[self.delegate didSelectDefaultApp:appKey];
break;
default:
break;
}
}
- (void)viewTapped:(UITapGestureRecognizer *)gesture
{
CGPoint point = [gesture locationInView:self.view];
// the tappedOutsideOfAppPickerVisibleArea method is up to you to implement
// you can also add a swipe down gesture that also calls `didRequestPickerDismissal`, like the default UI has
if ([self tappedOutsideOfAppPickerVisibleArea: point]) {
[self.delegate didRequestPickerDismissal];
}
}
@end
使视图控制器负责显示自定义应用选择器用户界面,实现 ChoosyDelegate
,将该视图控制器设置为它拥有的Choosy实例的代理,并实现 showCustomChoosyPickerWithModel:
#import "Choosy.h"
#import "MyCustomAppPickerViewController.h"
@interface MyViewController () <ChoosyDelegate, MyCustomAppPickerDelegate>
@property (nonatomic) Choosy *choosy;
@property (nonatomic) MyCustomAppPickerViewController *appPicker;
@end
@implementation MyViewController()
- (void)viewDidLoad
{
self.choosy = [Choosy new];
self.choosy.delegate = self;
...
}
#pragma mark ChoosyDelegate
- (void)showCustomChoosyPickerWithModel:(ChoosyPickerViewModel *)viewModel
{
self.appPicker = [MyCustomAppPickerViewController new];
appPicker.delegate = self;
[self presentViewController:appPicker];
...
}
#pragma mark ChoosyPickerDelegate
- (void)didSelectAppWithKey:(NSString *)appKey
{
[self.appPicker dismissViewControllerAnimated:YES completion:^{
[self.choosy didSelectApp:appKey];
}];
}
- (void)didSelectDefaultAppWithKey:(NSString *)appKey
{
[self.appPicker dismissViewControllerAnimated:YES completion:^{
[self.choosy didSelectDefaultApp:appKey];
}];
}
- (void)didRequestPickerDismissal
{
// just dismiss the app picker
// no need to notify Choosy since we're handling the UI part manually
[self.appPicker dismissViewControllerAnimated:YES completion:nil];
}
@end
Choosy可以在WebView内的链接上工作,无论您的应用是否只是托管WebView,或者完全基于WebView的应用。然而,UIWebView
不会在长按链接时通知任何人;因此,在处理WebView链接时,您应该禁用默认的应用选择功能
self.choosy.allowsDefaultAppSelection = NO;
更多内容将很快介绍...
即将推出
ChoosyActionContext
对象的支持月亮射击
要了解新版本和API更改,请关注Twitter上的@choosyios。
我们非常希望能够帮助您实现上述路线图!我们知道您非常出色。
代码审评、Pull请求和想法非常受欢迎!让我们使本机应用程序间链接尽可能简单,至少是在第三方应用中。您也可以通过以下链接与我们联系:[email protected]。
对Choosy的成功至关重要的是URL方案数据库。您可以通过向choosy-data存储库提交Pull请求来贡献新的URL方案或为现有的URL方案添加更多操作/参数。