为什么新视图控制器中的表视图不显示?迅速

2024-01-31

这是以下问题的后续:如何调用进行 API 调用的类的实例以及该类中发出请求的函数,并将其分配给变量?迅速 https://stackoverflow.com/questions/72400226/how-to-call-an-instance-of-a-class-that-makes-an-api-call-and-a-function-within.

我试图将一个新的视图控制器推入堆栈,并从初始视图控制器中呈现此视图控制器,但是当我运行程序时,应该在新视图控制器中显示的表视图不会加载在模拟器上。在运行程序之前、期间或之后,我根本没有收到来自 Xcode 的任何错误通知。此外,代码似乎没有在这个新视图控制器中执行,因为新视图控制器类(和视图控制器 .swift 文件)顶部/最开头的打印语句没有被打印。

当应该显示新视图控制器中的新表视图时,显示的是空白屏幕,但导航栏仍在顶部,后退按钮位于导航栏的左上角(就像通常一样)在更改为使用 YelpApi 类进行 API 请求并使用 async/await 之前正确显示表视图时)。发生这种情况时,我也没有在终端中收到任何错误消息。

我认为与该问题相关的是新的 YelpApi 类,该类用于在此处发出 API 端点请求,并使用 async/await。直到我使用这个新类和 async/await 重构代码后才出现这个问题。

我认为更具体地说,可能导致问题的是我在 NewViewController.swift 中的“func viewDidLoad() async {”之前删除了“覆盖”。我这样做是因为我将其留在那里时遇到错误,并找到了建议将其取出的解决方案,但是,正如已接受答案的评论中提到的那样,执行此操作存在问题(问题是没有编译时检查以确保您的签名正确):Swift 协议:方法不会覆盖其超类中的任何方法 https://stackoverflow.com/questions/24380681/swift-protocols-method-does-not-override-any-method-from-its-superclass.

我已经在网上(包括此处)查看过这个问题(表格视图未显示),但找不到可行的解决方案。一篇类似的帖子是这样的:视图控制器未正确显示 https://stackoverflow.com/questions/38782900/view-controller-not-showing-properly但我的代码已经以与接受的答案类似且相同的形式设置。我还让程序运行了 20 分钟,然后退出程序,以防请求由于某种原因花费了很长时间,但是仍然没有呈现所需的表格视图。

Code:

InitialViewController.swift:

//*Code for creating a table view that shows options to the user, for the user to select.*

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        
        //*Code for assigning values to variables related to what row in the table view the user selected.*
        
        
        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        let newVC = storyboard.instantiateViewController(identifier: "NewViewController") as! NewViewController
        newVC.modalPresentationStyle = .fullScreen
        newVC.modalTransitionStyle = .crossDissolve
        
        //Print Check.
        //Prints.
        print("Print Check: Right before code for presenting the new view controller.")

        navigationController?.pushViewController(newVC, animated: true)
        
    }

NewViewController.swift

import UIKit
import CoreLocation

class NewViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
    
    //Print Check.
    //Doesn't print.
    func printCheckBeforeIBOutletTableViewCode() {
        print("Print Check: Right before tableView IBOutlet code at top of NewViewController.swift file.")
    }
    
    @IBOutlet var tableView: UITableView!
    
    var venues: [Venue] = []
    
    //Print Check.
    //Doesn't print.
    func printCheckAfterIBOutletTableViewCode() {
        print("Print Check: Right after tableView IBOutlet code at top of NewViewController.swift file.")
    }
    
    func viewDidLoad() async {
        super.viewDidLoad()
        
        //Function calls for print checks.
        //Doesn't print.
        self.printCheckBeforeIBOutletTableViewCode()
        self.printCheckAfterIBOutletTableViewCode()
        
        tableView.register(UINib(nibName: "CustomTableViewCell", bundle: nil), forCellReuseIdentifier: "CustomTableViewCell")
        tableView.delegate = self
        tableView.dataSource = self
        
        //Print Check.
        //Doesn't print.
        print("Print Check: Right before creating an instance of YelpApi class, then creating a task to make the API request.")
        
        let yelpApi = YelpApi(apiKey: "Api key")
        
        Task {
            do {
                self.venues = try await yelpApi.searchBusiness(latitude: selectedLatitude, longitude: selectedLongitude, category: "category query goes here", sortBy: "sort by query goes here")
                self.tableView.reloadData()
            } catch {
                    //Handle error here.
                    print("Error")
            }
        }
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
           return venues.count
       }
       
       func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
           let cell = tableView.dequeueReusableCell(withIdentifier: "CustomTableViewCell", for: indexPath) as! CustomTableViewCell
           
           //Details for custom table view cell go here.
       }
           
       //Rest of table view protocol functions.
    
}

