2011-11-03 25 views
17

tl; dr - Safari trên iOS 5 đang lưu vào bộ nhớ cache rất khó, nó đang phá vỡ trang web của tôi.Sự cố với Bộ nhớ cache trang trong iOS 5 Safari khi điều hướng trở lại/dỡ sự kiện không được kích hoạt

Tôi đang vật lộn với cách trình duyệt Safari trong iOS 5 đề cập đến bộ đệm ẩn tiến về phía trước, mà chúng gọi là "Bộ nhớ trang". Cách nó được mô tả here giải thích hành vi rất tốt.

Rất đơn giản, trang Cache làm cho nó vì vậy khi bạn rời khỏi một trang chúng tôi “tạm dừng” nó và khi bạn quay trở lại chúng tôi nhấn “play”.

này đang gây ra những vấn đề xuyên suốt trang web của tôi. Khi sử dụng nút quay lại, hầu hết các trình duyệt khác sẽ hiển thị cho bạn trang ở trạng thái được tải. Không phải Safari trên iOS 5, nó cho bạn thấy trang như bạn cuối cùng còn lại nó. Một ví dụ đơn giản là vô hiệu hóa nút gửi. Nếu tôi sử dụng Javascript để vô hiệu hóa nút gửi, sau đó gửi biểu mẫu, khi bạn nhấp vào nút gửi vẫn sẽ bị tắt. Đây là một vấn đề trong các trình duyệt khác, bao gồm phiên bản Safari dành cho máy tính để bàn, nhưng nó được giải quyết bằng cách đặt trình xử lý sự kiện onload thành một hàm trống. Tôi tin rằng điều này cho trình duyệt để làm mất hiệu lực bộ nhớ cache vì một cái gì đó quan trọng có thể đã xảy ra trong chức năng đó. Bản hack này dường như không hoạt động đối với Safari trên iOS 5.

Dưới đây là vấn đề được giải quyết cho các yếu tố cần thiết. Khi bạn tải test.html, bạn sẽ thấy văn bản "Văn bản gốc". Khi bạn nhấp vào liên kết, văn bản đó sẽ thay đổi thành "Văn bản đã thay đổi - chuyển tiếp đến trang tiếp theo", sau đó trong 3 giây, bạn sẽ được chuyển tiếp đến test2.html. Tất cả đều tốt cho đến thời điểm này trong tất cả các trình duyệt. Trong tất cả các trình duyệt khác, khi bạn nhấp vào nút quay lại, văn bản bạn sẽ thấy là "Văn bản gốc", nhưng trên Safari cho iOS 5, bạn sẽ thấy "Thay đổi văn bản - chuyển tiếp tới trang tiếp theo".

Bất kỳ đề xuất nào về cách giải quyết vấn đề này?

Đây là một ví dụ đơn giản

test.html

<script> 
function changeText() { 
    el = document.getElementById("text"); 
    el.innerHTML = "Changed text - forwarding to next page"; 
    setTimeout("forward()",3000);  
} 
function forward() { 
    document.location.href = "test2.html"; 
} 
</script> 
<div id="text">Original Text</div> 
<a href="Javascript:changeText()">Click Here</a> 
<script> 
window.onunload = function(){}; 
</script> 

test2.html

<div>Click back button</div> 

Đây là một ví dụ thứ hai sử dụng một bài mẫu. Đây là một ví dụ đơn giản về cách ứng dụng của tôi hoạt động. Khi bạn điều hướng trở lại formtest2.asp, bạn sẽ thấy giá trị biểu mẫu đã đăng và văn bản div phải là bản gốc.

formtest.asp

<form method="post" action="formtest2.asp"> 
    Test: <input type="text" name="test"/> 
    <input type="submit" value="Submit"/> 
</form> 

formtest2.asp

<script> 
function changeText() { 
    el = document.getElementById("text"); 
    el.innerHTML = "Changed text - forwarding to next page"; 
    setTimeout("forward()",3000);  
} 
function forward() { 
    document.location.href = "test2.html"; 
} 
</script> 

