离线iOS Web应用程序:可以加载我的清单,但无法离线工作

74

我正在编写一个Web应用程序,可以在iOS离线使用。我已经创建了一个清单,并将其作为text/cache-manifest提供,当在Safari中运行时通常都很好用。

如果我将它添加为我的主屏幕上的应用程序,然后打开飞行模式,它根本无法打开应用程序——我会收到一个错误提示并询问是否关闭该应用程序。(我认为这就是离线应用程序的全部目的!)

  • 当我第一次在线加载应用程序时,我可以在日志中看到它请求清单中列出的每个页面。

  • 如果我关闭飞行模式并加载应用程序,则可以看到它请求的第一个文件是我的main.html文件(它既列在清单中,也具有manifest=...属性)。然后它请求清单和所有其他文件,在此加载期间对于所有请求的文件都得到200(对于任何第二次请求的文件都得到304)。

  • 当我在Chrome中加载页面并点击时,日志显示它在服务器上尝试访问的唯一内容是“/favicon.ico”(这是404,我认为iOS Safari也不会尝试加载它)。清单中列出的所有文件都是有效的且没有出现错误。

  • Chrome检查器在“应用程序缓存”下列出了我期望的所有缓存文件。整个文件集大小约为50 KB,远低于我找到的任何离线资源限制。

这是否应该起作用,也就是说,我是否能够仅使用HTML/CSS/JS创建离线iOS应用程序? 我在哪里可以找到原因,为什么它无法离线工作?

(虽然与此相关,但对我来说听起来不太一样,因为它是关于Safari而不是独立应用程序的:“在iPod上无法使Web应用程序脱机工作”)

13个回答

22

我确认名称为'cache.manifest'的文件解决了在IOS 4.3中的离线缓存问题。其他名称则无法正常工作。


+1 这对我有用 - 即使我可以看到iPad正在获取并使用我的先前叫做offline.manifest的清单文件。 - Paul Dixon

7

我发现调试HTML5离线应用程序很麻烦。我从这篇文章中的代码帮助我找出了我的应用程序的问题:

http://jonathanstark.com/blog/2009/09/27/debugging-html-5-offline-application-cache/

HTML 5离线应用程序缓存调试 by Jonathan Stark

如果您想为您的Web应用程序提供离线访问,则HTML5中提供的离线应用程序缓存非常有用。但是,调试它非常麻烦,特别是如果您仍在努力理解它。

如果您正在处理缓存清单,请将以下JavaScript添加到主HTML页面,并使用Firefox中的Firebug或Safari中的Debug> Show Error Console查看控制台输出。

如果您有任何问题,请在评论中告诉我。

希望对你有所帮助,
j

var cacheStatusValues = [];
cacheStatusValues[0] = 'uncached';
cacheStatusValues[1] = 'idle';
cacheStatusValues[2] = 'checking';
cacheStatusValues[3] = 'downloading';
cacheStatusValues[4] = 'updateready';
cacheStatusValues[5] = 'obsolete';

var cache = window.applicationCache;
cache.addEventListener('cached', logEvent, false);
cache.addEventListener('checking', logEvent, false);
cache.addEventListener('downloading', logEvent, false);
cache.addEventListener('error', logEvent, false);
cache.addEventListener('noupdate', logEvent, false);
cache.addEventListener('obsolete', logEvent, false);
cache.addEventListener('progress', logEvent, false);
cache.addEventListener('updateready', logEvent, false);

function logEvent(e) {
    var online, status, type, message;
    online = (navigator.onLine) ? 'yes' : 'no';
    status = cacheStatusValues[cache.status];
    type = e.type;
    message = 'online: ' + online;
    message+= ', event: ' + type;
    message+= ', status: ' + status;
    if (type == 'error' && navigator.onLine) {
        message+= ' (prolly a syntax error in manifest)';
    }
    console.log(message);
}

window.applicationCache.addEventListener(
    'updateready',
    function(){
        window.applicationCache.swapCache();
        console.log('swap cache has been called');
    },
    false
);

setInterval(function(){cache.update()}, 10000);

1
这是一个不错的 JS 代码片段,但迄今为止它没有帮助我学到任何新知识。日志中的所有下载/检查/空闲看起来都正如我所期望的那样。 - Ken
@Ken - 很抱歉听到这个消息。它确实帮助我缩小了错误范围(尽管找到确切原因仍然很痛苦)。它还为我提供了一些有关缓存是否成功加载/重新加载的良好反馈(在知道这一点之前,我会在每次更改后离线测试 - 在知道这一点之后,我知道我需要在尝试离线之前成功获取updateready事件)。 - Bert F
嗯,我需要担心updatereadyswapCache()等吗?我认为,由于我正在制作一个完全离线的应用程序(在初始加载后根本没有服务器交互),所以我只需将我的文件名放入缓存清单中即可。在我的情况下,这比那更复杂吗? - Ken

5
有时在MobileSafari中,应用程序缓存组会出现问题 - 它会下载缓存中的每个项目,然后在结束时触发一个通用的缓存错误事件。根据规范,应用程序缓存组基于清单的绝对URL。我发现当出现此错误时,更改清单的路径(例如cache2.manifest等)将为您提供一个新的缓存组并避免问题。我可以证明,我们所有的Web应用都可以在4.2和4.3的全屏幕离线模式下工作。