Venue.swift:

import Foundation

// MARK: - BusinessSearchResult
struct BusinessSearchResult: Codable {
    let total: Int
    let businesses: [Venue]
    let region: Region
}

// MARK: - Business
struct Venue: Codable {
    let rating: Double
    let price, phone, alias: String?
    let id: String
    let isClosed: Bool?
    let categories: [Category]
    let reviewCount: Int?
    let name: String
    let url: String?
    let coordinates: Center
    let imageURL: String?
    let location: Location
    let distance: Double
    let transactions: [String]

    enum CodingKeys: String, CodingKey {
        case rating, price, phone, id, alias
        case isClosed
        case categories
        case reviewCount
        case name, url, coordinates
        case imageURL
        case location, distance, transactions
    }
}

// MARK: - Category
struct Category: Codable {
    let alias, title: String
}

// MARK: - Center
struct Center: Codable {
    let latitude, longitude: Double
}

// MARK: - Location
struct Location: Codable {
    let city, country, address2, address3: String?
    let state, address1, zipCode: String?

    enum CodingKeys: String, CodingKey {
        case city, country, address2, address3, state, address1
        case zipCode
    }
}

// MARK: - Region
struct Region: Codable {
    let center: Center
}

FetchData.swift:

import Foundation
import CoreLocation

class YelpApi {
    
    private var apiKey: String
    
    init(apiKey: String) {
        self.apiKey = apiKey
    }
    
    func searchBusiness(latitude: Double,
                        longitude: Double,
                        category: String,
                        sortBy: String) async throws -> [Venue] {
        
        var queryItems = [URLQueryItem]()
        queryItems.append(URLQueryItem(name:"latitude",value:"\(latitude)"))
        queryItems.append(URLQueryItem(name:"longitude",value:"\(longitude)"))
        queryItems.append(URLQueryItem(name:"categories", value:category))
        queryItems.append(URLQueryItem(name:"sort_by",value:sortBy))
       
        var results = [Venue]()
        
        var expectedCount = 0
        let countLimit = 50
        var offset = 0
        
        queryItems.append(URLQueryItem(name:"limit", value:"\(countLimit)"))
        
        repeat {
            
            var offsetQueryItems = queryItems
            
            offsetQueryItems.append(URLQueryItem(name:"offset",value: "\(offset)"))
            
            var urlComponents = URLComponents(string: "https://api.yelp.com/v3/businesses/search")
            urlComponents?.queryItems = offsetQueryItems
            
            guard let url = urlComponents?.url else {
                throw URLError(.badURL)
            }
            
            var request = URLRequest(url: url)
            request.setValue("Bearer \(self.apiKey)", forHTTPHeaderField: "Authorization")
            
            let (data, _) = try await URLSession.shared.data(for: request)
            let businessResults = try JSONDecoder().decode(BusinessSearchResult.self, from:data)

            expectedCount = min(businessResults.total,1000)
            
            results.append(contentsOf: businessResults.businesses)
            offset += businessResults.businesses.count
        } while (results.count < expectedCount)
        
        return results
    }
}

Thanks!


Update:

根据 Andreas 和 Paulw11 的建议进行更改后,程序运行时表视图仍然没有加载,并且我在终端中得到的最后一个打印语句是“错误”catch块内Task创建 YelpApi 类的实例以发出初始 API 请求后NewViewController.swift。此后,我已将文件中的“错误”语句更改为“发出初始 API 端点请求时发生错误”。为了清楚起见。

以下是更新版本NewViewController.swift根据 Andreas 和 Paulw11 建议的更改,以及FetchData.swift带有新的打印语句以帮助识别新问题。这些更新版本下面是进行 Andreas 和 Paulw11 建议的更改后来自终端的返回语句,其中还包含 FetchData.swift 更新版本中的新打印语句(用于帮助识别新问题)。

更新版本NewViewController.swift with override插入并async带走:

import UIKit
import CoreLocation

class NewViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
    
    //Print Check.
    //Prints.
    func printCheckBeforeIBOutletTableViewCode() {
        print("Print Check: Right before tableView IBOutlet code at top of NewViewController.swift file.")
    }
    
    @IBOutlet var tableView: UITableView!
    
    var venues: [Venue] = []
    
    //Print Check.
    //Prints.
    func printCheckAfterIBOutletTableViewCode() {
        print("Print Check: Right after tableView IBOutlet code at top of NewViewController.swift file.")
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        //Function calls for print checks.
        //Prints.
        self.printCheckBeforeIBOutletTableViewCode()
        self.printCheckAfterIBOutletTableViewCode()
        
        tableView.register(UINib(nibName: "CustomTableViewCell", bundle: nil), forCellReuseIdentifier: "CustomTableViewCell")
        tableView.delegate = self
        tableView.dataSource = self
        
        //Print Check.
        //Prints.
        print("Print Check: Right before creating an instance of YelpApi class, then creating a task to make the API request.")
        
        let yelpApi = YelpApi(apiKey: "Api key")
        
        Task {
            do {
                self.venues = try await yelpApi.searchBusiness(latitude: selectedLatitude, longitude: selectedLongitude, category: "category query goes here", sortBy: "sort by query goes here")
                self.tableView.reloadData()
            } catch {
                    //Handle error here.
                    //Prints.
                    print("Error")
            }
        }
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
           return venues.count
       }
       
       func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
           let cell = tableView.dequeueReusableCell(withIdentifier: "CustomTableViewCell", for: indexPath) as! CustomTableViewCell
           
           //Details for custom table view cell go here.
       }
           
       //Rest of table view protocol functions.
    
}

更新版本FetchData.swift其中包括新的打印语句以帮助识别新问题:

import Foundation
import CoreLocation

class YelpApi {
    
    private var apiKey: String
    
    init(apiKey: String) {
        self.apiKey = apiKey
    }
    
    func searchBusiness(latitude: Double,
                        longitude: Double,
                        category: String,
                        sortBy: String) async throws -> [Venue] {
        
        var queryItems = [URLQueryItem]()
        queryItems.append(URLQueryItem(name:"latitude",value:"\(latitude)"))
        queryItems.append(URLQueryItem(name:"longitude",value:"\(longitude)"))
        queryItems.append(URLQueryItem(name:"categories", value:category))
        queryItems.append(URLQueryItem(name:"sort_by",value:sortBy))
       
        var results = [Venue]()
        
        var expectedCount = 0
        let countLimit = 50
        var offset = 0
        
        queryItems.append(URLQueryItem(name:"limit", value:"\(countLimit)"))
        
        //Print Check.
        //Prints.
        print("Print Check: Line before repeat-while loop.")
        
        repeat {
            
            //Print Check.
            //Prints.
            print("Print Check: Within repeat-while loop and before first line of code within it.")
            
            var offsetQueryItems = queryItems
            
            offsetQueryItems.append(URLQueryItem(name:"offset",value: "\(offset)"))
            
            var urlComponents = URLComponents(string: "https://api.yelp.com/v3/businesses/search")
            urlComponents?.queryItems = offsetQueryItems
            
            guard let url = urlComponents?.url else {
                throw URLError(.badURL)
            }
            
            var request = URLRequest(url: url)
            request.setValue("Bearer \(self.apiKey)", forHTTPHeaderField: "Authorization")
            
            //Print Check.
            //Prints.
            print("Print Check: Within repeat-while loop and before 'let (data, _) = try await' line of code.")
            let (data, _) = try await URLSession.shared.data(for: request)
            
            //Print Check.
            //Prints.
            print("Print Check: Within repeat-while loop and before 'let businessResults = try JSONDecoder()' line of code.")
            let businessResults = try JSONDecoder().decode(BusinessSearchResult.self, from:data)
            
            //Print Check.
            //Doesn't print.
            print("Print Check: Within repeat-while loop and right after 'let businessResults = try JSONDecoder()' line of code.")

            expectedCount = min(businessResults.total,1000)
            
            results.append(contentsOf: businessResults.businesses)
            offset += businessResults.businesses.count
        } while (results.count < expectedCount)
        
        //Print Check.
        //Doesn't print.
        print("Print Check: After repeat-while loop and before 'return results' code.")
        
        return results
    }
}

