由于未捕获的异常 'NSInvalidArgumentException' 而终止应用程序,原因:'UICollectionView must be initialized with a non-nil layout parameter'

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'UICollectionView must be initialized with a non-nil layout parameter'

我试图在 CollectionViewController 中显示一个 imagePicker 然后我遇到了如下错误。

Error:-

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'UICollectionView must be initialized with a non-nil layout parameter'
*** First throw call stack:
(
    0   CoreFoundation                      0x00007fff20421af6 __exceptionPreprocess + 242
    1   libobjc.A.dylib                     0x00007fff20177e78 objc_exception_throw + 48
    2   CoreFoundation                      0x00007fff204219d4 -[NSException initWithCoder:] + 0
    3   UIKitCore                           0x00007fff23d6caf5 -[UICollectionView initWithFrame:collectionViewLayout:] + 205
    4   UIKitCore                           0x00007fff23e72b06 -[UICollectionViewController _newCollectionViewWithFrame:collectionViewLayout:] + 75
    5   UIKitCore                           0x00007fff23e71e7d -[UICollectionViewController loadView] + 1461
    6   UIKitCore                           0x00007fff23f62947 -[UIViewController loadViewIfRequired] + 172
    7   UIKitCore                           0x00007fff23f630c1 -[UIViewController view] + 27
    8   UIKitCore                           0x00007fff23e421fe -[UIPresentationController __sizeClassPair] + 62
    9   UIKitCore                           0x00007fff23f75e46 -[UIViewController _presentViewController:withAnimationController:completion:] + 2429
    10  CoreFoundation                      0x00007fff204282fc __invoking___ + 140
    11  CoreFoundation                      0x00007fff204257b6 -[NSInvocation invoke] + 303
    12  UIKitCore                           0x00007fff23f70333 -[UIViewController _endDelayingPresentation] + 277
    13  UIKitCore                           0x00007fff23e799a2 -[UIImagePickerController _handleEndingPhotoPickerPresentationDelay] + 53
    14  libdispatch.dylib                   0x00000001037f37ec _dispatch_call_block_and_release + 12
    15  libdispatch.dylib                   0x00000001037f49c8 _dispatch_client_callout + 8
    16  libdispatch.dylib                   0x0000000103802e75 _dispatch_main_queue_callback_4CF + 1152
    17  CoreFoundation                      0x00007fff2038fdbb __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9
    18  CoreFoundation                      0x00007fff2038a63e __CFRunLoopRun + 2685
    19  CoreFoundation                      0x00007fff203896d6 CFRunLoopRunSpecific + 567
    20  GraphicsServices                    0x00007fff2c257db3 GSEventRunModal + 139
    21  UIKitCore                           0x00007fff24696cf7 -[UIApplication _run] + 912
    22  UIKitCore                           0x00007fff2469bba8 UIApplicationMain + 101
    23  Demo_App                            0x000000010139600b main + 75
    24  libdyld.dylib                       0x00007fff2025a3e9 start + 1
    25  ???                                 0x0000000000000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException

这是我的 AppDelegate.swift

class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?
    
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
        window = UIWindow()
        window?.makeKeyAndVisible()

        //get rid of shadow
        UINavigationBar.appearance().shadowImage = UIImage()
        UINavigationBar.appearance().setBackgroundImage(UIImage(), for: .default)

        let layout = type(of: UICollectionViewFlowLayout()).init()
        window?.rootViewController = UINavigationController(rootViewController: DemoApplicationController(collectionViewLayout: layout))
        FirebaseApp.configure()
        return true
    }
}

这里是 CollectionViewControllerDemoApplicationController.Swift

class DemoApplicationController: UICollectionViewController, UICollectionViewDelegateFlowLayout{
  
    override func viewDidLoad() {
        super.viewDidLoad()

        //title Label
        navigationController?.navigationBar.isTranslucent = false
        let titleLabel = UILabel(frame: CGRect(x: 0, y: 0, width: view.frame.width - 250, height: view.frame.height))
        titleLabel.text = "Demo Application"
        titleLabel.font = UIFont(name: "HelveticaNeue-Bold", size: 20)
        navigationItem.titleView = titleLabel
        titleLabel.textColor = UIColor(red: 0.12, green: 0.56, blue: 1.00, alpha: 1.00)
        setupCollectionView()
    }
    
   lazy var enroll: EnrollCell = {
        let en = EnrollCell()
        en.demoController = self
        return en
    }()
    
    func setupCollectionView() {
        if let flowLayout = collectionView?.collectionViewLayout as? UICollectionViewFlowLayout {
            flowLayout.scrollDirection = .horizontal
            flowLayout.minimumLineSpacing = 0
        }
        collectionView?.backgroundColor = .white
        collectionView.register(FeedCell.self, forCellWithReuseIdentifier: UsersCell.identifer)
        collectionView?.register(EnrollCell.self, forCellWithReuseIdentifier: EnrollCell.identifier)
        collectionView?.contentInset = UIEdgeInsets(top: 50, left: 0, bottom: 0, right: 0)
        collectionView?.scrollIndicatorInsets = UIEdgeInsets(top: 50, left: 0, bottom: 0, right: 0)
        collectionView.isPagingEnabled = true
    }
    
