2013-10-30 22 views
5

Tôi cần chuyển một số thông tin bổ sung cùng với UIWebView loadRequest: để nó đạt đến việc triển khai NSURLProtocol của tôi. Thông tin không được ràng buộc với NSURLRequest vì thông tin phải được giữ lại với NSURLRequest mainDocumentURL. Vì vậy, tôi được phân loại là NSURL và được xây dựng NSURLRequest với nó. Tôi đã biết rằng NSURLRequest đạt đến NSURLProtocol startLoading KHÔNG phải là trường hợp tôi đã cấp cho UIWebView loadRequest, vì vậy tôi cũng đã triển khai NSURL copyWithZone, ngây thơ mong rằng hệ thống tải URL sẽ sử dụng nó.iOS: chuyển NSURL tùy chỉnh sang NSURLProtocol

Hiện tại, NSURLProtocol canInitWithRequest được gọi là không một lần như mong đợi hợp lý, nhưng ít nhất 4 lần trước startLoading. 2 lần đầu tiên trong số đó, số điện thoại NSURLRequest đến vẫn chứa tùy chỉnh NSURL tùy chỉnh của tôi. Sau đó, mã nội bộ không may được gọi là CFURLCopyAbsoluteURL yêu cầu absoluteURL tùy chỉnh NSURLcanInitWithRequest tiếp theo của chúng tôi (và sau đó startLoading) đã nhận được NSURLRequest hoàn toàn mới với NSURL mới trong đó. copyWithZone không bao giờ được gọi và số bị phân loại là NSURL bị mất.

Trước khi tôi từ bỏ và thực hiện giải pháp kém và dễ vỡ khi gắn trực tiếp vào chuỗi URL, tôi muốn hỏi các trình thuật sĩ ở cấp cao hơn, cho dù họ thấy cách bắt được cảnh báo ban đầu trên radar NSURLProtocol hoặc làm thế nào để lừa CFURLCopyAbsoluteURL để thực hiện trường hợp tùy chỉnh của tôi. Tôi đã cố gắng để hack NSURL absoluteURL bằng cách trở lại một trường hợp mới của lớp NSURL tùy chỉnh của tôi, nhưng nó đã không giúp đỡ. Tôi đã thấy một số lời hứa trong chức năng NSURLProtocol setProperty, nhưng bây giờ nó xuất hiện khá vô ích. Hệ thống tải URL tạo ra các phiên bản mới của tất cả mọi thứ một cách vui vẻ và NSURLRequest đến ở số NSURLProtocol có vẻ giống như trường hợp được nhập vào UIWebView chỉ vô tình.

CẬP NHẬT: ok tôi muốn giữ bài đăng càng ngắn càng tốt, nhưng ngay cả câu trả lời đầu tiên cũng yêu cầu nền tảng kỹ thuật, vì vậy ở đây chúng tôi đi: tôi có nhiều ứng dụng UIWebView s. Các chế độ xem này có thể chạy yêu cầu đồng thời và hoàn toàn có thể chạy các yêu cầu cho cùng một URL. Nó giống như các tab trong trình duyệt trên máy tính để bàn. Nhưng tôi cần phải phân biệt số UIWebView là nguồn gốc của mỗi số NSURLRequest cụ thể đến số NSURLProtocol. Tôi cần một ngữ cảnh được thực hiện với mỗi yêu cầu URL. Tôi không thể chỉ đơn giản là ánh xạ các URL đến dữ liệu, bởi vì nhiều UIWebViews có thể tải cùng một URL tại bất kỳ thời điểm nào.

CẬP NHẬT 2: Việc đính kèm thông tin ngữ cảnh vào NSURL được ưu tiên và, theo như hiểu biết của tôi, chỉ có thể sử dụng được. Vấn đề là các yêu cầu đối với tài nguyên được tham chiếu bên trong trang (hình ảnh, v.v.) không được xem trực tiếp UIWebViewDelegate và kết thúc trực tiếp ở số NSURLProtocol. Tôi không có cơ hội để liên lạc, kiểm tra hoặc sửa đổi các yêu cầu như vậy ở bất cứ đâu trước NSURLProtocol. Liên kết theo ngữ cảnh duy nhất cho các yêu cầu như vậy là NSURLRequest mainDocumentURL của chúng.