<% 
Dim test 
test = Request("test") 
Response.Write("Test value: " & test & "<br />") 
%> 

<div id="text">Original Text</div> 
<a href="Javascript:changeText()">Click Here</a> 
<script> 
window.onunload = function(){}; 
</script> 

test2.html

<div>Click back button</div> 
+0

Chỉ cần thêm một chút thông tin về việc này. Dường như tất cả các trình duyệt mà tôi đã thử nghiệm (Firefox, IE, Safari Desktop) đang kích hoạt pagehide, và dỡ bỏ, theo thứ tự đó. Safari trên iOS 5 chỉ kích hoạt pagehide. – Clarke

+0

Khi mở một tab mới, sự kiện unload không được kích hoạt, chỉ cần pagehide. Khi mở một tab mới, bạn sẽ có thể điều hướng trở lại một tab cũ và xem trang giống như bạn đã rời khỏi nó. Vấn đề là khi chúng ta điều hướng từ một trang đến trang tiếp theo trong cùng một tab/cửa sổ, sự kiện dỡ bỏ sẽ được kích hoạt trên mỗi w3c nhưng không phải. http://www.w3.org/TR/DOM-Level-2-Events/events.html. "Sự kiện unload xảy ra khi triển khai DOM xóa tài liệu khỏi cửa sổ hoặc khung. Sự kiện này hợp lệ đối với các phần tử BODY và ​​FRAMESET." – Clarke

+0

Bất kỳ giải pháp nào bằng cách sử dụng location.reload() không thành công vì đối với hàm này, Safari trên ios 5 sẽ chỉ thực hiện GET, không phải là POST giống như tất cả các trình duyệt khác. – Clarke

Trả lời

1

Tôi đang gặp vấn đề tương tự.
Trên iOS4, khi bạn điều hướng homepage.html đến 2.html, sau đó quay lại homepage.html, js sẽ không được gọi là. khi bạn điều hướng homepage.html đến 2.html, từ 2.html bạn tiếp tục chuyển đến 3.html và sau đó quay lại từ 3 đến 2 đến trang chủ, JS sẽ là được gọi! Vâng, thật khủng khiếp!
Nhưng trên iOS5 MobileSafari, Nó luôn luôn có thể không được gọi :(Có lẽ đây là một lỗi bộ nhớ cache trên iOS5. Tôi đã thử nghiệm trên iOS 5.0.0 và 5.0.1, có kết quả tương tự.

Nhưng khi bạn thực hiện Sự kiện onUnload trên body phần tử, nó có thể khắc phục sự cố backforward trên MobileSafari trước đó Tôi chỉ cần thay đổi <body> thành <body onUnload=""> trong homepage.html, sau đó từ trang chủ thành 2.html, khi trở lại trang chủ, javascript trên trang chủ sẽ được gọi Nó hoạt động trên FF, Desktop Safari, Mobile Safari (iOS4)

Vì vậy, chúng ta có thể làm gì trên iOS5? Thật không may tôi đã không tìm thấy một giải pháp. Nhưng webapp của tôi chạy trong một khách hàng bản địa, tôi cố định này bằng cách thêm một cuộc gọi reload() từ mẹ đẻ:

 
     if (isOS5_) 
     { 
      [webView stringByEvaluatingJavaScriptFromString:@"location.reload();"]; 
     } 

khi webViewDidFinishLoad:

+0

Tôi đã thử thêm một lần tải lại trên trang khi điều hướng quay lại trang này, nhưng điều này gây ra sự cố trên các trang đang chờ bài đăng biểu mẫu. Tải lại chỉ cần tải URI mà không đăng dữ liệu biểu mẫu. – Clarke

1

trên trang web di động của tôi, tôi đã cố định các vấn đề với Mã JS nhỏ này:

if ((/iphone|ipad.*os 5/i).test(navigator.appVersion)) { 
    window.onload=function() { 
     localStorage.setItem("href",location.href); 
    }; 
    window.onpopstate=function() { 
     var a=localStorage.getItem("href"), 
      b=location.href; 
     if (b!==a&&b.indexOf((a+"#"))===-1) { 
      document.body.style.display="none"; 
      location.reload(); 
     } 
    }; 
} 

Kịch bản:

nhấp vào liên kết “Page2” từ “Trang1”: Khi nhấp vào “Trang1” được gần d, “Page2” được tải và kích hoạt quá trình tải và nhiều sự kiện khác.

[Trang1] -> nhấp vào liên kết -> [Page2] -> onload -> onpopstate -> ...

Tại thời điểm này nếu bạn nhấp vào nút quay lại của trình duyệt của bạn, “Page2” được đóng và “Page1” được tải và kích hoạt quá trình tải và nhiều sự kiện khác.

[Page2] -> nhấn vào nút quay lại -> [Trang1] -> onload -> onpopstate -> ...

Nhấp vào nút quay lại trong IOS5 làm cho đóng cửa “Trang1” và “Page2” xuất hiện nhưng trang không được tải, tỷ lệ khung nhìn bị hỏng và sự kiện duy nhất bị sa thải là onpopstate.

[Page2] -> nhấp vào nút quay lại -> [Page1] -> onpopstate.

Khắc phục:

Sửa chữa hoạt động xung quanh sự kiện onload, onpopstate và đối tượng localStorage.

onload là sự kiện đầu tiên được quản lý bởi tập lệnh và bên trong nó lưu trữ vị trí hiện tại.href trên localStorage.

Nếu không có lỗi nào, trong onpopstate vị trí hiện tại.href và href được lưu trữ phải giống nhau và tập lệnh sẽ không hoạt động.

Sử dụng Safari trên IOS5 trang không được tải và sự kiện onload không được kích hoạt, sau đó location.href và href được lưu trữ khác nhau trong sự kiện onpopstate.

Trong trường hợp này chỉ cần ẩn trang hiện tại (đối với một lỗi khác trong chế độ xem có liên quan đến điều này) và tải lại trang có đối tượng vị trí.

+0

Cảm ơn bạn đã nhập liệu, mặc dù nó sẽ không hoạt động cho tôi. Vì điều này làm việc cho bạn, bạn có thể muốn thêm ipod vào câu lệnh if. Tôi đã phải làm điều này bởi vì một iPod Touch là những gì tôi sử dụng để thử nghiệm và đã phải thêm nó để làm cho nó hoạt động. Giải pháp này hoạt động tốt cho các trang nội dung động, nhưng bị hỏng khi bạn điều hướng trở lại trang đang chờ gửi biểu mẫu. Location.reload() chỉ tải URI đó và không đăng các giá trị biểu mẫu ban đầu. Đây là nơi html mẫu của tôi ở trên không đầy đủ. – Clarke

26

Tôi cũng đang tìm câu trả lời cho cùng một vấn đề. Quay lại iOS 5 không thực thi bất kỳ javascript nào và chỉ rời khỏi trang ở trạng thái trước đó khi bạn rời đi hoặc được chuyển hướng.

Cố gắng tìm kiếm "onunload" lạ được tìm thấy trong "Is there a cross-browser onload event when clicking the back button?" chỉ hoạt động cho iOS 4, không phải iOS 5 mà không gọi sự kiện như mong đợi. Nickolay đã chỉ ra các chức năng mới trên web-kit gọi là "pageshow" và "pagehide" đáng tin cậy hơn nhiều so với ví dụ của Giuseppe.

  1. Bạn cần hack từ bài viết này: "Is there a cross-browser onload event when clicking the back button?" để làm việc này trong iOS 4.
  2. Sử dụng kịch bản này trong đó sử dụng các sự kiện mới để kiểm tra một cách an toàn nếu trang đã được nạp từ bộ nhớ cache và buộc một tải lại (tránh URL kiểm tra và lưu trữ địa phương và cũng bao gồm iPod) cho iOS 5:

    <body onunload=""> 
    ... 
    <script type="text/javascript"> 
    if ((/iphone|ipod|ipad.*os 5/gi).test(navigator.appVersion)) { 
        window.onpageshow = function(evt) { 
        // If persisted then it is in the page cache, force a reload of the page. 
        if (evt.persisted) { 
         document.body.style.display = "none"; 
         location.reload(); 
        } 
        }; 
    } 
    </script> 
    
+0

Cuối cùng, giải pháp này là giống như phần còn lại trong đó làm một tải lại không sửa chữa vấn đề của tôi. Từ bên dưới, "Giải pháp này hoạt động tốt cho các trang nội dung động, nhưng bị hỏng khi bạn điều hướng trở lại trang đang chờ gửi biểu mẫu. Location.reload() chỉ tải URI đó và không đăng các giá trị biểu mẫu ban đầu". – Clarke

+1

@Clarke: Bạn cần phải viết các tham số POST mà bạn muốn đăng lại vào đánh dấu bằng cách sử dụng mã phía máy chủ (giống như cách bạn đang viết biến "test"). Tiêm các phần tử đầu vào bị ẩn trong phần tử biểu mẫu cho tất cả các biến bạn muốn POST lại. Sau đó, sử dụng cùng một mã cơ bản ở trên, thay vì thực hiện tải lại, chỉ cần gửi biểu mẫu. – BrutalDev

+0

Điều đó dường như là một giải pháp tốt, nhưng trong thực tế nó không phải là. Đôi khi sự kiện đó không xảy ra. Tôi thậm chí không thể giải thích làm thế nào để lặp lại vấn đề đó, hãy thử mở trang 1 rồi đến trang 2, sau đó bấm lại, sự kiện cháy, sau đó lặp lại một vài lần. – Rantiev

0

Sau khi tìm thấy làm thế nào để tránh một trong những vấn đề (s) tất cả chúng ta dường như có về vấn đề này, tôi khó khăn tôi muốn chia sẻ :)

