简体   繁体   English

我可以在ViewDidLoad中加载UICollectionView的数据吗?

[英]Can I load a UICollectionView's data in ViewDidLoad?

My app's startup screen is a collection view. 我的应用程序的启动屏幕是集合视图。 If the users choose, he/she can "lock" the app using Face ID/Touch ID at app launch. 如果用户选择,则他/她可以在应用启动时使用Face ID / Touch ID“锁定”应用。 I do this by presenting a view controller that contains a UIVisualEffectView on top of my collection view controller. 为此,我在集合视图控制器的顶部提供了一个包含UIVisualEffectView视图控制器。 I screenshot my collection view controller in viewDidLoad , then put the screenshot in a UIImageView beneath the UIVisualEffectView . 我截图我的收藏视图控制器viewDidLoad ,然后将截图中UIImageView的下方UIVisualEffectView

The problem is, the collection view is not loaded when the screenshot is taken and the UIVisualEffectView controller appears. 问题是,截取屏幕截图并显示UIVisualEffectView控制器时,不会加载集合视图。 The screenshot contains the navigation bar, but the content of the view is just black. 屏幕截图包含导航栏,但是视图的内容仅为黑色。 I call the function to display the visual effect view controller in the collection view's viewDidLoad function. 我调用该函数以在集合视图的viewDidLoad函数中显示视觉效果视图控制器。

Is there a way to load the collection view's data before I take a screenshot in viewDidLoad ? viewDidLoad截屏之前,有没有办法加载集合视图的数据? The data is stored in Core Data. 数据存储在核心数据中。 I have already tried moving the Core Data functions from viewWillAppear to viewDidLoad , but that also didn't work. 我已经尝试过将核心数据功能从viewWillAppear移到viewDidLoad ,但这也没有用。

EDIT: I was able to solve my problem, but not by loading my UICollectionView 's data in ViewDidLoad, as that seems to be impossible. 编辑:我能够解决我的问题,但不能通过在ViewDidLoad中加载UICollectionView的数据来解决,因为这似乎是不可能的。 I added a UIVisualEffectView directly on top of my UICollectionView . 我直接在UIVisualEffectView之上添加了UICollectionView I also added it as a subview to UIApplication.shared.keyWindow so that it would appear above the navigation bar. 我还将它作为子视图添加到UIApplication.shared.keyWindow以便它出现在导航栏上方。 The edited code is down below. 编辑后的代码在下面。

Here is my code: 这是我的代码:

For the collection view controller: 对于集合视图控制器:

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
}
}

For the UIVisualEffectView controller: 对于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
    }
}

EDIT: Revised code for my collection view controller: 编辑:我的集合视图控制器的修改的代码:

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)
}
}

It looks like you can't load any view's content in viewDidLoad . 看来您无法在viewDidLoad加载任何视图的内容。 According to the Apple View Controller Programming Guide, " viewDidLoad is called when the view controller's content view (the top of its view hierarchy) is created and loaded from a storyboard." 根据《 Apple View Controller编程指南》,“在从情节提要中创建并加载视图控制器的内容视图(其视图层次结构的顶部)时,将调用viewDidLoad 。” Basically, it's called when the view controller and its subviews are loaded, but not visible. 基本上,它是在加载视图控制器及其子视图但不可见时调用的。 ViewDidAppear is where the view controller and its subviews are made visible. ViewDidAppear是使视图控制器及其子视图可见的地方。 According to the Apple View Controller Programming Guide, " viewDidAppear is called just after the view controller's content view has been added to the app's view hierarchy." 根据《 Apple View Controller编程指南》,“在将视图控制器的内容视图添加到应用程序的视图层次结构之后,将调用viewDidAppear 。” In other words, the view controller and its subviews have been made visible. 换句话说,视图控制器及其子视图已变得可见。

I was able to solve my problem, although the answer to it doesn't answer this question. 我能够解决我的问题,尽管它的答案不能解决这个问题。 I added the answer to that problem as an edit to my question. 我将该问题的答案添加为对我的问题的编辑。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM