Swift: Getting 'Snapshotting a view that has not been rendered..' error when trying to open a URL in safari from my app

前端 未结 8 1611
一整个雨季
一整个雨季 2020-12-28 12:48

One of the specifications of my app is that on tapping a tableView cell, the user will be redirected to the website associated with the cell. Here is the code:



        
相关标签:
8条回答
  • 2020-12-28 13:09

    Also using Objective-C, using the suggested [modeAlert.view layoutIfNeeded] reduced errors to one as above. Final error has been suppressed by changing last addAction from UIAlertActionStyleCancel to UIAlertActionStyleDefault as below. Not a great workaround to what appears to be a bug.

    [modeAlert addAction:[UIAlertAction
                      actionWithTitle:NSLocalizedString(@"Cancel", @"")
                      style:UIAlertActionStyleDefault
                      handler:nil ]];
    
    0 讨论(0)
  • 2020-12-28 13:13

    I was getting a similar debug warning when trying to present a QLPreviewController modally. I've read on other posts that it's an Xcode bug.

    For me the error displayed when I ran my app on the simulator but not on an actual device. Must be an Xcode/Simulator issue. Hope that helps.

    0 讨论(0)
  • 2020-12-28 13:13

    I was facing the similar problem (same warning XD).

    Snapshotting a view that has not been rendered results in an empty snapshot. Ensure your view has been rendered at least once before snapshotting or snapshot after screen updates.


    My Xcode version is 9.4.1, and everything was perfect until I add resignFirstResponder() in textFieldShouldReturn(_ textField: UITextField).


    Here was my situation:

    When I touched UITextField with text in the UITableViewCell, It will show the warning.

    So I changed the way to trigger UITextField(Edit version). It never show the warning again.

    In conclusion, I still don't know why this happened, but what I can do is avoid the warning, hope It will help someone :D



    Edited code:

    class TableViewCell: UITableViewCell {
        // add this in TableViewCell
        override func setSelected(_ selected: Bool, animated: Bool) {
            super.setSelected(selected, animated: animated)
            answerTextField.isEnabled = selected
            if selected {
                answerTextField.becomeFirstResponder()
            } else {
                answerTextField.resignFirstResponder()
            }
        }
    }
    


    Original code:

    class ViewController: UIViewController {
    
        private let tableView: UITableView = {
            let t = UITableView()
            t.separatorStyle = .none
            t.backgroundColor = .clear
            return t
        }()
    
        private let cellId = "Cell"
    
        private let data = [
            Model(title: "A", answer: "a"),
            Model(title: "B", answer: "b"),
            Model(title: "C", answer: nil),
            Model(title: "D", answer: nil)
        ]
    
        override func viewDidLoad() {
            super.viewDidLoad()
            tableView.dataSource = self
            tableView.delegate = self
            tableView.register(TableViewCell.self, forCellReuseIdentifier: cellId)
            view.addSubview(tableView)
            tableView.frame = view.frame
        }
    }
    
    extension ViewController: UITableViewDataSource, UITableViewDelegate {
    
        func numberOfSections(in tableView: UITableView) -> Int {
            return 3
        }
    
        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return data.count
        }
    
        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    
            if let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath) as? TableViewCell {
                cell.contentView.backgroundColor = indexPath.section % 2 == 0 ? .gray : .white
                cell.setData(data[indexPath.row])
                return cell
            }
            return UITableViewCell()
        }
    
        func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
            return 100
        }
    }
    
    class TableViewCell: UITableViewCell {
    
        private let titleLabel = UILabel()
        private let answerTextField = UITextField()
    
        override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
            super.init(style: style, reuseIdentifier: reuseIdentifier)
            setupViews()
        }
        required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
            setupViews()
        }
    
        func setupViews() {
            setupTitleLabels()
        }
    
        func setData(_ data: Model) {
            titleLabel.text = data.title
            answerTextField.text = data.answer
        }
    
        private func setupTitleLabels() {
            answerTextField.delegate = self
    
            let sv = UIStackView(arrangedSubviews: [titleLabel, answerTextField])
            sv.axis = .vertical
            sv.spacing = 0
            sv.distribution = .fill
    
            contentView.addSubview(sv)
            sv.topAnchor.constraint(equalTo: contentView.topAnchor).isActive = true
            sv.leftAnchor.constraint(equalTo: contentView.leftAnchor).isActive = true
            sv.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true
            sv.rightAnchor.constraint(equalTo: contentView.rightAnchor).isActive = true
        }
    }
    
    extension TableViewCell: UITextFieldDelegate {
        func textFieldShouldReturn(_ textField: UITextField) -> Bool {
            textField.resignFirstResponder()
            return true
        }
    }
    
    struct Model {
        let title: String
        var answer: String?
        init(title: String, answer: String? = nil) {
            self.title = title
            self.answer = answer
        }
    }
    
    0 讨论(0)
  • 2020-12-28 13:24

    I had the same problem and found a simple solution that makes sense.

    If it's an iPad ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) then do NOT add the UIAlertAction with style UIAlertActionStyleCancel to the UIAlertController.

    I made this change and my errors went away. This solution makes sense since you don't need a cancel action for alerts with style UIAlertControllerStyleActionSheet on an iPad.

    0 讨论(0)
  • 2020-12-28 13:26

    To avoid copy/paste from Saliom's answer you can make such subclass and use it instead of UIAlertController:

    class AlertController: UIAlertController {
    
        override func viewWillAppear(animated: Bool) {
            super.viewWillAppear(animated)
            self.view.layoutIfNeeded()
        }
    
    }
    
    0 讨论(0)
  • I think the last warning came from the Cancel button.

    On iOS8 the cancel button is shown only when needed. If you run the app on iPhone it is visible. If you run the app on iPad the cancel button is not shown and the handler for the cancel action (style:UIAlertActionStyleCancel) is called when the user taps outside the popup.

    the answer come from: amalicka's answer

    0 讨论(0)
提交回复
热议问题