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

Swift 4.1从服务器获取图片失败,求解决方案及代码修正

从服务器加载图片到UIImageView/UITableView的问题排查与修复

问题根源梳理

首先看你用Postman测试的初始API返回——它返回的是HTML <img>标签片段+结尾的JSON,完全不是直接的图片二进制数据:

<img src='http://localhost/Book-My-BIM-API/Company-Registration- API/v1/companyImages/harshilpatel@gmail.com_company-registration.jpg' style='height:40%;width:40%;'/>
<img src='http://localhost/Book-My-BIM-API/Company-Registration- API/v1/companyImages/shriyakshah@gmail.com_company-registration.jpg' style='height:40%;width:40%;'/>
...
{"message":"Image displayed Successfully"}

所以你最初的代码直接把data转成UIImage肯定失败,因为那根本不是图片数据。

后来你更新了API,改成了更规范的JSON结构(虽然你贴的内容不完整,但能看出是包含logos数组,每个元素带company_logo图片URL的格式):

{ 
  "logos": [ 
    { 
      "company_logo": "http://172.16.1.22/Book-My-BIM-API/Company-Registration-API/v1/companyImages/harshilpatel@gmail.com_company-registration.

这是正确的方向,但你的代码还有几个关键问题:

  1. 缺失匹配JSON结构的Codable模型定义(你用了ImageData和Images但没贴,大概率和API返回不匹配)
  2. TableView cell复用导致的图片错位问题:异步加载完成后,cell可能已经被复用给其他行
  3. 用try? Data(contentsOf:)同步加载图片,既没有错误处理,还会阻塞线程
  4. 服务器返回的URL用了localhost,模拟器/真机无法访问,需要改成局域网IP(比如你之前用的172.16.1.22)

完整修复方案

1. 定义匹配JSON结构的Codable模型

根据你更新后的API返回,假设完整的JSON结构是:

{
  "logos": [
    {
      "company_logo": "http://172.16.1.22/Book-My-BIM-API/Company-Registration-API/v1/companyImages/xxx.jpg"
    }
  ],
  "message": "Image displayed Successfully"
}

对应的Swift模型:

import Foundation

// 顶层响应模型,匹配API返回的根结构
struct ImageResponse: Codable {
    let logos: [ImageData]
    let message: String
}

// 单个图片数据模型,匹配logos数组中的元素
struct ImageData: Codable {
    let company_logo: String
}

2. 修正网络请求代码

确保正确解析JSON,并且回到主线程更新UI:

func downloadImage(){
    guard let downloadURL = URL(string: "http://172.16.1.22/UploadImage/displayImage.php") else{
        print("无效的请求URL")
        return
    }
    
    URLSession.shared.dataTask(with: downloadURL) { (data, response, error) in
        // 处理请求错误
        if let error = error {
            print("请求失败:\(error.localizedDescription)")
            return
        }
        
        // 确保有返回数据
        guard let data = data else {
            print("未接收到数据")
            return
        }
        
        do {
            let decoder = JSONDecoder()
            // 用定义好的模型解析JSON
            let imageResponse = try decoder.decode(ImageResponse.self, from: data)
            self.imageArray = imageResponse.logos
            
            // 必须回到主线程刷新TableView
            DispatchQueue.main.async {
                self.imageTableVieqw.reloadData()
            }
        } catch {
            print("JSON解析失败:\(error.localizedDescription)")
            // 打印详细错误信息,方便调试
            print("错误详情:\(error)")
        }
    }.resume()
}

3. 修复TableView Cell的图片加载问题

解决cell复用导致的图片错位,同时用异步加载替代阻塞线程的同步请求:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "imageCell", for: indexPath) as! ImageTableViewCell
    
    // 先设置占位图,避免复用旧数据
    cell.imageCell.image = UIImage(named: "placeholder") // 替换成你的占位图名称
    
    let imageURLString = imageArray[indexPath.row].company_logo
    guard let imageURL = URL(string: imageURLString) else {
        print("无效的图片URL:\(imageURLString)")
        return cell
    }
    
    // 用URLSession异步加载图片,不阻塞主线程
    URLSession.shared.dataTask(with: imageURL) { [weak cell] (data, _, error) in
        if let error = error {
            print("图片加载失败:\(error.localizedDescription)")
            return
        }
        
        guard let data = data, let image = UIImage(data: data) else {
            print("无法将数据转为图片")
            return
        }
        
        // 回到主线程更新UI,同时检查cell是否还对应当前行
        DispatchQueue.main.async {
            guard let currentCell = cell, 
                  let currentIndexPath = tableView.indexPath(for: currentCell), 
                  currentIndexPath == indexPath else {
                // cell已经被复用,放弃更新
                return
            }
            currentCell.imageCell.image = image
        }
    }.resume()
    
    return cell
}

4. 解决HTTP访问限制

因为你用的是HTTP协议,iOS默认会阻止非HTTPS请求,需要在Info.plist中添加ATS例外(推荐用更安全的域名白名单方式):

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSExceptionDomains</key>
    <dict>
        <key>172.16.1.22</key>
        <dict>
            <key>NSIncludesSubdomains</key>
            <true/>
            <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
            <true/>
        </dict>
    </dict>
</dict>

额外优化建议

  • 使用成熟的图片加载库(比如SDWebImage、Kingfisher),它们已经帮你处理了缓存、cell复用、错误处理等问题,代码会更简洁:
    比如用SDWebImage的话,cell里的加载代码可以简化为:
    import SDWebImage
    
    // 在cellForRowAt中
    cell.imageCell.sd_setImage(with: imageURL, placeholderImage: UIImage(named: "placeholder"))
    
  • 给图片添加本地缓存,避免重复请求相同图片
  • 处理图片加载失败的情况(比如显示错误占位图)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:35:52