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

iOS如何通过HTML字符串在WKWebView中展示手风琴组件

解决方案:在WKWebView中实现手风琴组件展示API数据

问题核心

你当前的错误在于直接把API返回的JSON字符串当作HTML加载,而实际上该JSON包含的是手风琴的标题和描述数组,需要先解析数据,再生成对应的手风琴HTML结构,并添加样式与交互逻辑。

现有代码

let fullDesc = responseDict?["description_middle"]?.string ?? ""
let htmlString:String! = fullDesc 

// self.detailWeb.customUserAgent = "Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 Edge/12.10136"

self.detailWeb.loadHTMLString("<html><body><style>p{align-items:justify;justify-content:justify} h1, h2, h3, h4, h5, h6{font-size:20px; font-weight:bold;} </style><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0,Proxima Nova-Regular\">\(htmlString!)</body></html>", baseURL: nil)

API返回数据

"description_middle": "{\"ac_title\":[\"When Should I take this Service?\",\"What benefits will I get by taking this onsite styling consultation service?\",\"Can I select a Fashion Stylist of my choice for this consultation?\",\"What Happens after I make the Payment?\"],\"ac_description\":[\"<p>You should take this Wardrobe Consultation Service if you are facing any of the following situations:</p>\\r\\n\\r\\n<ul>\\r\\n\\t<li>You are struggling to find clothes that fit and flatter your body type</li>\\r\\n\\t<li>You have a big event coming up and need help putting together the perfect outfit</li>\\r\\n\\t<li>you want to update your professional image and make a great first impression</li>\\r\\n\\t<li>you have a closet full of clothes but nothing to wear</li>\\r\\n\\t<li>you want to build a sustainable wardrobe that is both stylish and environmentally friendly</li>\\r\\n</ul>\\r\\n\",\"<p>Taking a Wardrobe Consultation Service brings you several benefits. Some of those benefits are given below:</p>\\r\\n\\r\\n<ul>\\r\\n\\t<li>Time and Convenience:&nbsp;A personal stylist saves your time and effort by doing the shopping, research and curating outfits for you, freeing up your own time to focus on other things.</li>\\r\\n\\t<li>Increased Confidence:&nbsp;A stylist can help you develop your personal style, which can lead to increased confidence in your appearance and self-esteem.</li>\\r\\n\\t<li>Expertise:&nbsp;Personal stylists have expertise in fashion, body shapes, color analysis and current trends, allowing you to benefit from their professional knowledge and advice.</li>\\r\\n\\t<li>Maximizing Wardrobe:&nbsp;A stylist can help you to get the most out of your existing wardrobe, by creating new outfits and suggesting key pieces to purchase, making the most of your investment.</li>\\r\\n\\t<li>Cost Savings:&nbsp;By investing in a personal stylist, you may save money in the long run by avoiding costly fashion mistakes, and making informed purchases that add value to your wardrobe.</li>\\r\\n</ul>\\r\\n\",\"<p>We would be introducing this feature in future. Until then, StyleBuddy will assign you the best available stylist at the time of your booking.</p>\\r\\n\",\"<p>Our Client Support Team will reach out to you to initiate your service sessions. You will be asked to update a Client Information Form, which is required for the Stylist to prepare for your Service. You can also call or WhatsAPP us on&nbsp;+91-00&nbsp;to enquire about&nbsp;your appointment. This service is available from 10 AM to 7 PM India time except on Sundays.</p>\\r\\n\"]}"

完整实现方案

步骤说明

  1. 解析API返回的JSON字符串,提取手风琴的标题与描述数组
  2. 动态生成手风琴的HTML结构
  3. 内嵌CSS实现手风琴的视觉样式,添加JavaScript处理展开/收起交互
  4. 将完整HTML加载到WKWebView

代码示例

import UIKit
import WebKit

class ViewController: UIViewController, WKNavigationDelegate {
    @IBOutlet weak var detailWeb: WKWebView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        detailWeb.navigationDelegate = self
        
        // 替换为你的实际API响应数据
        guard let fullDesc = responseDict?["description_middle"] as? String,
              let data = fullDesc.data(using: .utf8),
              let accordionData = try? JSONSerialization.jsonObject(with: data) as? [String: [String]],
              let titles = accordionData["ac_title"],
              let descriptions = accordionData["ac_description"],
              titles.count == descriptions.count else {
            detailWeb.loadHTMLString("<html><body><p>加载失败</p></body></html>", baseURL: nil)
            return
        }
        
        // 生成手风琴面板HTML
        var accordionHTML = ""
        for index in 0..<titles.count {
            accordionHTML += """
            <div class="accordion-item">
                <button class="accordion-title" onclick="toggleAccordion(this)">\(titles[index])</button>
                <div class="accordion-content">
                    \(descriptions[index])
                </div>
            </div>
            """
        }
        
        // 完整HTML模板
        let finalHTML = """
        <html>
        <head>
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <style>
                body {
                    font-family: 'Proxima Nova-Regular', sans-serif;
                    margin: 16px;
                }
                p { text-align: justify; }
                ul { padding-left: 20px; }
                
                /* 手风琴核心样式 */
                .accordion-item {
                    margin-bottom: 8px;
                    border: 1px solid #e0e0e0;
                    border-radius: 4px;
                }
                .accordion-title {
                    width: 100%;
                    padding: 12px 16px;
                    text-align: left;
                    background-color: #f5f5f5;
                    border: none;
                    border-radius: 4px;
                    font-size: 16px;
                    font-weight: bold;
                    cursor: pointer;
                    display: flex;
                    justify-content: space-between;
                    align-items: center;
                }
                .accordion-title::after {
                    content: "+";
                    font-size: 20px;
                    transition: transform 0.3s;
                }
                .accordion-title.active::after {
                    transform: rotate(45deg);
                }
                .accordion-content {
                    max-height: 0;
                    overflow: hidden;
                    transition: max-height 0.3s ease-out;
                    padding: 0 16px;
                }
                .accordion-content.active {
                    max-height: 1000px;
                    padding: 12px 16px;
                }
            </style>
        </head>
        <body>
            \(accordionHTML)
            <script>
                function toggleAccordion(button) {
                    button.classList.toggle('active');
                    const content = button.nextElementSibling;
                    content.classList.toggle('active');
                }
                // 默认展开第一个面板(可选)
                document.addEventListener('DOMContentLoaded', () => {
                    const firstTitle = document.querySelector('.accordion-title');
                    firstTitle && toggleAccordion(firstTitle);
                });
            </script>
        </body>
        </html>
        """
        
        detailWeb.loadHTMLString(finalHTML, baseURL: nil)
    }
}

关键说明

  • JSON解析:确保将API返回的字符串转成可操作的数组,避免直接加载原始JSON文本
  • 动态生成结构:通过循环生成每个手风琴面板,保证数据与UI的对应
  • 样式与交互:用CSS实现折叠/展开的过渡动画,JavaScript处理点击事件,实现手风琴核心功能
  • 响应式适配:通过viewport标签确保在移动端屏幕上正常显示

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 16:07:04