11

多くの検索/グーグル検索を行いましたが、HTTP 応答ヘッダーをキャプチャする方法についての答えを得ることができませんでしたUIWebview。アプリの起動時に UIWebview でユーザーを登録ゲートウェイ (既にアクティブ) にリダイレクトするとします。ユーザーが登録を完了すると、HTTP 応答ヘッダーで返される登録時にユーザーに割り当てられた一意の ID がアプリに通知されます。 .

を使用して HTTP 応答ヘッダーをキャプチャ/印刷する直接的な方法はありますUIWebviewか?

4

4 に答える 4

19

から応答オブジェクトを取得する方法はありませんUIWebView(それについては、Apple にバグを報告してください)。

しかし、2つの回避策

1) 共有 NSURLCache 経由

- (void)viewDidAppear:(BOOL)animated {
    NSURL *u = [NSURL URLWithString:@"http://www.google.de"];
    NSURLRequest *r = [NSURLRequest requestWithURL:u];
    [self.webView loadRequest:r];
}

- (void)webViewDidFinishLoad:(UIWebView *)webView {
    NSCachedURLResponse *resp = [[NSURLCache sharedURLCache] cachedResponseForRequest:webView.request];
    NSLog(@"%@",[(NSHTTPURLResponse*)resp.response allHeaderFields]);
}
@end

これがうまくいくなら、これは理想的です


そうしないと

  1. NSURLConnection を完全に使用してから、ダウンロードした NSData を使用してUIWebView:)にフィードすることができます

これは悪い回避策です。(リチャードがコメントで指摘したように。)それには大きな欠点があり、それがあなたのケースで有効な解決策であるかどうかを確認する必要があります

NSURL *u = [NSURL URLWithString:@"http://www.google.de"];
NSURLRequest *r = [NSURLRequest requestWithURL:u];
[NSURLConnection sendAsynchronousRequest:r queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *resp, NSData *d, NSError *e) {
    [self.webView loadData:d MIMEType:nil textEncodingName:nil baseURL:u];
    NSLog(@"%@", [(NSHTTPURLResponse*)resp allHeaderFields]);
}];
于 2013-03-18T12:34:19.953 に答える
8

私はobjective-cランタイムが大好きです。やりたいことはありますが、そのためのAPIがありませんか?DM;HR。

さて、もっと深刻なことに、これに対する解決策があります。から開始されたすべてのURL応答をキャプチャしますCFNetwork。これは、UIWebViewが舞台裏で使用するものです。また、AJAXリクエスト、画像の読み込みなどもキャプチャします。

これにフィルターを追加することは、おそらくヘッダーの内容に正規表現を行うのと同じくらい簡単なはずです。

@implementation NSURLResponse(webViewHack)

static IMP originalImp;

static char *rot13decode(const char *input)
{
    static char output[100];

    char *result = output;

    // rot13 decode the string
    while (*input) {
        if (isalpha(*input))
        {
            int inputCase = isupper(*input) ? 'A' : 'a';

            *result = (((*input - inputCase) + 13) % 26) + inputCase;
        }
        else {
            *result = *input;
        }

        input++;
        result++;
    }

    *result = '\0';
    return output;
}

+(void) load {
    SEL oldSel = sel_getUid(rot13decode("_vavgJvguPSHEYErfcbafr:"));

    Method old = class_getInstanceMethod(self, oldSel);
    Method new = class_getInstanceMethod(self, @selector(__initWithCFURLResponse:));

    originalImp = method_getImplementation(old);
    method_exchangeImplementations(old, new);
}

-(id) __initWithCFURLResponse:(void *) cf {
    if ((self = originalImp(self, _cmd, cf))) {
        printf("-[%s %s]: %s", class_getName([self class]), sel_getName(_cmd), [[[self URL] description] UTF8String]);

        if ([self isKindOfClass:[NSHTTPURLResponse class]])
        {
            printf(" - %s", [[[(NSHTTPURLResponse *) self allHeaderFields] description] UTF8String]);
        }

        printf("\n");
    }

    return self;
}

@end
于 2013-03-18T13:16:34.763 に答える
1

@Richard J. Ross III が書いたより高レベルの API コードが必要な場合は、NSURLProtocolをサブクラス化する必要があります。

AnNSURLProtocolは URL リクエストを処理するオブジェクトです。したがって、 NSHipsterおよびRay Wenderlichでよりよく説明されている特定のタスクに使用できます。これには、応答から HTTP ヘッダーを取得する場合が含まれます。

コード

NSURLProtocol からサブクラス化された新しいクラスを作成すると、.h ファイルは次のようになります。

@interface CustomURLProtocol : NSURLProtocol <NSURLConnectionDelegate>

@property (nonatomic, strong) NSURLConnection *connection;

@end

あなたの .m ファイルには、あなたが望むものを処理するためのこれらのメソッドが必要です

@implementation CustomURLProtocol

+ (BOOL)canInitWithRequest:(NSURLRequest *)request {
    // Here you can add custom filters to init or not specific requests
    return YES;
}

+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request {
    // Here you can modify your request
    return request;
}

+ (BOOL)requestIsCacheEquivalent:(NSURLRequest *)a toRequest:(NSURLRequest *)b {
    return [super requestIsCacheEquivalent:a toRequest:b];
}

- (void)startLoading {
    // Start request
    self.connection = [NSURLConnection connectionWithRequest:self.request delegate:self];
}

- (void) stopLoading {
    [self.connection cancel];
    self.connection = nil;
}

#pragma mark - Delegation

#pragma mark NSURLConnectionDelegate

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
    if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
        NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
        
        // Here we go with the headers
        NSDictionary *allHeaderFields = [httpResponse allHeaderFields];
    }
    
    [self.client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageNotAllowed];
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
    [self.client URLProtocol:self didLoadData:data];
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
    [self.client URLProtocolDidFinishLoading:self];
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
    [self.client URLProtocol:self didFailWithError:error];
}

また、最後に行うことは、このプロトコルをロード システムに登録することです。これは、AppDelegate で簡単に実現できます。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [NSURLProtocol registerClass:[CustomURLProtocol class]];
    return YES;
}
于 2016-01-27T00:57:49.703 に答える
-1

NSHTTPURLResponseのようなメソッドがあります

- (NSDictionary *)allHeaderFields

詳細については https://developer.apple.com/library/ios/#documentation/Cocoa/Reference/Foundation/Classes/NSHTTPURLResponse_Class/Reference/Reference.html#//apple_ref/occ/cl/NSHTTPURLResponse

編集:申し訳ありませんが、考えていませんでしたUIWebView。あなたが使用する場合、私のソリューションは機能しますNSURLConnection

ただし、webview に をフィードすると、NSURLConnection応答ヘッダーを含む接続をキャプチャする機会があります。

于 2013-03-18T12:22:01.920 に答える