    override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 2
    }
    
    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: UsersCell.identifer, for: indexPath)
        if indexPath.item == 1 {
            return collectionView.dequeueReusableCell(withReuseIdentifier: EnrollCell.identifier, for: indexPath)
        }
        return cell
    }
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return CGSize(width: view.frame.width, height: view.frame.height - 60)
    }
    
}

extension DemoApplicationController : UIImagePickerControllerDelegate,UINavigationControllerDelegate{
    
  @objc func pickTheImage() {
        print(123)
        let vc = UIImagePickerController()
        vc.sourceType = .photoLibrary
        vc.delegate = self
        vc.allowsEditing = true
        present(vc, animated: true, completion: nil)
        
        func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
            if let image = info[UIImagePickerController.InfoKey(rawValue: "UIImagePickerControllerEditedImage")] as? UIImage {
                print("imagepicked")
                enroll.profileIG.image=image
               
            }
            dismiss(animated: true, completion: nil)
        }
        func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
            dismiss(animated: true, completion: nil)
        }
    }
   
}

第一个 CollectionViewCell 名为 FeedCell.swift

class FeedCell: BaseCell,UICollectionViewDataSource,UICollectionViewDelegate,UICollectionViewDelegateFlowLayout {
  
    let db = Firestore.firestore()
    var documentdata = ""
    lazy var collectionView : UICollectionView = {
        let layout = UICollectionViewFlowLayout()
        let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
        cv.backgroundColor = .white
        cv.dataSource = self
        cv.delegate = self
        return cv
    }()
    

        override  func setupViews() {
        super.setupViews()
        addSubview(collectionView)
        addConstraintsWithFormat("H:|[v0]|", views: collectionView)
        addConstraintsWithFormat("V:|[v0]|", views: collectionView)
            collectionView.register(UsersCell.self, forCellWithReuseIdentifier: UsersCell.identifer)
        loadUserData()
    }
    
    
     func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return dataFile.count
    }

    
     func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: UsersCell.identifer, for: indexPath) as! UsersCell
        cell.titleLabel.text = dataFile[indexPath.item].FirstName
        cell.titleLabel.text?.append(" \(dataFile[indexPath.item].LastName)")
        cell.subtitleTextView.text = dataFile[indexPath.item].Gender
        cell.subtitleTextView.text.append(" | \(dataFile[indexPath.item].Age()) |")
        cell.subtitleTextView.text.append(" \(dataFile[indexPath.item].homeTowndata)")
        
        return cell
    }
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        frameWidth = Int(frame.width)
        return CGSize(width: frame.width, height: frame.height/8)
    }
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
        return 0
    }
    
}

第二个 CollectionViewCell 名为 EnrollCell.swift

class EnrollCell: UsersCell,UICollectionViewDelegate,UICollectionViewDelegateFlowLayout{
    var demoController = DemoApplicationController()
    
   static let identifier = "EnrollKey"
    
    let profileIG : UIImageView = {
        let imageView = UIImageView()
//        imageView.image = UIImage(named: "1")
        imageView.backgroundColor = UIColor(red: 0.12, green: 0.56, blue: 1.00, alpha: 1.00)
        imageView.layer.cornerRadius=22
        imageView.layer.masksToBounds=true
        imageView.translatesAutoresizingMaskIntoConstraints = false
        return imageView
    }()
    
    let setProfilePhoto: UIButton = {
        let profile = UIButton()
        profile.setTitle("Select Profile Photo", for: .normal)
        profile.setTitleColor(UIColor(red: 0.12, green: 0.56, blue: 1.00, alpha: 1.00), for: .normal)
        profile.titleLabel?.font = UIFont(name: "HelveticaNeue-Bold", size: 16)
        profile.translatesAutoresizingMaskIntoConstraints = false
        return profile
    }()
    
