UITableView 在点击屏幕之前不可见
Posted
技术标签:
【中文标题】UITableView 在点击屏幕之前不可见【英文标题】:UITableView not visible until tapped on screen 【发布时间】:2020-07-12 18:43:46 【问题描述】:我是 swift 新手,
我正在开发一个应用程序 对于从服务器获取 URL 的图像,我有 2 个不同的 API 来获取横幅数据和 tableView 数据。
横幅加载并运行后,我正在填充 UITableView, 问题是某个时间(大约 1 分钟)后 UITableView 可见,或者我必须点击屏幕使其可见 当我在屏幕之间切换时,横幅也无法正常滚动。
有人可以查看代码并帮助我解决问题吗?
这是我到目前为止所做的
Controller Code
class CompanyViewController: UIViewController,IndicatorInfoProvider
@IBOutlet weak var tableView: UITableView!
@IBOutlet weak var sliderCollectionView: UICollectionView!
@IBOutlet weak var pageView: UIPageControl!
var activityIndicator: UIActivityIndicatorView=UIActivityIndicatorView()
var imgArr = [UIImage(named: "LoginHeader")]
var imgArrTemp = [String]()
var sectionHeaderName = [String]()
var imageArray = [[String]]()
var sectionImage = [String]()
var timer = Timer()
var counter = 0
override func viewDidLoad()
super.viewDidLoad()
pageView.numberOfPages = imgArr.count
pageView.currentPage = 0
tableView.delegate = self
tableView.dataSource = self
tableView.estimatedRowHeight = 120
tableView.tableFooterView = UIView()
override func viewDidAppear(_ animated: Bool)
super.viewDidAppear(animated)
self.getBannerData()
DispatchQueue.main.async()
self.getCenterData()
self.tableView.reloadData()
func indicatorInfo(for pagerTabStripController: PagerTabStripViewController) -> IndicatorInfo
return IndicatorInfo(title: "COMPANY")
@objc func changeImage()
if counter < imgArr.count
let index = IndexPath.init(item: counter, section: 0)
self.sliderCollectionView.scrollToItem(at: index, at: .centeredHorizontally, animated: true)
pageView.currentPage = counter
counter += 1
else
counter = 0
let index = IndexPath.init(item: counter, section: 0)
self.sliderCollectionView.scrollToItem(at: index, at: .centeredHorizontally, animated: true)
pageView.currentPage = counter
counter = 1
func getCenterData()
let appId = LocalStorage.getStringDataFromLocalStorage(key:Constants.APPID)
let token = "Bearer "+LocalStorage.getStringDataFromLocalStorage(key: Constants.TOKEN)
if let url = URL(string: Constants.EXPERIENCE_CENTER+appId)
var request = URLRequest(url: url)
request.httpMethod = "GET"
request.setValue(token, forHTTPHeaderField:"Authorization")
APIManager.sharedInstance.getCall(request: request)
(data) in
if(!data.isEmpty)
do
let _object = try JSONDecoder().decode(ExperienceCenterModel.self, from: Data(data.utf8))
let data = try JSONEncoder().encode(_object.practice)
let jsonString = String(data: data, encoding: .utf8)!
LocalStorage.saveStringDataInLocalStorage(key: Constants.PRACTICE, value: jsonString)
let technology = try JSONEncoder().encode(_object.technology)
let technologyJsonString = String(data: technology, encoding: .utf8)!
LocalStorage.saveStringDataInLocalStorage(key: Constants.TECTNOLOGY, value: technologyJsonString)
for sectionHeader in _object.practice.data
self.sectionHeaderName.insert(sectionHeader.practiceName!, at: self.sectionHeaderName.count)
self.sectionImage.removeAll()
for images in sectionHeader.experience
let url = images.experienceImage.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)
self.sectionImage.insert(url!, at: self.sectionImage.count)
self.imageArray.insert(self.sectionImage, at: self.imageArray.count)
self.tableView.reloadData()
catch
let nsError = error as NSError
print(nsError.localizedDescription)
func getBannerData()
let defaults = UserDefaults.standard
let appId = defaults.string(forKey: Constants.APPID)
let token = "Bearer "+defaults.string(forKey: Constants.TOKEN)!
if let url = URL(string: Constants.EXPERIENCE_BANNER_CENTER+appId!)
var request = URLRequest(url: url)
request.httpMethod = "GET"
request.setValue(token, forHTTPHeaderField:"Authorization")
APIManager.sharedInstance.getCall(request: request)
(data) in
if(!data.isEmpty)
do
let _object = try JSONDecoder().decode(SliderModel.self, from: Data(data.utf8))
self.imgArr.removeAll()
for images in _object.data
let url = images.experience_image.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)
let imageUrlString = url
let imageUrl:URL = URL(string: imageUrlString!)!
// self.imgArrTemp.insert(url!, at: self.imgArrTemp.count)
// self.pageView.numberOfPages = self.imgArrTemp.count
DispatchQueue.main.async()
let imageData:NSData = NSData(contentsOf: imageUrl)!
self.imgArr.insert(UIImage(data: imageData as Data), at: self.imgArr.count)
self.pageView.numberOfPages = self.imgArr.count
self.stopActivityIndicator()
catch
self.stopActivityIndicator()
self.showAlertMessage(alertMessage: Constants.COMMON_ERROR)
DispatchQueue.main.async
self.timer = Timer.scheduledTimer(timeInterval: 2.0, target: self, selector: #selector(self.changeImage), userInfo: nil, repeats: true)
func startActivityIndicator()
activityIndicator.center = CGPoint(x: 180, y: -40)
activityIndicator.hidesWhenStopped = true
activityIndicator.style = UIActivityIndicatorView.Style.gray
view.addSubview(activityIndicator)
activityIndicator.startAnimating()
UIApplication.shared.beginIgnoringInteractionEvents()
func stopActivityIndicator()
activityIndicator.stopAnimating()
UIApplication.shared.endIgnoringInteractionEvents()
func showAlertMessage(alertMessage:String)
self.stopActivityIndicator()
let alert = UIAlertController(title: "Alert", message: alertMessage, preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "OK", style: .default, handler: action in
switch action.style
case .default:
print("default")
case .cancel:
print("cancel")
case .destructive:
print("destructive")
))
self.present(alert, animated: true, completion: nil)
extension CompanyViewController: UICollectionViewDelegate, UICollectionViewDataSource
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
return 10
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
if(self.imgArr.count > 0)
if let vc = cell.viewWithTag(111) as? UIImageView
if(self.imgArr.count == indexPath.row)
vc.image = self.imgArr[indexPath.row-1]
else
vc.image = self.imgArr[indexPath.row]
return cell
extension CompanyViewController: UICollectionViewDelegateFlowLayout
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets
return UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
let size = sliderCollectionView.frame.size
return CGSize(width: size.width, height: size.height)
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat
return 0.0
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat
return 0.0
extension CompanyViewController: UITableViewDelegate, UITableViewDataSource
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String?
if self.sectionHeaderName.count>0
return self.sectionHeaderName[section]
else
return ""
//NUMBER OF SECTION WE WANT IN A TABLE
func numberOfSections(in tableView: UITableView) -> Int
return self.sectionHeaderName.count
/*NUMNBER OF ROWS IN A SECTION*/
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
return 1
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
return 130
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
guard let cell = tableView.dequeueReusableCell(withIdentifier: "tableViewCell", for: indexPath) as? TableViewCell else fatalError("Unable to create table view cell")
cell.cellDataURI = self.imageArray[indexPath.section]
cell.collectionView.reloadData()
return cell
Table View Cell
的代码
class TableViewCell: UITableViewCell, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout
var cellData = [UIImage]()
var cellDataURI = [String]()
lazy var imageCache: NSCache<NSString,UIImage> =
return NSCache<NSString,UIImage>.init()
()
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
return self.cellDataURI.count
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionCell", for: indexPath) as? CollectionViewCell
let url = cellDataURI[indexPath.row]
guard let image = self.imageCache.object(forKey: NSString(string: url))else
return loadImage(url: URL(string: url)!, cell: cell!, indexPath: indexPath)
cell?.imageView.image = image//cellDataURI[indexPath.row]
return cell!
func loadImage(url: URL,cell: CollectionViewCell, indexPath: IndexPath) -> CollectionViewCell
URLSession.shared.dataTask(with: url)
(rawData, _, _) in
guard let data = rawData else return
guard let image = UIImage.init(data: data) else
return
self.imageCache.setObject(image, forKey: NSString(string: url.absoluteString) )
DispatchQueue.main.async
guard let visCell = self.collectionView.cellForItem(at: indexPath) as? CollectionViewCell else return
visCell.imageView.image = image
.resume()
return cell
func numberOfSections(in collectionView: UICollectionView) -> Int
return 1
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize
let size = CGSize(width: 150, height: 300)
return size
@IBOutlet weak var collectionView: UICollectionView!
override func awakeFromNib()
super.awakeFromNib()
self.collectionView.delegate = self
self.collectionView.dataSource = self
任何帮助将不胜感激
【问题讨论】:
【参考方案1】:您可以使用 dispatch group 运行多个 api 并在所有任务完成时收到通知。然后重新加载tableview
let dispatchGroup = DispatchGroup()
dispatchGroup.enter()
firstApiCall(completion:
dispatchGroup.leave()
)
dispatchGroup.enter()
secondApiCall(completion:
dispatchGroup.leave()
)
dispatchGroup.notify(queue: .main) [weak self] in
print("All Data fetched")
self?.tableView.reloadData()
【讨论】:
以上是关于UITableView 在点击屏幕之前不可见的主要内容,如果未能解决你的问题,请参考以下文章
当单元格不可见时,UITableView indexPathForCell 返回 null