Lau*_*Fan 46 ios ios8 ios-app-extension
我添加以下代码:
- (IBAction)done {
// Return any edited content to the host app.
// This template doesn't do anything, so we just echo the passed in items.
NSURL *url = [NSURL URLWithString:@"lister://today"];
[self.extensionContext openURL:url completionHandler:^(BOOL success) {
NSLog(@"fun=%s after completion. success=%d", __func__, success);
}];
[self.extensionContext completeRequestReturningItems:self.extensionContext.inputItems completionHandler:nil];
}
Run Code Online (Sandbox Code Playgroud)
在我创建Action Extension目标之后.但它无法奏效.
我的目的是:当用户在Photos.app(iOS的默认Photos.app或被调用的图库)中查看照片时,他点击分享按钮以启动我们的扩展视图.我们可以将Photos.app中的图像传输到我自己的应用程序,并在我的应用程序中处理或上传图像.
我也尝试"CFBundleDocumentTypes"但它也无法工作.
任何帮助将不胜感激.
Jul*_*lon 42
这就是我以前做的事情:
UIWebView * webView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 0, 0)];
NSString *urlString = @"https://itunes.apple.com/us/app/watuu/id304697459";
NSString * content = [NSString stringWithFormat : @"<head><meta http-equiv='refresh' content='0; URL=%@'></head>", urlString];
[webView loadHTMLString:content baseURL:nil];
[self.view addSubview:webView];
[webView performSelector:@selector(removeFromSuperview) withObject:nil afterDelay:2.0];
Run Code Online (Sandbox Code Playgroud)
请注意,在这种情况下,我将从UIInputViewController实例化此调用.
此方法还应使用包含应用程序中的URL方案
更新2015年4月17日:这不适用于iOS 8.3.我们正在寻找解决方案,我们会尽快更新答案
更新06/01/2015:我们找到了适用于iOS 8.3的解决方案
var responder = self as UIResponder?
while (responder != nil){
if responder!.respondsToSelector(Selector("openURL:")) == true{
responder!.callSelector(Selector("openURL:"), object: url, delay: 0)
}
responder = responder!.nextResponder()
}
Run Code Online (Sandbox Code Playgroud)
这将找到一个合适的响应者来发送openURL.
您需要添加此扩展来替换swift的performSelector并帮助构建机制:
extension NSObject {
func callSelector(selector: Selector, object: AnyObject?, delay: NSTimeInterval) {
let delay = delay * Double(NSEC_PER_SEC)
let time = dispatch_time(DISPATCH_TIME_NOW, Int64(delay))
dispatch_after(time, dispatch_get_main_queue(), {
NSThread.detachNewThreadSelector(selector, toTarget:self, withObject: object)
})
}
}
Run Code Online (Sandbox Code Playgroud)
更新2015年6月15日:Objective-C
有人要求Objective-C中的代码,所以在这里.我不打算运行它,因为我现在没有时间,但它应该非常简单:
UIResponder *responder = self;
while(responder){
if ([responder respondsToSelector: @selector(OpenURL:)]){
[responder performSelector: @selector(OpenURL:) withObject: [NSURL URLWithString:@"www.google.com" ]];
}
responder = [responder nextResponder];
}
Run Code Online (Sandbox Code Playgroud)
如上所述,我没有运行这个Objective-C代码,它只是从Swift代码转换而来.如果您遇到任何问题和解决方案,请告诉我,我会更新.如今,我只是使用swift,不幸的是我的大脑正在弃用Objective-C
更新05/02/2016:不推荐使用的功能
正如@KyleKIM指出的那样,Selector函数已经被#selector替换为Swift 2.2.此外,还有一个已弃用的功能,可能会在Swift 3.0中删除,所以我正在做一些研究以找到替代方案.
更新2016年9月16日:XCode 8,Swift 3.0和iOS10 以下代码仍在处理上述版本.你会得到一些警告:
let url = NSURL(string:urlString)
let context = NSExtensionContext()
context.open(url! as URL, completionHandler: nil)
var responder = self as UIResponder?
while (responder != nil){
if responder?.responds(to: Selector("openURL:")) == true{
responder?.perform(Selector("openURL:"), with: url)
}
responder = responder!.next
}
Run Code Online (Sandbox Code Playgroud)
更新日期:6/15/2017:XCode 8.3.3
let url = NSURL(string: urlString)
let selectorOpenURL = sel_registerName("openURL:")
let context = NSExtensionContext()
context.open(url! as URL, completionHandler: nil)
var responder = self as UIResponder?
while (responder != nil){
if responder?.responds(to: selectorOpenURL) == true{
responder?.perform(selectorOpenURL, with: url)
}
responder = responder!.next
}
Run Code Online (Sandbox Code Playgroud)
小智 25
试试这个代码.
UIResponder* responder = self;
while ((responder = [responder nextResponder]) != nil)
{
NSLog(@"responder = %@", responder);
if([responder respondsToSelector:@selector(openURL:)] == YES)
{
[responder performSelector:@selector(openURL:) withObject:[NSURL URLWithString:urlString]];
}
}
Run Code Online (Sandbox Code Playgroud)
小智 20
这是设计的.我们不希望自定义操作成为应用程序启动器.
Han*_*kke 16
Apple接受了以下解决方案,即主机应用程序将使用的"相同"代码.它适用于迄今为止所有iOS 8版本(在iOS 8.0 - iOS 8.3上测试).
NSURL *destinationURL = [NSURL URLWithString:@"myapp://"];
// Get "UIApplication" class name through ASCII Character codes.
NSString *className = [[NSString alloc] initWithData:[NSData dataWithBytes:(unsigned char []){0x55, 0x49, 0x41, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E} length:13] encoding:NSASCIIStringEncoding];
if (NSClassFromString(className)) {
id object = [NSClassFromString(className) performSelector:@selector(sharedApplication)];
[object performSelector:@selector(openURL:) withObject:destinationURL];
}
Run Code Online (Sandbox Code Playgroud)
Ale*_*ang 14
Swift 3.0和4.0中的工作解决方案:
// For skip compile error.
func openURL(_ url: URL) {
return
}
func openContainerApp() {
var responder: UIResponder? = self as UIResponder
let selector = #selector(openURL(_:))
while responder != nil {
if responder!.responds(to: selector) && responder != self {
responder!.perform(selector, with: URL(string: "containerapp://")!)
return
}
responder = responder?.next
}
}
Run Code Online (Sandbox Code Playgroud)
说明:
在扩展中,api受编译器限制,不允许您像容器应用程序一样使用openURl(:URL).然而,api仍然在这里.
在我们声明它之前我们不能在我们的类中执行方法,我们真正想要的是让UIApplication执行这个方法.
回想一下响应者链,我们可以使用
var responder: UIResponder? = self as UIResponder
responder = responder?.next
Run Code Online (Sandbox Code Playgroud)
循环到UIApplication对象.
我使用此方法的应用程序通过了审核流程,因此请不要担心使用它.
Den*_*ovs 10
以下代码适用于Xcode 8.3.3、iOS10、Swift3和Xcode 9、iOS11、Swift4,没有任何编译器警告:
func openUrl(url: URL?) {
let selector = sel_registerName("openURL:")
var responder = self as UIResponder?
while let r = responder, !r.responds(to: selector) {
responder = r.next
}
_ = responder?.perform(selector, with: url)
}
func canOpenUrl(url: URL?) -> Bool {
let selector = sel_registerName("canOpenURL:")
var responder = self as UIResponder?
while let r = responder, !r.responds(to: selector) {
responder = r.next
}
return (responder!.perform(selector, with: url) != nil)
}
Run Code Online (Sandbox Code Playgroud)
确保您的应用支持通用链接,否则它将在浏览器中打开链接。更多信息在这里:https : //developer.apple.com/library/content/documentation/General/Conceptual/AppSearch/UniversalLinks.html
键盘扩展的工作解决方案(在iOS 9.2上测试).此类别添加了访问隐藏sharedApplication对象的特殊方法,然后调用openURL:它.(当然,你必须使用openURL:你的应用程序方案的方法.)
extension UIInputViewController {
func openURL(url: NSURL) -> Bool {
do {
let application = try self.sharedApplication()
return application.performSelector("openURL:", withObject: url) != nil
}
catch {
return false
}
}
func sharedApplication() throws -> UIApplication {
var responder: UIResponder? = self
while responder != nil {
if let application = responder as? UIApplication {
return application
}
responder = responder?.nextResponder()
}
throw NSError(domain: "UIInputViewController+sharedApplication.swift", code: 1, userInfo: nil)
}
}
Run Code Online (Sandbox Code Playgroud)
这似乎是一个错误,因为文档说:
打开包含应用程序
在某些情况下,扩展请求打开包含的应用程序是有意义的.例如,当用户单击某个事件时,OS X中的"日历"小组件将打开"日历".要确保您的包含应用程序以在用户当前任务的上下文中有意义的方式打开,您需要定义应用程序及其扩展可以使用的自定义URL方案.
扩展程序不直接告诉其包含的应用程序打开; 相反,它使用NSExtensionContext的openURL:completionHandler:方法告诉系统打开其包含的应用程序.当扩展使用此方法打开URL时,系统会在完成请求之前验证该请求.
我今天报告了这个问题:http://openradar.appspot.com/17376354如果你有空闲时间,你应该欺骗它.
小智 7
NSExtensionContext仅支持今天扩展中的openURL函数,这在Apple的文档中有关NSExtensionContext的描述.原始单词是"每个扩展点确定是否支持此方法,或者在哪种条件下支持此方法.在iOS 8.0中,只有今日扩展名point支持这种方法."
可能的解决方法:创建并添加一个小的UIWebView到您的视图,并运行它与你上面设置的URL方案的loadRequest方法.这是一种解决方法,我不确定Apple会对此发表什么.祝好运!
使用现代 Swift 语法的 Julio Bailon 答案的更新版本:
let url = NSURL(string: "scheme://")!
var responder: UIResponder? = self
while let r = responder {
if r.respondsToSelector("openURL:") {
r.performSelector("openURL:", withObject: url)
break
}
responder = r.nextResponder()
}
Run Code Online (Sandbox Code Playgroud)
现在不需要 NSObject 的扩展。
注意:在调用此代码之前,您必须等待视图附加到视图层次结构,否则无法使用响应者链。
| 归档时间: |
|
| 查看次数: |
28057 次 |
| 最近记录: |