3
我发现在开启飞行模式后清除Safari缓存是一种有效的测试应用程序是否真正离线运行的方法。 有时候我会被骗以为应用程序缓存正在工作,但实际上并没有。

3

截至 iOS 4.2 版本,任何使用 <meta name="apple-mobile-web-app-capable" content="yes" /> 标签的离线网络应用(包括飞行模式)都需要联网才能运行。我已经验证了每个示例,并且那些使用 Safari 渲染站点的示例可以正常工作,但是当你加入这个 meta 标签后,它就无法正常工作。如果您尝试不使用该标签来运行应用程序,您会明白我的意思。


1
@pattern86 有趣的是,我这里有一个网站(还在开发中,所以不能分享,很抱歉),它似乎可以使用<meta name="apple-mobile-web-app-capable" content="yes" />正常工作。我可以关闭浏览器和离线Web应用程序,打开飞行模式,仍然可以毫无问题地加载离线Web应用程序。是否需要其他行为来触发此错误?我想确保我们不会在实际应用中遇到这个问题... - Rowan
1
奇怪的是,Curiously PieGuy 对我也有效。我使用的是4.2(8C134),这是4.2GM版本。我将尝试升级到4.2.1并查看会发生什么:( - Rowan
@Rowan 我所指的离线 Web 应用是添加到主屏幕上的应用。如果你在 Safari 中将它们加为书签并在那里使用,它应该仍然可以正常工作。我还没有在 iOS 4.3 上测试过这个功能。 - jsejcksn
@pattern86 同意,我也是指主屏幕 Web 应用程序。我有机会在 4.2.1 和 4.3 上测试了我的网站 - 在这两种情况下,它都可以正常工作。因此,在这里似乎存在一些其他的影响(清单对许多事情都很敏感),但整个清单似乎确实能够按预期运作。 - Rowan
@Rowan,我很高兴你让它正常工作了!我会在这个周末尝试一下。 - jsejcksn
显示剩余2条评论

2
自从我将iPad从4.2更新到4.3.1以来,我一直苦于iOS 4.3“无离线缓存”问题。我在这个网站的另一篇帖子中看到它在4.3.2中再次工作。所以我再次更新了我的iPad,现在是iOS 4.3.3。但是,直到我将清单文件重命名为“cache.manifest”,离线缓存仍然无法正常工作。然后缓存开始工作,我可以从主屏幕运行我的HTML5离线应用程序。我不需要将favicon.ico放入缓存清单中。而且我也有全屏功能(将“apple-mobile-web-app-capable”设置为“yes”)。

1

我有一个可能的解决方法 - 看起来有点疯狂,但是试试看... 我经常使用cache.manifest和全屏应用程序(如果需要测试,请参考:http://www.mrspeaker.net/2010/07/12/argy-bargy/ - 添加到主屏幕,然后打开飞行模式,它会启动 - 至少在iOS 4.2.1上是这样)

我发现一件奇怪的事情是,有时候似乎文件中的某些“元”信息会阻止它们被缓存 - 你是否注意到在bash中,如果你执行“ls”,一些文件(取决于你的颜色设置)会出现无法解释的高亮显示?文件可以具有操作系统(我想)自动添加的元数据 - 并且有方法可以删除它... 我记不清为什么了,但这里有更多细节:从Snow Leopard中删除文件的元数据

有一天,我为了解决一个问题而苦恼不已,但是我知道它应该可以解决... Chrome 显示所有文件都已加载,但最终却出现了一个通用错误。最后,我使用空白文件重新创建了项目结构,并将内容复制/粘贴到新的文件中。它奏效了 - 开始像预期的那样缓存!

当我查看文件时,我注意到有一些元信息。我尝试清除这些信息,原始项目再次工作了。我不确定这是否是它再次工作的原因 - 也许这只是巧合。

因为它奏效了,所以我没有太在意。几个月后,同样的问题再次发生,复制/粘贴技巧再次奏效。我很忙,所以我没有进一步调查 - 但我发誓下一次再发生这种情况时我会找到根本原因....但我还没有遇到过。

呼...总之,我很高兴能在这里写下这些...

[更新:数月后 - 我无法重现此问题,因此我认为这不是元数据的原因]


1
今天我在iOS 4.3上遇到了同样的问题。通过添加一个favicon.ico文件并将其添加到清单中,我成功解决了这个问题。

1

1

我有几个离线和在线/离线网络应用程序。

当我关闭飞行模式时,会收到一个清单和一些其他文件的请求。

我不会收到图像、JavaScript、CSS或缓存的AJAX文件的请求。

如果您看到资源的请求,IOS没有将它们缓存。

Safari通常对清单更加挑剔。

我建议您在计算机上尝试Safari。


不,如上所述(Safari在这里与Chrome相同,据我所知),它从未尝试从桌面浏览器请求任何资源(除了/favicon.ico)。唯一这样做的时候是从iOS Safari,在飞行模式下(或其他离线情况下,可能会这样)。 - Ken
我想看这个页面。我在家里用我的 Mac 运行 Chrome/Safari/Firefox 浏览器,而在 iPhone 和 iPad 上则使用 iOS 系统。 - JakeCigar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接