Могу ли я загрузить данные UICollectionView в ViewDidLoad? - PullRequest
0 голосов
/ 01 мая 2018

Экран запуска моего приложения представляет собой коллекцию. Если пользователь выбирает, он / она может «заблокировать» приложение, используя Face ID / Touch ID при запуске приложения. Я делаю это, представляя контроллер представления, который содержит UIVisualEffectView поверх моего контроллера представления коллекции. Я делаю снимок экрана моего контроллера представления коллекции в viewDidLoad, затем помещаю снимок экрана в UIImageView ниже UIVisualEffectView.

Проблема в том, что представление коллекции не загружается, когда делается снимок экрана и появляется контроллер UIVisualEffectView. Снимок экрана содержит панель навигации, но содержимое представления просто черное. Я вызываю функцию для отображения контроллера представления визуальных эффектов в функции viewDidLoad представления коллекции.

Есть ли способ загрузить данные представления коллекции, прежде чем сделать снимок экрана в viewDidLoad? Данные хранятся в Core Data. Я уже пытался переместить функции 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)
}
}

1 Ответ

0 голосов
/ 02 мая 2018

Похоже, вы не можете загрузить содержимое любого представления в viewDidLoad. Согласно Руководству по программированию контроллера Apple View, «viewDidLoad вызывается, когда представление контента контроллера представления (верхняя часть его иерархии представлений) создается и загружается из раскадровки». По сути, он вызывается, когда контроллер представления и его подпредставления загружены, но не видны. ViewDidAppear - это место, где контроллер представления и его подпредставления становятся видимыми. Согласно Руководству по программированию контроллера Apple View, «viewDidAppear вызывается сразу после того, как представление контента контроллера представления было добавлено в иерархию представления приложения». Другими словами, контроллер представления и его подпредставления стали видимыми.

Мне удалось решить мою проблему, хотя ответ на нее не отвечает на этот вопрос. Я добавил ответ на эту проблему в качестве редактирования моего вопроса.

...