Sau khi đọc vài chủ đề liên quan về chủ đề, chủ yếu là trên chồng tràn "đối tượng nóng nhất", xử lý "Bộ nhớ trang" (http://www.webkit.org/blog/427/webkit-page-cache-i-the-basics/http://www.webkit.org/blog/516/webkit-page-cache-ii-the-unload-event/), hãy kiểm tra sự kiện "dỡ tải" (developer.apple.com/library/IOS) /ipad/#documentation/AppleApplications/Reference/SafariWebContent/HandlingEvents/HandlingEvents.html)/"pageshow" không có tiếng ồn phải đối phó với "hiển thị trang" ngắn gọn ở trạng thái trước đó của nó (không phải trang trước đó là trạng thái INITIAL, mà chỉ là trang khi nó còn lại) trong khi người dùng chuyển về ứng dụng/hoặc mở khóa thiết bị của mình/hoặc quay lại ứng dụng sau khi thoát ứng dụng.

Dường như (đối với tôi, ít nhất), mà này "trục trặc có thể nhìn thấy" đã được giải quyết khi tôi đã làm các bản cập nhật cho iOS6, giống như 5 mins ago; D

tôi sau đó có thể sử dụng ứng dụng web của tôi trong safari di động như bình thường và sau khi thêm nó vào màn hình chính, hành vi trong trường hợp "chuyển đổi ứng dụng" hoặc "khởi chạy lại", có hoặc không có bộ nhớ cache đã xóa, giống như lần khởi động đầu tiên: bạn thấy trang BLANK và sau đó là nội dung (có thể là trang tương ứng với url đã được lưu vào màn hình chính hoặc bất kỳ nội dung nào khác được tải bằng cách sử dụng localStorage ví dụ [trường hợp của tôi (..)]).

Đối với các sự kiện tôi có thể bắt, cũng như trên các thiết bị IOS5 IOS5, tôi có thể quản lý để thoát khỏi "trục trặc bền vững trực quan" đó. Tôi đoán đó là vì cách "Page Cache" hoạt động, nhưng bây giờ tôi đang chạy IOS6 trên iPad, vì trục trặc không còn ở đó nữa, tôi đoán nhóm Safari phải cải thiện cách họ xử lý các ứng dụng web "màn hình chính" (..)

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