+0

Vấn đề chính ở đây là bạn đang cố gắng tải thêm thông tin về 'NSURL' hơn URL. Vì vậy, câu hỏi là, loại thông tin nào bạn đang cố gắng vượt qua? Thông thường, bạn sẽ tải phụ đề này, bằng cách lưu trữ một bản đồ các URL tới "dữ liệu khác" trong một số đối tượng có thể truy cập vào 'NSURLProtocol', nhưng tôi nghĩ rằng hiểu rõ hơn về những gì bạn đang cố gắng giải quyết sẽ giúp ích ở đây. –

+0

Đã hiểu, hãy xem bản cập nhật. –

Trả lời

3

Nếu có cách nào đó để nhận số NSURL ban đầu của bạn được sử dụng làm mainDocumentURL điều đó sẽ lý tưởng. Nếu không có cách nào để ngăn chặn nó được sao chép, tôi nghĩ về hack sau đây như là một thay thế:

Trước khi tạo mỗi UIWebView, set the user agent string với giá trị duy nhất. Giả sử thay đổi này chỉ ảnh hưởng đến UIWebView đối tượng được tạo sau đó, do đó, mỗi chế độ xem sẽ kết thúc bằng chuỗi tác nhân người dùng riêng biệt của riêng nó.

Trong triển khai NSURLProtocol, bạn có thể kiểm tra chuỗi tác nhân người dùng để xác định liên kết UIWebView và chuyển nó tới trình xử lý giao thức thực bằng chuỗi tác nhân người dùng thực (vì vậy máy chủ sẽ không thấy gì khác).

Tất cả điều này phụ thuộc vào lượt xem thực sự kết thúc bằng các chuỗi UA khác nhau. Hãy cho tôi biết nếu bạn quản lý để làm cho nó hoạt động!

+0

Điều này phù hợp với tôi, mặc dù phụ thuộc vào ít nhất hai tính năng iOS không có giấy tờ. Thay đổi ** Tác nhân người dùng ** thực sự chỉ ảnh hưởng đến 'UIWebView' mới được tạo ra, chứ không chỉ ảnh hưởng đến' UIWebView' mới được tạo ra. Đối với bản ghi, bạn cần phải vượt qua ít nhất một 'NSURLRequest' thông qua' UIWebView' mới được tạo để làm cho thanh tác vụ ** User-Agent ** ". –

+0

Pavel, bạn cần bao nhiêu dữ liệu để vượt qua NSURL? Nếu bạn chỉ cần "để phân biệt UIWebView là nguồn gốc của mỗi NSURLRequest cụ thể đến NSURLProtocol", bạn có thể sử dụng setCachePolicy với giá trị của riêng bạn cho yêu cầu chính của bạn. Và NSURLProtocol sẽ chuyển giá trị đó cho các yêu cầu con của UIWebView. Dù sao, bạn có thể đặt cachePolicy thành mặc định khi bạn nắm bắt nó. Nhưng tôi không shure đó là một cách tốt ... Những gì bạn nghĩ? –

1

