草庐IT

javascript - 在 UiWebView 中用本地 Javascript 文件覆盖远程 HTML?

coder 2024-01-12 原文

我们正在构建移动应用程序。虽然我们不是 objective c 程序员,但我们是 web 开发人员,并且有一个想法来构建类似原生应用程序但使用 HTML/CSS。

我们计划通过 UIWebView 从我们的服务器加载一个外部空白 HTML 文件(由 Drupal 提供),并希望从本地设备加载 CSS 和 Javascript。即网站发送基本的非样式化 HTML,应用程序加载本地 CSS 和 JS 来设置样式。

更新 #3 - 找到解决方案但存在小错误:

我们首先对远程 URL 进行了正常的 NSURL 调用。并在 - (void)viewDidLoad 中将 webview delegate 设置为 self。

NSURL *url = [NSURL URLWithString:@"localhost:8888/ios/"];
NSURLRequest *requestURL = [NSURLRequest requestWithURL:url];
mainView.delegate = self;
[mainView loadRequest:requestURL];

然后在 - (void)webViewDidFinishLoad:(UIWebView *)webView 中我们创建了一个新的 NSSstring 调用 JS DOM 来注入(inject) .jS 文件到标题中。

NSString * JScode =
@"var script = document.createElement('script');"
"script.type = 'text/javascript';"
"script.src = 'file';"
"document.getElementsByTagName('head')[0].appendChild(script);"
;

由于我们计划在应用程序本地托管 Javascript 和 CSS,因此我们决定调用一个 .jS 文件来加载 css 和 JS 组件。

为了让我们调用实际的 .js 文件,我们必须对实际文件路径执行字符串替换:

JScode = [JScode stringByReplacingOccurrencesOfString:@"file" withString: [[NSBundle mainBundle] pathForResource:@"script" ofType:@"js" inDirectory:@"www"]];

最后我们运行了一个 stringByEvaluatingJavaScriptFromString:JScode 并加载了 .js 文件!

之前:

之后

剩余问题: 无论出于何种原因,代码显示文件已加载但有一个奇怪的 URL,当我们单击它时会出现文件未找到错误。在模拟器之外,JS 代码可以正确执行。

帮忙吗?

最佳答案

我看到至少 2 个选项:

  • 您可以尝试使用 file: URL。问题是它们必须是绝对的,并且安装路径是可变的,因此您可能必须将其发送到服务器,以便他可以返回包含正确 URL 的 HTML。

  • 您可以手动加载 HTML,然后修改它以添加到本地资源的链接,并使用 loadHTMLString:baseURL: 显示它,但是您需要拦截所有进一步的加载webView:shouldStartLoadWithRequest:navigationType: 中的请求(链接点击等)。然后该方法应该做同样的事情(加载 HTML、修改它、显示它)。

编辑:第二个选项的部分代码:

- (void)loadView
{
    [super loadView];
    self.view = [[UIWebView alloc] initWithFrame:[UIScreen mainScreen].applicationFrame];
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"url-from-server"]];

    receivedData = [NSMutableData dataWithCapacity: 0];

    // create the connection with the request
    // and start loading the data
    connection=[[NSURLConnection alloc] initWithRequest:request delegate:self];
    if (!connection) {
        // Release the receivedData object.
        receivedData = nil;

        // Inform the user that the connection failed.
    }
}

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    // This method is called when the server has determined that it
    // has enough information to create the NSURLResponse object.

    // It can be called multiple times, for example in the case of a
    // redirect, so each time we reset the data.

    // receivedData is an instance variable declared elsewhere.
    [receivedData setLength:0];
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    // Append the new data to receivedData.
    // receivedData is an instance variable declared elsewhere.
    [receivedData appendData:data];
}

- (void)connectionDidFinishLoading:(NSURLConnection *)conn
{
    // do something with the data
    // receivedData is declared as a property elsewhere
    NSLog(@"Succeeded! Received %d bytes of data",[receivedData length]);

    NSString *string = [[[NSString alloc] initWithData:receivedData encoding:NSUTF8StringEncoding] stringByReplacingOccurrencesOfString:@"REPLACEME" withString:[[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"test" ofType:@"css"]] absoluteString]];

    [((UIWebView *)self.view) loadHTMLString:string baseURL:[NSURL URLWithString:@""]];

    // Release the connection and the data object
    // by setting the properties (declared elsewhere)
    // to nil.  Note that a real-world app usually
    // requires the delegate to manage more than one
    // connection at a time, so these lines would
    // typically be replaced by code to iterate through
    // whatever data structures you are using.
    connection = nil;
    receivedData = nil;
}

HTML 文件如下所示:

<html>
        <head>
                <link rel="stylesheet" href="REPLACEME" type="text/css">
        </head>
        <body>
                whatever
        </body>
</html>

CSS 名为 test.css

关于javascript - 在 UiWebView 中用本地 Javascript 文件覆盖远程 HTML?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24577788/

有关javascript - 在 UiWebView 中用本地 Javascript 文件覆盖远程 HTML?的更多相关文章

  1. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

  2. ruby - 其他文件中的 Rake 任务 - 2

    我试图在一个项目中使用rake,如果我把所有东西都放到Rakefile中,它会很大并且很难读取/找到东西,所以我试着将每个命名空间放在lib/rake中它自己的文件中,我添加了这个到我的rake文件的顶部:Dir['#{File.dirname(__FILE__)}/lib/rake/*.rake'].map{|f|requiref}它加载文件没问题,但没有任务。我现在只有一个.rake文件作为测试,名为“servers.rake”,它看起来像这样:namespace:serverdotask:testdoputs"test"endend所以当我运行rakeserver:testid时

  3. ruby-on-rails - 在 Rails 中将文件大小字符串转换为等效千字节 - 2

    我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,

  4. ruby-on-rails - Rails 3 中的多个路由文件 - 2

    Rails2.3可以选择随时使用RouteSet#add_configuration_file添加更多路由。是否可以在Rails3项目中做同样的事情? 最佳答案 在config/application.rb中:config.paths.config.routes在Rails3.2(也可能是Rails3.1)中,使用:config.paths["config/routes"] 关于ruby-on-rails-Rails3中的多个路由文件,我们在StackOverflow上找到一个类似的问题

  5. ruby - 将差异补丁应用于字符串/文件 - 2

    对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl

  6. ruby - 使用 ruby​​ 将 HTML 转换为纯文本并维护结构/格式 - 2

    我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h

  7. ruby - 如何将脚本文件的末尾读取为数据文件(Perl 或任何其他语言) - 2

    我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚

  8. ruby - 使用 Vim Rails,您可以创建一个新的迁移文件并一次性打开它吗? - 2

    使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta

  9. ruby - 使用 C 扩展开发 ruby​​gem 时,如何使用 Rspec 在本地进行测试? - 2

    我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当

  10. ruby-on-rails - 在混合/模块中覆盖模型的属性访问器 - 2

    我有一个包含模块的模型。我想在模块中覆盖模型的访问器方法。例如:classBlah这显然行不通。有什么想法可以实现吗? 最佳答案 您的代码看起来是正确的。我们正在毫无困难地使用这个确切的模式。如果我没记错的话,Rails使用#method_missing作为属性setter,因此您的模块将优先,阻止ActiveRecord的setter。如果您正在使用ActiveSupport::Concern(参见thisblogpost),那么您的实例方法需要进入一个特殊的模块:classBlah

随机推荐