You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Swift在iOS UITextView中嵌入带iframe的HTML实现视频播放

UITextView渲染带iframe的HTML内容解决方案

根本原因说明

UITextView通过NSAttributedString加载HTML时,仅支持有限的HTML标签集,iframe标签不在原生支持范围内,所以无法直接渲染。


方案1:占位图+点击唤起播放(最稳妥,兼容性最高)

实现成本低、稳定性高,是无WKWebView可用时的首选方案:

  • 第一步:预处理原始HTML,通过正则匹配提取所有iframe标签的src属性值,同时将iframe标签替换为视频播放占位图对应的<img>标签,可自定义占位图宽高适配排版。
  • 第二步:将处理后的HTML加载为NSAttributedString,同时给占位图对应的富文本范围添加自定义属性,存储对应提取到的视频URL。
  • 第三步:给UITextView添加点击手势识别,点击时判断点击位置的富文本是否携带视频URL属性,存在则唤起AVPlayer/AVPlayerViewController播放对应资源。

核心代码示例

// 匹配iframe提取src的正则示例
NSString *htmlString = @"你的原始HTML内容";
NSString *regexPattern = @"<iframe[^>]+src\\s*=\\s*['\"]([^'\"]+)['\"][^>]*>";
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:regexPattern options:NSRegularExpressionCaseInsensitive error:nil];
NSMutableString *processedHTML = [htmlString mutableCopy];

// 倒序遍历匹配结果,避免替换后range错位
NSArray *matches = [regex matchesInString:htmlString options:0 range:NSMakeRange(0, htmlString.length)];
for (NSTextCheckingResult *result in [matches reverseObjectEnumerator]) {
    NSRange srcRange = [result rangeAtIndex:1];
    NSString *videoURL = [htmlString substringWithRange:srcRange];
    // 替换iframe为占位img标签,可自定义宽高
    NSString *placeholderImgTag = [NSString stringWithFormat:@"<img src='本地占位图资源名' width='300' height='200'/>", videoURL];
    [processedHTML replaceCharactersInRange:result.range withString:placeholderImgTag];
}

// 加载处理后的HTML为富文本
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithData:[processedHTML dataUsingEncoding:NSUTF8StringEncoding] options:@{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType, NSCharacterEncodingDocumentAttribute: @(NSUTF8StringEncoding)} documentAttributes:nil error:nil];
// 给占位图范围添加自定义存储视频URL的属性,此处省略遍历富文本匹配img范围的逻辑
textView.attributedText = attributedString;
// 点击手势处理逻辑
- (void)handleTapOnTextView:(UITapGestureRecognizer *)gesture {
    CGPoint tapLocation = [gesture locationInView:textView];
    UITextPosition *textPosition = [textView closestPositionToPoint:tapLocation];
    NSDictionary *attributes = [textView textStylingAtPosition:textPosition inDirection:UITextStorageDirectionForward];
    NSURL *videoURL = attributes[自定义视频URL属性名];
    if (videoURL) {
        // 唤起播放器
        AVPlayerViewController *playerVC = [[AVPlayerViewController alloc] init];
        playerVC.player = [AVPlayer playerWithURL:videoURL];
        [self presentViewController:playerVC animated:YES completion:^{
            [playerVC.player play];
        }];
    }
}

方案2:NSTextAttachment嵌入原生视频视图(适合需在文本流内直接播放的场景)

如果要求视频直接在文本流内播放无需跳转,可采用本方案:

  • 第一步:同方案1,匹配提取所有iframe的视频地址,记录每个iframe在原始HTML中的位置和尺寸。
  • 第二步:创建自定义NSTextAttachment,对应每个视频的占位位置,设置attachment的bounds为预期的视频渲染尺寸。
  • 第三步:将原始HTML中iframe标签替换为对应attachment的占位标记,加载生成富文本后,将自定义的带AVPlayerLayer的视图添加到UITextView的对应坐标位置,监听滚动事件调整视图位置实现跟随富文本滚动。

注意事项

  • 如果iframe的src是第三方平台的嵌入网页而非直链视频流,AVPlayer无法直接播放,可根据需求选择跳转系统浏览器打开对应URL,或单独解析嵌入页的实际视频资源地址。
  • 加载HTML时需明确指定NSDocumentTypeDocumentAttribute为NSHTMLTextDocumentType,编码指定为UTF-8,避免普通HTML内容渲染异常。
  • 需将UITextView的isEditable设为NO,避免误触编辑状态影响交互。

内容的提问来源于stack exchange,提问作者Chrishan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.30 05:54:06