Bạn nói rằng bạn không thể đặt nó trên NSURLRequest, nhưng tôi không rõ lý do tại sao từ cuộc thảo luận cập nhật của bạn. Đó sẽ là nơi tự nhiên nhất để đặt nó.

  • Triển khai webView:shouldLoadWithRequest:navigationType:.
  • Đính kèm thêm thuộc tính vào yêu cầu được cung cấp bằng cách sử dụng objc_setAssociatedObject. Sau đó trả lại YES.(Thật tuyệt khi sử dụng setProperty:forKey:inRequest: ở đây, nhưng UIWebView chuyển cho chúng tôi một yêu cầu không thể thay đổi được, vì vậy chúng tôi chỉ có thể đính kèm các đối tượng liên quan.
  • Trong số NSProtocol, đọc thuộc tính bổ sung của bạn bằng cách sử dụng objc_getAssociatedObject. Yêu cầu phải giống với yêu cầu bạn đã trình bày trước đó. Bạn cho rằng đây không phải là trường hợp. Bạn có nói rằng yêu cầu tại webView:shouldLoadWithRequest:navigationType: khác với yêu cầu tại initWithRequest:cachedResponse:client:?

Tôi có thiếu một yêu cầu hoặc không gian khác không?

+0

Đối với tùy chọn 'NSURL' trên' NSURLRequest', hãy xem ** UPDATE2 **. Tôi đã gần như đi tìm 'objc_setAssociatedObject' ngay từ đầu cuộc hành hương này, nhưng sau đó tôi phát hiện ra rằng, và tôi xác nhận rằng,' NSURLProtocol' chỉ được tham khảo với đối tượng ban đầu, sau đó trao cho các cá thể hoàn toàn mới của cả hai ' NSURLRequest' và kèm theo 'NSURL'. –

1

Bạn có thể chuyển tùy chọn thông qua tiêu đề yêu cầu tùy chỉnh, giả sử rằng trang web hoặc nhà cung cấp dịch vụ được nhắm mục tiêu không bằng cách nào đó loại bỏ các tùy chọn đó khi chuyển tiếp.

Thử thách sẽ đến với lược đồ mã hóa có thể được mã hóa hợp lý thành chuỗi ASCII cho giá trị trường tiêu đề và sau đó được giải mã thành giá trị thực tế bạn muốn. Đối với điều này, một tuỳ chỉnh NSValueTransformer có vẻ thích hợp nhất.

+0

Cảm ơn bạn đã chọn cuộc gọi email của tôi và xin lỗi vì phản ứng muộn. Tôi đã đi đến cái gì khác. Tôi đã kết thúc bằng cách sử dụng tiêu đề yêu cầu, vì vậy +1, nhưng không phải cách bạn đang đề xuất. Vấn đề với giải pháp của bạn là tôi không tự tạo yêu cầu, chúng có nguồn gốc trong 'UIWebView'. Như bạn có thể đã biết, giao diện nhạo báng gọi là 'UIWebViewDelegate' chỉ xem xét các URL khung với bạn. Tôi cần phải phân biệt * tất cả * yêu cầu tài nguyên. –

0

Tôi đã gặp vấn đề tương tự. Cuối cùng tôi đã mắc kẹt vào giải pháp được Matthew đề xuất (sử dụng chuỗi tác nhân người dùng). Tuy nhiên, vì giải pháp không được giải quyết, tôi thêm một câu trả lời mới với nhiều chi tiết hơn. Hơn nữa, tôi phát hiện ra rằng bạn không cần phải gửi một yêu cầu để làm cho tác nhân người dùng "dính". Nó là đủ để có được thông qua javascript như đề nghị here.

Các bước sau đã làm việc cho tôi:

(1) Nhận tác nhân người dùng mặc định hiện tại. Bạn cần nó sau này để đưa nó trở lại yêu cầu trong NSURLProtocol. Bạn cần sử dụng chế độ xem webview mới, vì việc nhận được tác nhân người dùng sẽ làm cho nó dính vào webview, vì vậy bạn không thể thay đổi nó sau này.

UIWebView* myWebview = [[UIWebView alloc] init]; 
NSString* defaultUserAgent = [myWebview stringByEvaluatingJavaScriptFromString:@"navigator.userAgent"]; 
[myWebview release]; // no needed with ARC, but to emphasize, that the webview instance is not needed anymore 

(2) Thay đổi giá trị trong tiêu chuẩnUserDefaults (lấy từ here).

NSDictionary* userAgentDict = [NSDictionary dictionaryWithObjectsAndKeys:@"yourUserAgent", @"UserAgent", nil]; 
[[NSUserDefaults standardUserDefaults] registerDefaults:userAgentDict]; 

(3) Đặt chuỗi tác nhân người dùng mới vào webView của bạn bằng cách tải nó qua javascript như đã thực hiện trong (1), nhưng lần này trên ví dụ webview bạn thực sự làm việc.

(4) Hoàn nguyên tác nhân người dùng mặc định trong tiêu chuẩnUserDefaults as done here.

Các vấn đề liên quan