Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/434.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript UITableViewCell中的UIWebView仅在第一个单元格中完成加载_Javascript_Ios_Uiwebview - Fatal编程技术网

Javascript UITableViewCell中的UIWebView仅在第一个单元格中完成加载

Javascript UITableViewCell中的UIWebView仅在第一个单元格中完成加载,javascript,ios,uiwebview,Javascript,Ios,Uiwebview,我使用UIWebView作为UITable中每个UITableViewCell的附件视图,以便在每个表视图中显示一个小的Openlayers贴图。当我第一次显示表视图时,第一个单元格中的UIWebView显示地图,但所有其他单元格中的其他UIWebView均为空 如果我上下滚动表格,那么当其他单元格返回视图时,它们都可以正常加载,每个单元格都有各自不同的小地图 UIWebView在init上加载一个初始HMTL文档,该文档包括标准Openlayers ol.js javascript 附件视图U

我使用UIWebView作为UITable中每个UITableViewCell的附件视图,以便在每个表视图中显示一个小的Openlayers贴图。当我第一次显示表视图时,第一个单元格中的UIWebView显示地图,但所有其他单元格中的其他UIWebView均为空

如果我上下滚动表格,那么当其他单元格返回视图时,它们都可以正常加载,每个单元格都有各自不同的小地图

UIWebView在init上加载一个初始HMTL文档,该文档包括标准Openlayers ol.js javascript

附件视图UIView子类是UIWebView的委托,在向其发送另一个javascript以绘制地图特征之前,它会等待UIWebView加载

登录此委托方法会发现web视图
loaded
属性为YES/TRUE,但javascript
readyState
仍在
loading

为什么会这样?我怎样才能使它按预期工作

webView被告知通过调用
drawRect:
方法中的
loadHTMLString:baseURL:
加载通用HTML/javascript。然后使用
webviewdiffinishload:
delegate方法检查加载何时完成,以便在通用HTML/javascript完成后可以运行特定于单元格的javascript

有关守则如下:

- (void)drawRect:(CGRect)rect {
    NSString *path = [NSBundle pathForResource:@"style" ofType:@"html" inDirectory:[[NSBundle mainBundle] bundlePath]];
    NSString *html = [NSString stringWithContentsOfFile:path usedEncoding:nil error:nil];

    [_webView loadHTMLString:html baseURL:[NSURL fileURLWithPath:[path stringByDeletingLastPathComponent] isDirectory:YES]];
}

- (void)webViewDidFinishLoad:(UIWebView *)webView {
    if ( ! _webView.loading ) {
        if ( [[webView stringByEvaluatingJavaScriptFromString:@"document.readyState"] isEqualToString:@"complete"] ) {
            NSLog(@"All good");
            [self drawFeatures];
        } else {
            NSLog(@"ERROR:  webView loaded, readyState '%@'", [webView stringByEvaluatingJavaScriptFromString:@"document.readyState"]);
            //[self performSelector:@selector(drawFeatures) withObject:nil afterDelay:0.5];
        }
    }
}
[self-drawFeatures]
汇编一些javascript并将其发送到UIWebView运行,它依赖于在初始HTML网页中完成的标准Openlayers(ol.js)javascript。)

输出为:

2017-02-26 15:15:00.071 myapp[50443:25603667] ERROR:  webView loaded, readyState 'loading'
2017-02-26 15:15:00.093 myapp[50443:25603667] ERROR:  webView loaded, readyState 'loading'
2017-02-26 15:15:00.116 myapp[50443:25603667] ERROR:  webView loaded, readyState 'loading'
2017-02-26 15:15:00.132 myapp[50443:25603667] ERROR:  webView loaded, readyState 'loading'
2017-02-26 15:15:00.148 myapp[50443:25603667] ERROR:  webView loaded, readyState 'loading'
2017-02-26 15:15:00.166 myapp[50443:25603667] ERROR:  webView loaded, readyState 'loading'
2017-02-26 15:15:00.190 myapp[50443:25603667] ERROR:  webView loaded, readyState 'loading'
2017-02-26 15:15:00.208 myapp[50443:25603667] ERROR:  webView loaded, readyState 'loading'
2017-02-26 15:15:00.226 myapp[50443:25603667] ERROR:  webView loaded, readyState 'loading'
2017-02-26 15:15:00.245 myapp[50443:25603667] ERROR:  webView loaded, readyState 'loading'
2017-02-26 15:15:00.262 myapp[50443:25603667] ERROR:  webView loaded, readyState 'loading'
2017-02-26 15:15:00.292 myapp[50443:25603667] All good
从该输出中可以看到,大多数单元格的
isLoaded
状态为true,而第一个单元格的
isLoaded
状态为true(在真正加载并实际准备就绪后,最后出现)。这意味着web视图认为它已加载,但实际上并没有加载