    lazy var collectionView : UICollectionView = {
        let layout = UICollectionViewFlowLayout()
        let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
        cv.backgroundColor = .white
        cv.delegate = self
        return cv
    }()

    
    override func setupViews() {
        addSubview(profileIG)
        addSubview(setProfilePhoto)
        UserDataButton.addTarget(self, action: #selector(editButtonTapped), for: UIControl.Event.touchUpInside)
        setProfilePhoto.addTarget(demoController.self, action: #selector(DemoApplicationController.pickTheImage), for: UIControl.Event.touchUpInside)
}
}

在您的 EnrollCell 中创建一个名为 pickTheImageDelegate 的协议,并将其作为委托并执行 DemoApplicationController 的操作以执行选择器控制器。

此处 EnrollCell.Swift 更新代码

import UIKit
import Firebase

protocol pickTheImageDelegate {
    func pickTheImage()
}

class EnrollCell: UsersCell,UICollectionViewDelegate,UICollectionViewDelegateFlowLayout{
    var delegate : pickTheImageDelegate?
   static let identifier = "EnrollKey"
    
    var demoController : DemoApplicationController?

let profileIG : UIImageView = {
        let imageView = UIImageView()
        imageView.image = UIImage(named: "1")
        imageView.layer.cornerRadius=22
        imageView.layer.masksToBounds=true
        imageView.translatesAutoresizingMaskIntoConstraints = false
        return imageView
    }()
    
    let setProfilePhoto: UIButton = {
        let profile = UIButton()
        profile.setTitle("Select Profile Photo", for: .normal)
        profile.setTitleColor(UIColor(red: 0.12, green: 0.56, blue: 1.00, alpha: 1.00), for: .normal)
        profile.titleLabel?.font = UIFont(name: "HelveticaNeue-Bold", size: 16)
        profile.translatesAutoresizingMaskIntoConstraints = false
        return profile
    }()

 lazy var collectionView : UICollectionView = {
        let layout = UICollectionViewFlowLayout()
        let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
        cv.backgroundColor = .white
        cv.delegate = self
        return cv
    }()

  override func setupViews() {
        addSubview(profileIG)
        addSubview(setProfilePhoto)

        setProfilePhoto.backgroundColor = .white

        UserDataButton.addTarget(self, action: #selector(editButtonTapped), for: UIControl.Event.touchUpInside)

        setProfilePhoto.addTarget(demoController, action: #selector(DemoApplicationController.pickTheImage), for: UIControl.Event.touchUpInside)

        addConstraintsWithFormat("H:|-150-[v0(100)]-150-|", views: profileIG)
        addConstraintsWithFormat("V:|-50-[v0(100)]-16-|", views: profileIG)

        addConstraintsWithFormat("H:|-105-[v0(\(frame.width/2))]|", views: setProfilePhoto)
        addConstraintsWithFormat("V:|-150-[v0(35)]|", views: setProfilePhoto)

}
}

这里的DemoApplicationContrller.Swift就是我们的UICollectionViewController

import UIKit
class DemoApplicationController: UICollectionViewController, UICollectionViewDelegateFlowLayout{
    
    var enroll : EnrollCell?
 
    override func viewDidLoad() {
        super.viewDidLoad()
        //title Label
        navigationController?.navigationBar.isTranslucent = false
        let titleLabel = UILabel(frame: CGRect(x: 0, y: 0, width: view.frame.width - 250, height: view.frame.height))
        titleLabel.text = "Demo Application"
        titleLabel.font = UIFont(name: "HelveticaNeue-Bold", size: 20)
        navigationItem.titleView = titleLabel
        titleLabel.textColor = UIColor(red: 0.12, green: 0.56, blue: 1.00, alpha: 1.00)
        enroll?.delegate=self
        setupCollectionView()
    }
    
    func setupCollectionView() {
        if let flowLayout = collectionView?.collectionViewLayout as? UICollectionViewFlowLayout {
            flowLayout.scrollDirection = .horizontal
            flowLayout.minimumLineSpacing = 0
        }
        collectionView?.backgroundColor = .white
        collectionView.register(FeedCell.self, forCellWithReuseIdentifier: UsersCell.identifer)
        collectionView?.register(EnrollCell.self, forCellWithReuseIdentifier: EnrollCell.identifier)
        collectionView?.contentInset = UIEdgeInsets(top: 50, left: 0, bottom: 0, right: 0)
        collectionView?.scrollIndicatorInsets = UIEdgeInsets(top: 50, left: 0, bottom: 0, right: 0)
        collectionView.isPagingEnabled = true
    }
    
   
    override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 2
    }
    
    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: UsersCell.identifer, for: indexPath)
        if indexPath.item == 1 {
            return collectionView.dequeueReusableCell(withReuseIdentifier: EnrollCell.identifier, for: indexPath)
        }
        return cell
    }
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return CGSize(width: view.frame.width, height: view.frame.height - 60)
    }
    
}


extension DemoApplicationController : UIImagePickerControllerDelegate,UINavigationControllerDelegate,pickTheImageDelegate{
    
    @objc func pickTheImage() {
        let vc = UIImagePickerController()
        vc.sourceType = .photoLibrary
        vc.delegate = self
        vc.allowsEditing = true
        present(vc, animated: true, completion: nil)
        
        func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
            if let image = info[UIImagePickerController.InfoKey(rawValue: "UIImagePickerControllerEditedImage")] as? UIImage {
                enroll?.profileIG.image = image
            }
            dismiss(animated: true, completion: nil)
        }
        func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
            dismiss(animated: true, completion: nil)
        }
    }
   
}