我试图在桌面视图中将Instagram帖子添加到单元格中,但是尽管尝试了很多不同的东西,但我无法正确计算单元格高度。我为每个单元格创建了一个WKWebView
,并使用Instagram提供的嵌入代码loadHTMLString
,对Instagram的HTML进行了一些修改:
`<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"></head>`
当我在模拟器中运行它时,Instagram帖子似乎是正确的大小大约半秒钟,然后它被调整大小。
以下是一些基本代码,用于演示运行时的问题,单个硬编码的Instagram帖子显示在两个不同的单元格中,例如用途。如果我将loadRequest
和NSURLRequest
与随机网站而不是loadHTMLString
一起使用,则单元格大小合适,并且一切都按预期工作。如何在UITableViewCells中使用Instagram嵌入代码,以显示整个帖子?
InstagramViewController.h
#import <UIKit/UIKit.h>
#import <WebKit/WebKit.h>
@interface InstagramViewController : UIViewController <WKNavigationDelegate, WKUIDelegate, UITableViewDelegate, UITableViewDataSource>
@property (strong, nonatomic) IBOutlet WKWebView *webView;
@property (strong, nonatomic) IBOutlet UITableView *tableView;
@end
InstagramViewController.m
#import "InstagramViewController.h"
@interface InstagramViewController ()
@property (nonatomic) BOOL loaded;
@property (nonatomic) CGFloat cellHeight;
@end
@implementation InstagramViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.tableView.estimatedRowHeight = 150;
self.tableView.rowHeight = UITableViewAutomaticDimension;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 2;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *simpleTableIdentifier = @"simpleTableIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:simpleTableIdentifier];
}
WKWebViewConfiguration *theConfiguration = [[WKWebViewConfiguration alloc] init];
WKWebView *webView = [[WKWebView alloc] initWithFrame:cell.contentView.frame configuration:theConfiguration];
webView.navigationDelegate = self;
[webView.scrollView setScrollEnabled:NO];
webView.autoresizingMask = UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth;
webView.tag = indexPath.section;
NSString *instagramEmbedHTML = @"\
<!DOCTYPE html>\
<html>\
<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\
</head>\
<body>\
<blockquote class=\"instagram-media\" data-instgrm-captioned data-instgrm-version=\"7\" style=\" background:#FFF; border:0; border-radius:3px; box-shadow:0 0 1px 0 rgba(0,0,0,0.5),0 1px 10px 0 rgba(0,0,0,0.15); margin: 1px; max-width:658px; padding:0; width:99.375%; width:-webkit-calc(100% - 2px); width:calc(100% - 2px);\">\
<div style=\"padding:8px;\">\
<div style=\" background:#F8F8F8; line-height:0; margin-top:40px; padding:41.91489361702128% 0; text-align:center; width:100%;\">\
<div style=\" background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACwAAAAsCAMAAAApWqozAAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAAAMUExURczMzPf399fX1+bm5mzY9AMAAADiSURBVDjLvZXbEsMgCES5/P8/t9FuRVCRmU73JWlzosgSIIZURCjo/ad+EQJJB4Hv8BFt+IDpQoCx1wjOSBFhh2XssxEIYn3ulI/6MNReE07UIWJEv8UEOWDS88LY97kqyTliJKKtuYBbruAyVh5wOHiXmpi5we58Ek028czwyuQdLKPG1Bkb4NnM+VeAnfHqn1k4+GPT6uGQcvu2h2OVuIf/gWUFyy8OWEpdyZSa3aVCqpVoVvzZZ2VTnn2wU8qzVjDDetO90GSy9mVLqtgYSy231MxrY6I2gGqjrTY0L8fxCxfCBbhWrsYYAAAAAElFTkSuQmCC); display:block; height:44px; margin:0 auto -44px; position:relative; top:-22px; width:44px;\">\
</div>\
</div>\
<p style=\" margin:8px 0 0 0; padding:0 4px;\">\
<a href=\"https://www.instagram.com/p/BVR2uajF1Qc/\" style=\" color:#000; font-family:Arial,sans-serif; font-size:14px; font-style:normal; font-weight:normal; line-height:17px; text-decoration:none; word-wrap:break-word;\" target=\"_blank\">I wish for... free cupcakes!! First 50 customers at our #Gramercy location get a free #Summer Collection 3-Pack to celebrate 5 beautiful, magical years on 23rd St! Today only! Open 'til 10pm #happybirthday</a>\
</p>\
<p style=\" color:#c9c8cd; font-family:Arial,sans-serif; font-size:14px; line-height:17px; margin-bottom:0; margin-top:8px; overflow:hidden; padding:8px 0 7px; text-align:center; text-overflow:ellipsis; white-space:nowrap;\">A post shared by Baked by Melissa (@bakedbymelissa) on <time style=\" font-family:Arial,sans-serif; font-size:14px; line-height:17px;\" datetime=\"2017-06-13T12:00:48+00:00\">Jun 13, 2017 at 5:00am PDT</time>\
</p>\
</div>\
</blockquote>\
<script async defer src=\"http://platform.instagram.com/en_US/embeds.js\"></script>\
</body></html>";
[webView loadHTMLString:instagramEmbedHTML baseURL:nil];
[cell.contentView addSubview:webView];
return cell;
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return [self calculateHeightForCellAtIndexPath:indexPath];
}
-(CGFloat)calculateHeightForCellAtIndexPath:(NSIndexPath *)indexP{
while (!_loaded) {
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
}
NSLog(@"new cell height: %f", _cellHeight);
return _cellHeight;
}
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
NSLog(@"I finished");
[webView evaluateJavaScript:@"document.body.scrollHeight;" completionHandler:^(NSString *result, NSError *error) {
if (error != NULL) {
NSLog(@"Error %@",error);
}
NSLog(@"new scrollHeight Result %@",result);
float ht = [result floatValue];
NSIndexPath* indexOfCell = [NSIndexPath indexPathForRow:0 inSection:webView.tag];
UITableViewCell* cell = [self.tableView cellForRowAtIndexPath:indexOfCell];
cell.frame = CGRectMake(0, 0, cell.frame.size.width, ht);
_cellHeight = ht;
self.loaded = YES;
}];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
@end
这里是我运行上面代码时获得的输出的屏幕截图,其中您可以看到嵌入的大小超过计算单元格高度的大小,在这种情况下切断整个注释部分:< / p>
答案 0 :(得分:0)
我已经为此苦苦挣扎很长时间了。此解决方案对我有用。
您将获得适当的高度。从那时起,您的任务就是处理它并设置容器的高度。
警告:这并不简单。
注意:Instagram和Twitter嵌入在这里真是可怕的动物。他们的脚本计算宽度ot 621(!)的高度,并将其设置为iframe的属性。因此,您“简单”(LOL)必须重新计算大小。请参阅新属性“ modded”,以避免多次设置高度。
没有跨域限制。您无法读取/更改从不同于baseURL-s域的网址加载的iframe内容。那太容易了,但是浏览器有一个很好的理由就拒绝了。
这是使用HTML,CSS,Javascript,当然还有Swift的混合解决方案。
func initMyWebView() {
//...
let contentController = WKUserContentController()
let config = WKWebViewConfiguration()
config.preferences = preferences
config.allowsInlineMediaPlayback = true
config.userContentController = contentController
config.mediaTypesRequiringUserActionForPlayback = []
contentController.add(
self,
name: "heightChanged"
)
contentController.add(
self,
name: "log"
)
contentController.removeAllUserScripts()
contentController.addUserScript(WKUserScript(source: windowSizeWatcherScript(), injectionTime: .atDocumentEnd, forMainFrameOnly: true))
// ...
}
func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
if message.name == "log" {
print("JSLog: " + String(describing: message.body))
return
}
if message.name == "heightChanged" {
if let messageDict = message.body as? Dictionary<String, CGFloat> {
if nil != messageDict["height"] {
DispatchQueue.main.async { [weak self] in
// Implement the height update to your needs
self?.updateHeight(height: messageDict["height"]!)
}
}
}
return
}
}
func style(jsonStyle: JSONTextStyleModel?) -> String {
let maxHTMLW = bounds.width
return """
html, body {
margin: 0 !important;
padding: 0 !important;
width: 100% !important;
max-width: \(maxHTMLW)px !important;
min-width: \(maxHTMLW)px !important;
}
body {
font-family: Roboto;
background-color: \(Theme.shared.generalColors.background);
color: \((jsonStyle?.color).defaultsTo(value: "#333"));
font-size: 16px;
font-weight: 300;
}
#\(contentId) {
margin: 0 2% !important;
padding: 0 !important;
height: 100%;
display: block;
width: 96%;
}
iframe {
width: 100% !important;
}
iframe.instagram-media-rendered {
}
"""
}
func online(html: String, with style: String) -> String {
return """
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
\(style)
</style>
</head>
<body>
<div id="\(contentId)">
\(html)
</div>
</body>
</html>
"""
}
func windowSizeWatcherScript() -> String {
let maxInstaW = bounds.width * 0.96
return """
var prevHeight = 0;
var prevWidth = 0;
var contentId = "\(contentId)";
customLog("windowSizeWatcherScript added")
var resizeTimeout = setTimeout(function () { resize(); }, 125);
if (typeof(webkit) !== 'undefined' && typeof(webkit.messageHandlers.log) !== 'undefined') {
console.log = customLog;
}
function resize() {
clearTimeout(resizeTimeout);
resizeTimeout = setTimeout('resize();', 250);
if (typeof(webkit) == 'undefined' || typeof(webkit.messageHandlers.heightChanged) == 'undefined') {
customLog("Cannot send webkit messages");
return;
}
if (resizeInsta()) {
return
}
if (resizeTwitter()) {
return
}
if (resizeIframes()) {
return
}
if (resizeContent()) {
return
}
resizeDocument()
}
function customLog(message) {
if (typeof(webkit) == "undefined" || typeof(webkit.messageHandlers.log) == "undefined") {
console.log("No native app context");
console.log(message)
return
}
try { webkit.messageHandlers.log.postMessage(message);} catch (err) { console.log("No native app context"); }
}
function handleSize(width, height) {
if (height > 0 && prevHeight != height) {
customLog("W: " + width + " H: " + height);
try { webkit.messageHandlers.heightChanged.postMessage({"height": height});} catch (err) { customLog("No native app context"); }
customLog("Detected width " + width + " and height " + height);
prevHeight = height;
}
}
function resizeInsta() {
var insta = document.getElementsByClassName("instagram-media-rendered");
if (typeof(insta) !== "undefined" && insta.length > 0) {
var width = insta[0].offsetWidth;
var height = Math.max(insta[0].scrollHeight, insta[0].offsetHeight);
var h = insta[0].getAttribute("height")
if (h !== "undefined" && h > 0) {
var modded = insta[0].getAttribute("modded")
if (modded == "undefined") {
h = h.replace("px", "")
let r = \(maxInstaW) / 621;
height = h * r;
width = \(Int(maxInstaW));
insta[0].setAttribute("height", height + "px");
insta[0].setAttribute("modded", "1");
insta[0].setAttribute("width", "\(Int(maxInstaW))px");
}
}
handleSize(width, height)
return true;
}
return false;
}
function resizeTwitter() {
var insta = document.getElementsByClassName("twitter-tweet-rendered");
if (typeof(insta) !== "undefined" && insta.length > 0) {
var width = insta[0].offsetWidth;
var height = Math.max(insta[0].scrollHeight, insta[0].offsetHeight);
var h = insta[0].getAttribute("height")
if (h !== "undefined" && h > 0) {
var modded = insta[0].getAttribute("modded")
if (modded == "undefined") {
h = h.replace("px", "")
let r = \(maxInstaW) / 621;
height = h * r;
width = \(Int(maxInstaW));
insta[0].setAttribute("height", height + "px");
insta[0].setAttribute("modded", "1");
insta[0].setAttribute("width", "\(Int(maxInstaW))px");
}
}
handleSize(width, height)
return true;
}
return false;
}
function resizeIframes() {
var iframes = document.getElementsByTagName("iframe");
if (typeof(iframes) !== "undefined" && iframes.length > 0) {
var width = iframes[0].offsetWidth;
var height = Math.max(iframes[0].scrollHeight, iframes[0].offsetHeight);
handleSize(width, height)
return true
}
return false
}
function resizeContent() {
var content = document.getElementById(contentId);
if (typeof(content) !== 'undefined') {
var width = content.offsetWidth;
var height = Math.max(content.scrollHeight, content.offsetHeight);
handleSize(width, height)
return true
}
return false
}
function resizeDocument() {
var width = document.body.offsetWidth;
var height = Math.max(document.body.scrollHeight, document.body.offsetHeight);
handleSize(width, height)
return true
}
"""
}