从未调用loading error delegate方法,因此似乎没有HTML/UIWebView错误:

-(void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error {
    NSLog(@"ERROR loading style view HTML:\n%@", [error description]);
}
请注意,如果我将委托方法更改为仅检查javascript
readyState
,并忽略
isLoading
值,我将永远不会获得complete的
readyState
。只需加载。这大概是因为web视图完成了加载,所以不会再次调用此委托方法

解决有效的问题:

我可以通过取消注释上面委托方法中注释掉的
performSelector:withObject:afterDelay:
来解决这个问题。这表明HTML最终确实加载OK,但委托方法在真正准备就绪后永远不会被调用

我怎样才能让它按预期工作,而不用求助于狡猾的“延迟执行”解决方案

尝试其他方法更新

下面是另一个版本的尝试,部分基于@Ricowere答案中的想法(类似于我开始使用
drawRect:
hack之前的想法)

HTML加载现在在我的UIWebView子类方法中。在这种情况下,适当的方法是在我设置该UIWebView子类的属性时:

- (void)setStyle:(RenderStyle *)style {
    _style = style;

    ...
    ...

    NSString *path = [NSBundle pathForResource:@"style" ofType:@"html" inDirectory:[[NSBundle mainBundle] bundlePath]];
    NSString *html = [NSString stringWithContentsOfFile:path usedEncoding:nil error:nil];

    [self loadHTMLString:html baseURL:[NSURL fileURLWithPath:[path stringByDeletingLastPathComponent] isDirectory:YES]];
}
- (id)initWithFrame:(CGRect)frame {
    if ( self = [super initWithFrame:frame] ) {
        ...
        self.navigationDelegate = self;
    }

    return self;
}

- (void)setStyle:(RenderStyle *)style {
    _style = style;

    NSURL *url = [NSBundle URLForResource:@"style" withExtension:@"html" subdirectory:nil inBundleWithURL:[[NSBundle mainBundle] bundleURL]];

    [self loadFileURL:url allowingReadAccessToURL:[url URLByDeletingLastPathComponent]];
}

- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
    [self drawFeatures];  //  This line runs the secondary instance-dependant javascript that relies on the generic javascript already having been completed
}
然后,在table view委托中,每次表视图单元格出列时,将UIWebView子类视图作为附件视图添加到其中,然后对于该UIWebView子类视图,调用加载HTML的属性方法:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"styleCell"];

    if ( cell == nil ) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"styleCell"];
        ...
        ...
    }

    ...
    ...
    StyleViewUIWebViewSubclass *styleView = [[StyleViewUIWebViewSubclass alloc] initWithFrame:frame];

    cell.accessoryView = styleView;

    styleView.style = [[RenderStyle alloc] initWithString:styles[styleName]];

    return cell;
}

但是,这仍然存在同样的问题。要使其正常工作,仍然需要上面的“延迟执行”解决方案。

首先,删除drawRect中的代码。这种方法完全错误,您将业务逻辑放在绘图方法中。(执行一次,然后重用单元格)

在这里,我向您展示一种简单的方法来解决这个问题

class CellExample: UITableViewCell, UIWebViewDelegate {
    var accessoryWebView: UIWebView? {
        return accessoryView as? UIWebView
    }

    //If you're dequeuing the cell from IB.
    override func awakeFromNib() {
        // Set the frame you need or do this through autolayout.
        let webView = UIWebView(frame: CGRect(x: 0, y: 0, width: 50, height: 50))
        accessoryView = webView
    }