Returned Print Statements from Terminal Returned After Making Andreas and Paulw11's Suggested Changes and Running Program:

Print Check: Right before code for presenting the new view controller.
Print Check: Right before tableView IBOutlet code at top of NewViewController.swift file.
Print Check: Right after tableView IBOutlet code at top of NewViewController.swift file.
Print Check: Right before creating an instance of YelpApi class, then creating a task to make the API request.
Print Check: Line before repeat-while loop.
Print Check: Within repeat-while loop and before first line of code within it.
Print Check: Within repeat-while loop and before 'let (data, _) = try await' line of code.
Date and Time, Project Name, and some other info [boringssl] boringssl_metrics_log_metric_block_invoke(153) Failed to log metrics
Print Check: Within repeat-while loop and before 'let businessResults = try JSONDecoder()' line of code.
Error occurred when making initial API endpoint request.

必须退出程序,因为它在终端中执行上面最后一条打印语句后“停滞”/没有执行任何操作。

此外,每当我发出 API 请求时,都会出现“日期和时间、项目名称和其他一些信息 [boringssl] Boringssl_metrics_log_metric_block_invoke(153) 无法记录指标”打印语句,并且经过研究,不会对项目。

在“发出初始 API 端点请求时发生错误”之前打印的最后一个打印语句。是“打印检查:在repeat-while循环内和‘letbusinessResults = try JSONDecoder()’代码行之前。”表明代码行出了问题let businessResults = try JSONDecoder().decode(BusinessSearchResult.self, from:data),这让我认为问题可能正在发生并且与附加时有关queryItems for category and sort_by in the searchBusinesses的功能YelpApi类定义在FetchData.swift。我正在努力解决这个问题,如果我解决了这个问题,我会更新。

感谢您的帮助!


我认为您已经发现了其中一个问题。你的代码在func viewDidLoad() async永远不会被执行,因为没有人调用它。通过增加async你没有覆盖原来的UIViewController方法不再了。 (看https://developer.apple.com/documentation/uikit/uiviewcontroller/1621495-viewdidload https://developer.apple.com/documentation/uikit/uiviewcontroller/1621495-viewdidload) 你能删除吗async并再次覆盖它?我认为至少应该执行代码,并且您应该看到打印语句。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么新视图控制器中的表视图不显示?迅速 的相关文章

  • Firebase持久化,清除Firebase缓存

    我的应用程序使用 Firebase 来同步和恢复数据 我用setValue withCompletionBlock 插入 更新和删除 Firebase 对象的方法 每当有 CoreData 保存时就会调用此方法 从而将我的所有本地更改同步到
  • Swift3:如何处理优先组现在运算符应该用主体声明?

    以前的 Swift 3 运算符代码是 infix operator associativity left precedence 150 但现在 根据 Xcode 8 beta 6 这会生成以下警告 operator should not b
  • Xcode:将信息从 UITableViewController 传递到 UIViewController

    我有一个 UIViewController 它应该根据 UITableViewController 中按下的单元格向我显示详细信息 目前我正在给他们讲一个续集 override func prepare for segue UIStoryb
  • Swift 返回类型说明

    我看到一个 Swift 函数写如下 func calculation imageRef CGImage gt red UInt green UInt blue UInt 我需要知道上面函数的返回类型是什么 我无法将它与任何已知类型联系起来
  • 领域对象返回 nil (Swift)

    我有一个自定义多边形对象 因此我可以将地图叠加保存到领域 我能够成功创建这个对象 但是当我想检索 var 多边形对象时 它返回 nil 当我打印多边形对象时 它可以很好地打印出所有数据 这是打印内容的示例 CustomPolygon nam
  • 使用 UIActivityViewController 分享视频

    我正在尝试使用默认的苹果共享屏幕将视频分享到 Twitter 和 Facebook 等 我已经让它与图像一起使用 但我不知道如何更改它以与视频一起使用 提前致谢 这是我用来分享照片的代码 IBAction shareButtonPresse
  • 使用单个共享后台线程进行 iOS 数据处理?

    我有一个应用程序 可以从网络下载大量资源 并对每个资源进行一些处理 我不希望这项工作发生在主线程上 但它非常轻量级且优先级低 因此所有这些都可以真正发生在同一个共享工作线程上 这似乎是一件好事 因为设置和拆除所有这些工作线程都需要工作 没有
  • 在 iOS 框架中嵌入框架

    我有一个包含另一个目标 框架 的项目 它是主项目的依赖项 该框架需要它自己的框架 因此我使用 carthage 添加了它们 该项目在模拟器上编译并运行良好 但是在物理设备上运行时出现以下错误 dyld Library not loaded
  • iOS-图表库:没有支持数据的 x 轴标签不显示

    我正在使用流行的 iOS 图表库 3 1 1 版本 我遇到了 x 轴标签的问题 我似乎无法在网上找到答案 假设我想要一张图表 其中一周的每一天都有一个 x 轴标签 即 S M T W T F S 我读过的很多论坛都建议采用在 x 轴上设置自
  • 处理 UIPageControl 有太多点而无法全部显示在屏幕上的最佳方法是什么

    我的应用程序中有一个 UIPageControl 大约有 10 个页面 点 看起来非常完美 但是用户可以添加许多不同的视图 因此点的数量可能会变成 30 个 发生这种情况时 点就会从屏幕边缘消失 并且您始终无法看到当前选定的页面 这一切看起
  • PutAsync 不会向 Web api 发送请求,但 fiddler 工作正常

    几个小时以来我一直在试图找出问题所在 但我就是找不到问题所在 通过 Mvc 应用程序 put 方法不会被命中 请求不会发生 但是当我在 fiddler 中测试它时 api 中的 PutMethod 可以工作 希望有人能为我解决问题 也欢迎提
  • iOS:如何创建并绘制(并保存)大于屏幕的图像?

    我们正在创建一个 iOS 照片应用程序 为此 我们必须创建动态大小的图像 最大约为 2500x1600 像素 创建此图像后 我们希望以相当快的速度在大图像之上绘制较小的图像 正如我们所看到的 问题在于不可能获得大于屏幕分辨率的上下文 该调用
  • 前导点的自动完成功能无法快速工作

    当我尝试在 swift 中使用 前导点语法 时 我没有得到任何自动完成建议 是否没有实现此自动完成功能 或者是我的 Xcode 版本 6 3 1 有问题 例如 当我尝试这样的事情时 let col UIColor whiteColor 在我
  • 检测wifi是否启用(无论是否连接)

    对于 GPS 跟踪应用程序来说 在打开 WIFI 的情况下记录位置信号会导致数据非常不精确或存在间隙 在开始跟踪之前 我已使用可达性查询来检测 wifi 是否可用 问题是 如果进行该查询时 wifi 已启用但未连接到网络 则表明无法通过 w
  • 本地通知替代周重复

    我有两个通知 我想隔周重复一次 例如 在第一周的星期一设置一个通知 并应在第三周的星期一重复 第二次通知设置在第二周的星期二 并且应在第四周的星期二重复 为此我该怎么办 获取周数 并根据周数做出决定
  • 来自 facebook 的高分辨率图像

    这就是我获取相册和相册中的图片的方式 let connectionPhotos FBSDKGraphRequestConnection let requestPhotos FBSDKGraphRequest graphPath String
  • 基于动态集合视图的 UITableView 的动态高度

    我必须添加一个UICollectionView里面一个UITableViewCell The collectionView可以有不同数量的项目 所以collectionView应在内部适当调整tableView 我已经在我的项目中实现了这个
  • 另一个 - “无法识别的选择器发送到实例”问题

    我查看了有关该主题的每个已发布问题 但没有一个给我解决方案 我的项目在很大程度上复制了开发库中的 AVPlayer 演示应用程序 减去清理功能 我有一个复制和粘贴AVPlayerDemoPlaybackView类 重命名为YOPlaybac
  • 在 Monogame 和 UIKit 之间切换

    我一直在搜索和搜索 但似乎找不到适合我想做的事情的解决方案 而且我几乎已经到了不得不问它是否可能的地步 我正在使用 Xamarin Studio 开发 iOS 应用程序 我有几个不同的屏幕设置为 UIViewController 它们运行良
  • iOS 所需的设备功能自动对焦相机

    我有一个 iOS 应用程序 我在其中设置Required Device Capabilities配置设置需要两者still camera and auto focus camera因为它需要在具有更好的自动对焦相机传感器的新一代设备上运行

随机推荐