ios - 我可以在 ViewDidLoad 中加载 UICollectionView 的数据吗?
问题描述
我的应用程序的启动屏幕是一个集合视图。如果用户选择,他/她可以在应用启动时使用 Face ID/Touch ID “锁定”应用。我通过展示一个视图控制器来做到这一点,该控制器UIVisualEffectView
在我的集合视图控制器之上包含一个。我在 中截取我的集合视图控制器viewDidLoad
,然后将截屏UIImageView
放在UIVisualEffectView
.
问题是,在截取屏幕截图并UIVisualEffectView
出现控制器时未加载集合视图。屏幕截图包含导航栏,但视图的内容只是黑色的。我调用该函数在集合视图的viewDidLoad
函数中显示视觉效果视图控制器。
有没有办法在我截屏之前加载集合视图的数据viewDidLoad
?数据存储在核心数据中。我已经尝试将 Core Data 函数从 移动viewWillAppear
到viewDidLoad
,但这也没有用。
编辑:我能够解决我的问题,但不能通过UICollectionView
在 ViewDidLoad 中加载我的数据,因为这似乎是不可能的。我UIVisualEffectView
直接在我的UICollectionView
. 我还将它添加为子视图,UIApplication.shared.keyWindow
以便它出现在导航栏上方。编辑后的代码在下面。
这是我的代码:
对于集合视图控制器:
import UIKit
import CoreData
import LocalAuthentication
var ssImage: UIImage?
class AlbumViewController: UIViewController {
// MARK: - Properties
@IBOutlet weak var albumCollectionView: UICollectionView!
var albums: [NSManagedObject] = []
// MARK: - Actions
func getScreenShot()-> UIImage? {
var screenshotImage :UIImage?
let layer = UIApplication.shared.keyWindow!.layer
let scale = UIScreen.main.scale
UIGraphicsBeginImageContextWithOptions(layer.frame.size, false, scale);
guard let context = UIGraphicsGetCurrentContext() else {return nil}
layer.render(in:context)
screenshotImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
ssImage = screenshotImage
print("Got screenshot.")
return screenshotImage
}
// ViewDidLoad and ViewWillAppear
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
//Core Date functions
guard let appDelegate =
UIApplication.shared.delegate as? AppDelegate else {
return
}
let managedContext =
appDelegate.persistentContainer.viewContext
let fetchRequest =
NSFetchRequest<NSManagedObject>(entityName: "Album")
let sortDescriptor = NSSortDescriptor(key: "albumName", ascending: true, selector: #selector(NSString.localizedCaseInsensitiveCompare(_:)))
fetchRequest.sortDescriptors = [sortDescriptor]
do {
albums = try managedContext.fetch(fetchRequest)
} catch let error as NSError {
print("Could not fetch. \(error), \(error.userInfo)")
}
//Setup
self.albumCollectionView.reloadData()
}
override func viewDidLoad() {
super.viewDidLoad()
if AppSettings.requiresLogin == true {
getScreenShot()
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let rootController = storyboard.instantiateViewController(withIdentifier: "authenticateVC") as! LockedLaunchVC
self.present(rootController, animated: false, completion: nil)
}
}
//Core Data functions
func save(name: String) {
guard let appDelegate =
UIApplication.shared.delegate as? AppDelegate else {
return
}
let managedContext =
appDelegate.persistentContainer.viewContext
let entity =
NSEntityDescription.entity(forEntityName: "Album",
in: managedContext)!
let albumName = NSManagedObject(entity: entity,
insertInto: managedContext)
albumName.setValue(name, forKeyPath: "albumName")
do {
try managedContext.save()
albums.append(albumName)
} catch let error as NSError {
print("Could not save. \(error), \(error.userInfo)")
}
}
}
//Collection View functions
extension AlbumViewController: UICollectionViewDataSource, UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return albums.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let reuseIdentifier = "AlbumCell"
// get a reference to our storyboard cell
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath as IndexPath) as! AlbumsViewCell
//Core Data methods
let albumName = albums[indexPath.row]
cell.albumNameLabel?.text = albumName.value(forKeyPath: "albumName") as? String
//Return the finished cell
return cell
}
}
对于 UIVisualEffectView 控制器:
import UIKit
import LocalAuthentication
class LockedLaunchVC: UIViewController {
let bioIDAuth = BiometricIDAuth()
@IBOutlet weak var screenshotImageView: UIImageView!
@IBAction func unlockButtonTapped(_ sender: UIButton) {
authAndDismiss()
}
func authAndDismiss(){
bioIDAuth.authenticateUser() {
self.dismiss(animated: true, completion: nil)
print("Locked VC dismissed.")
}
}
override func viewDidLoad() {
super.viewDidLoad()
self.modalTransitionStyle = .crossDissolve
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
screenshotImageView.image = ssImage
}
}
编辑:我的集合视图控制器的修订代码:
import UIKit
import CoreData
class AlbumViewController: UIViewController {
// MARK: - Properties
@IBOutlet weak var albumCollectionView: UICollectionView!
@IBOutlet weak var lockedBlurView: UIVisualEffectView!
@IBOutlet weak var lockedLabelView: UIView!
@IBOutlet weak var lockedLabel: UILabel!
var albums: [NSManagedObject] = []
let bioIDAuth = BiometricIDAuth()
// MARK: - Actions
@IBAction func unwindToAlbumsScreen(sender: UIStoryboardSegue) {
}
@IBAction func unlockButtonTapped(_ sender: UIButton) {
bioIDAuth.authenticateUser() {
UIView.animate(withDuration: 0.25, animations: {self.lockedBlurView.alpha = 0})
}
}
// ViewDidLoad and ViewWillAppear
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
//Core Date functions
guard let appDelegate =
UIApplication.shared.delegate as? AppDelegate else {
return
}
let managedContext =
appDelegate.persistentContainer.viewContext
let fetchRequest =
NSFetchRequest<NSManagedObject>(entityName: "Album")
let sortDescriptor = NSSortDescriptor(key: "albumName", ascending: true, selector: #selector(NSString.localizedCaseInsensitiveCompare(_:)))
fetchRequest.sortDescriptors = [sortDescriptor]
do {
albums = try managedContext.fetch(fetchRequest)
} catch let error as NSError {
print("Could not fetch. \(error), \(error.userInfo)")
}
//Setup to do when the view will appear
self.albumCollectionView.reloadData()
}
override func viewDidLoad() {
super.viewDidLoad()
lockedLabelView.layer.cornerRadius = 12
switch bioIDAuth.biometricType() {
case .faceID:
lockedLabel.text = "Albums are locked. Tap anywhere to use Face ID to unlock."
case .touchID:
lockedLabel.text = "Albums are locked. Tap anywhere to use Touch ID to unlock."
default:
lockedLabel.text = "Albums are locked. Tap anywhere to use your passcode to unlock."
}
if AppSettings.requiresLogin == false {
lockedBlurView.alpha = 0
}
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
if AppSettings.requiresLogin == true {
let curWin = UIApplication.shared.keyWindow
curWin?.addSubview(lockedBlurView)
}
}
//Core Data functions
func save(name: String) {
guard let appDelegate =
UIApplication.shared.delegate as? AppDelegate else {
return
}
let managedContext =
appDelegate.persistentContainer.viewContext
let entity =
NSEntityDescription.entity(forEntityName: "Album",
in: managedContext)!
let albumName = NSManagedObject(entity: entity,
insertInto: managedContext)
albumName.setValue(name, forKeyPath: "albumName")
do {
try managedContext.save()
albums.append(albumName)
} catch let error as NSError {
print("Could not save. \(error), \(error.userInfo)")
}
}
}
//Collection View functions
extension AlbumViewController: UICollectionViewDataSource, UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return albums.count
}
// make a cell for each cell index path
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let reuseIdentifier = "AlbumCell"
// get a reference to our storyboard cell
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath as IndexPath) as! AlbumsViewCell
//Core Data methods
let albumName = albums[indexPath.row]
cell.albumNameLabel?.text = albumName.value(forKeyPath: "albumName") as? String
//Return the finished cell
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let albumNameFromCell = albums[indexPath.row]
albumNameTapped = albumNameFromCell.value(forKeyPath: "albumName") as! String
self.performSegue(withIdentifier: "albumCellTappedSegue", sender: self)
}
}
解决方案
看起来您无法在viewDidLoad
. 根据 Apple View Controller Programming Guide,“viewDidLoad
在创建视图控制器的内容视图(其视图层次结构的顶部)并从情节提要加载时调用。” 基本上,它在视图控制器及其子视图被加载但不可见时被调用。 ViewDidAppear
是视图控制器及其子视图可见的地方。根据 Apple 视图控制器编程指南,“viewDidAppear
在视图控制器的内容视图被添加到应用程序的视图层次结构后立即调用。” 换句话说,视图控制器及其子视图已经可见。
我能够解决我的问题,尽管它的答案没有回答这个问题。我添加了该问题的答案作为对我的问题的编辑。
推荐阅读
- json - 错误 data.forEach 不是函数(如何提取对象的 Json 对象)
- python - Python - 从嵌套列表中提取值
- arrays - 组合对象流中的数组
- python - 读取文件并用 python 替换 LF,但不是 CR-LF
- r - 用循环绑定嵌套列表中的 tibbles 行,无论 tibbles 的数量是多少
- c# - 如何为 iText7 / pdfhtml 设置默认字体
- azure-cosmosdb - Azure 为存储在 CosmosDB 中的图形数据提供了可视化工具
- excel - Excel 2013 使用查询获取 sql server 数据
- c++ - 从我的类到字符串的隐式和显式转换
- c - 我可以在不为我计算的情况下打印出一个 int 吗(带有“+”符号和前后两个数字)在 c 中?