2012-04-14 12 views
2

私のアプリでは、自分のアプリ内のリンクをUIWebView内で開くために、私のAppDelegateにプライベートメソッドを実装して、デフォルトのopenURL:メソッドをオーバーライドしました。しかし、今ではデフォルトの機能が必要です。ここでアプリケーションでopenURLの実装を動的に変更するにはどうすればよいですか?

は、私がやったことだ:

@implementation UIApplication (Private) 

- (BOOL)customOpenURL:(NSURL*)url 
{ 
    AppDelegate *MyWatcher = (AppDelegate *)[[UIApplication sharedApplication] delegate]; 

    if (MyWatcher.currentViewController) { 
     [MyWatcher.currentViewController handleURL:url]; 
     return YES; 
    } 
    return NO; 
} 

@end 

- (void)applicationDidBecomeActive:(UIApplication *)application { 
    Method customOpenUrl = class_getInstanceMethod([UIApplication class], @selector(customOpenURL:)); 
    Method openUrl = class_getInstanceMethod([UIApplication class], @selector(openURL:)); 

    method_exchangeImplementations(openUrl, customOpenUrl); 
} 

私もカスタムオープンURLの処理が必要とされた私のクラスでhandleURL:を実施しました。しかし、これは私がiTunesで簡単にiTunesリンクを開いてみたいという私の他のクラスを妨げている。だから達成する方法が分からないのは、customOpenURL:の代わりに元のopenURL:を使用する方法です。

+0

なぜ、 'openURL'の代わりに' customOpenURL'を呼び出せないのですか?その後、上書きする必要はありません。 – Krizz

+0

customURLはUIWebViewでリンクを開きますが、1つのリンクではUIwebViewで開き、もう1つのリンクではiTunesで開きたいとします。 – Ashutosh

+0

しかし、私はあなたが 'UIWebView'でオープンしたいリンクに対して' customOpenURL'を呼び出すことができず、iTunesで外部から起動したいリンクに対して 'openURL'をなぜ呼び出せないのでしょうか? – Krizz

答えて

4

UIApplicationをサブクラス化し、openURL:を直接オーバーライドすることができます。 Info.plistの基本クラスを変更して、UIApplicationサブクラスを使用するようにしてください。

例:

@interface ECApplication : UIApplication 

@end 

@implementation ECApplication 

- (BOOL)openURL:(NSURL*)url 
{ 

    AppDelegate *MyWatcher = (AppDelegate *)[[UIApplication sharedApplication] delegate]; 

    if (MyWatcher.currentViewController) { 
     [MyWatcher.currentViewController handleURL:url]; 
     return YES; 
    } 
    return NO; 
} 

@end 

次に、あなたのInfo.plistファイルで、原則クラスキーを探し、そしてECApplication(またはものは何でも、あなたのサブクラスに名前を付ける)に値を変更します。

+0

それを入手できませんでした。コードで説明できますか? – Ashutosh

+0

私の答えを更新しました。 – edc1591

+0

そして、私はUIApplicationの私的実装を削除する必要があります。しかし今ではプリンシパルクラスがECApplicationになるので、openURLメソッドはどのように動作しますか – Ashutosh

2

あなたは他のいくつかのメソッドに元の実装を設定し、それを呼び出すことができます。

@implementation UIApplication (Private) 
- (BOOL)originalOpenURL:(NSURL*)url 
{ 
    return NO; 
} 

- (BOOL)customOpenURL:(NSURL*)url 
{ 
    if (/* some condition */) 
    { 
     // your code 
    } 
    else 
    { 
     return [self originalOpenURL: url]; 
    } 
} 

@end 

- (void)applicationDidBecomeActive:(UIApplication *)application { 
    Method customOpenUrl = class_getInstanceMethod([UIApplication class], @selector(customOpenURL:)); 
    Method openUrl = class_getInstanceMethod([UIApplication class], @selector(openURL:)); 
    Method originalOpenUrl = class_getInstanceMethod([UIApplication class], @selector(originalOpenURL:)); 

    method_exchangeImplementations(openUrl, originalOpenUrl); 
    method_exchangeImplementations(openUrl, customOpenUrl); 
} 

注:これは、あなたの質問に直接答えを与えるだけのソリューションです。この問題へのより明確なアプローチは、@ edc1591によって提案されたものです。 [super openURL:url]で元のopenURL:にアクセスできます。

+0

どちらも動作しません。私はedcによって与えられたものを試してみようと思います。 – Ashutosh

+0

どこでこれを行うべきですか?[super openURL:url]; – Ashutosh

+0

@Ashutoshそれは動作します - ちょうど私のXcodeとiPhoneのシミュレータでテストされています。 – Krizz

0

Krizzが指摘しているアプローチは、最初のアプリの起動時にのみ機能します。別のApp(つまりFacebookアプリ)にリダイレクトするURLを開いた場合、アプリが再開されると実装が失われます。最初のアプリの起動時にのみmethod_exchangeImplementationsが呼び出されることを確認するためのフラグを追加すると動作するようです。

関連する問題