    //You have to call this everytime a cell is dequeued 
    //(Then the content is properly displayed again.)
    func load(url: URL) {
        accessoryWebView?.delegate = self

        //Load the request or the HTML content as you need.

        //accessoryWebView?.loadHTMLString("whatever", baseURL: URL(string: "whatever")!)
//      accessoryWebView?.loadRequest(URLRequest(url: url,
//                                               cachePolicy: .returnCacheDataElseLoad,
//                                               timeoutInterval: 10 ))
    }

    override func prepareForReuse() {
        super.prepareForReuse()

        //If the cell is reused 'restart' the stack.
        accessoryWebView?.delegate = nil
        accessoryWebView?.stopLoading()
    }

    func webViewDidFinishLoad(_ webView: UIWebView) {
        // Do the stuff you need about the javascript.
    }
}

多亏了@Ricowere的一些提示,我的解决方案才得以实现。我的解决方案基于@Ricowere answer的想法,但使用UITableView委托而不是UITableViewCell子类,并在Objective C而不是Swift中完成这一切

这就是最终为我工作的原因

在my WKWebView子类中:

- (void)setStyle:(RenderStyle *)style {
    _style = style;

    ...
    ...

    NSString *path = [NSBundle pathForResource:@"style" ofType:@"html" inDirectory:[[NSBundle mainBundle] bundlePath]];
    NSString *html = [NSString stringWithContentsOfFile:path usedEncoding:nil error:nil];

    [self loadHTMLString:html baseURL:[NSURL fileURLWithPath:[path stringByDeletingLastPathComponent] isDirectory:YES]];
}
- (id)initWithFrame:(CGRect)frame {
    if ( self = [super initWithFrame:frame] ) {
        ...
        self.navigationDelegate = self;
    }

    return self;
}

- (void)setStyle:(RenderStyle *)style {
    _style = style;

    NSURL *url = [NSBundle URLForResource:@"style" withExtension:@"html" subdirectory:nil inBundleWithURL:[[NSBundle mainBundle] bundleURL]];

    [self loadFileURL:url allowingReadAccessToURL:[url URLByDeletingLastPathComponent]];
}

- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
    [self drawFeatures];  //  This line runs the secondary instance-dependant javascript that relies on the generic javascript already having been completed
}
然后在我的UITableViewDelegate中:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"styleCell"];

    if ( cell == nil ) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"styleCell"];
        ...
        WKWebViewSubclass *styleView = [[WKWebViewSubclass alloc] initWithFrame:frame];

        cell.accessoryView = styleView;
    }

    ...
    ((WKWebViewSubclass *)cell.accessoryView).style = [[RenderStyle alloc] initWithString:styleString];

    return cell;
}

它的运行速度似乎比UIWebView慢了一点,这很奇怪,但至少它运行起来没有错误,也没有任何不可靠的解决办法。

啊胡说八道……在给了你100分赏金后,我意识到我仍然有延迟解决办法。在删除此解决办法后,它仍然不起作用。事实上,这是很多就像我在尝试
drawRect:
之前开始做的一样。请查看我问题中的更新,以了解我现在正在尝试的内容(不完全是您发布的内容,但我认为是相同的想法?)。我相信问题是,现在仍然是,当调用所有这些代码时,单元格及其附属视图实际上在屏幕上不可见,而UIWebView不在屏幕上加载HTML。您遇到的问题(主要问题)是,您使用UIWebView和注入Javascript的功能有限。请改用WKWebView。(这一个将考虑DOM加载)我上传了一个正常工作的开放层示例。看看这个。关于您提供的解决方案,请再次查看,因为您重用单元格的方式不正确。您每次都在创建
StyleViewUIWebViewSubclass
,而不是重用它。希望它确实有帮助!:)好的,它现在可以工作了,使用WKWebView而不是UIWebView。我使用UIWebView是为了获取其javascript上下文以进行调试(我不知道是否可以使用WKWebView,这比通过Safari完成要好得多),但我现在已经关闭了javascript,所以不再需要了。WKWebView速度很慢…在加载所有单元格内容之前需要大约2秒钟。但它可以。我将发布我的解决方案作为答案,以显示我所做的