0
votes

I have set up the activity indicator while loading to next view. The original view contains a tableView of buttons and it will direct to the next view when the button is clicked. However, it doesn't show up when coming back to the original view. It works on another view transition but I don't know why it doesn't work here.

Here's the button clicking function of processing to next view:

@objc func remark(_ sender: UIButton) {
    ViewControllerUtils().showActivityIndicator(uiView: self.tableView)

    DispatchQueue.main.async {
        self.markDetailsDelegate?.getStudentList(paperId: sender.paperId!, schoolClass: sender.schoolClass!, studentToShow: sender.studentToShow, questionNo: sender.questionNo!, readOnlyFlag: false) { returnList, studentReturnList, returnMarkBox, returnMCOptionBox, returnStudentMarkList, error  in
            self.pdfFileList = returnList!
            self.studentList = studentReturnList!
            self.questionMarkBox = returnMarkBox!
            self.mcQuestionOptionBox = returnMCOptionBox!
            self.studentMarkList = returnStudentMarkList!
        }

        DispatchQueue.main.async {
            ViewControllerUtils().hideActivityIndicator(uiView: self.tableView)
        }
    }
}

Function of reloading the tableView (once it's returning back to the tableView, it is called to reload it):

@objc func reloadMarkDetails() {
    ViewControllerUtils().showActivityIndicator(uiView: self.tableView)

    DispatchQueue.main.async {
        self.markDetailsDelegate?.reloadMarkDetails(paperId: self.currentPaperId, schoolClass: self.currentSchoolClass) { returnPDFFileList, returnStudentList, returnQuestionMarkBox, returnMCQuestionOptionBox, returnStudentMarkList, returnPaperCommentList, returnPaperSummary, returnMarkSummary, returnTagSummary, returnLastMarkedSummary, returnAnsNoOfPage, returnDatetime, returnPaperFreezedFlag, error in
            self.studentList = returnStudentList
            self.studentMarkList = returnStudentMarkList
            self.markSummary = returnMarkSummary
            self.lastMarkedSummary = returnLastMarkedSummary
            self.paperFreezedFlag = returnPaperFreezedFlag

            DispatchQueue.main.async {
                ViewControllerUtils().hideActivityIndicator(uiView: self.tableView)

                self.tableView.reloadData()
                self.tableView.layoutIfNeeded()
            }
        }
    }
}

Utility class of managing activity indicator:

class ViewControllerUtils: UIView {

    static var shared = ViewControllerUtils()

    var container: UIView = UIView()
    var loadingView: UIView = UIView()
    var activityIndicator: UIActivityIndicatorView = UIActivityIndicatorView()
    var loadingTextLabel = UILabel()
    let margin: CGFloat = 20.0

    /*
     Show customized activity indicator (with text),
     actually add activity indicator to passing view

     @param uiView - add activity indicator to this view
     @param title - add title to activity indicator
     */
    func showActivityIndicator(uiView: UIView, title: String) {
        container.frame = uiView.frame
        container.center = uiView.center
        container.backgroundColor = UIColorFromHex(rgbValue: 0x444444, alpha: 0.2)

        loadingView.frame = CGRect(x: 0, y: 0, width: 230, height: 60)
        loadingView.center = uiView.center
        loadingView.backgroundColor = UIColorFromHex(rgbValue: 0xffffff, alpha: 1.0)
        loadingView.clipsToBounds = true
        loadingView.layer.cornerRadius = 10
        loadingView.layer.shadowColor = UIColor.black.cgColor
        loadingView.layer.shadowOpacity = 1
        loadingView.layer.shadowOffset = .zero
        loadingView.layer.shadowRadius = 10

        activityIndicator.frame = CGRect(x: 0.0, y: 5.0, width: 40, height: 40);
        activityIndicator.style = UIActivityIndicatorView.Style.gray
        activityIndicator.center = CGPoint(x: (activityIndicator.frame.size.width + margin) / 2, y: loadingView.frame.size.height / 2)

        loadingTextLabel.textColor = UIColor.black
        loadingTextLabel.text = title
        loadingTextLabel.font = .systemFont(ofSize: 16, weight: .medium)
        loadingTextLabel.textAlignment = .center
        loadingTextLabel.sizeToFit()
        loadingTextLabel.adjustsFontSizeToFitWidth = true
        loadingTextLabel.lineBreakMode = NSLineBreakMode.byWordWrapping
        loadingTextLabel.frame = CGRect(x: activityIndicator.frame.size.width + margin * 0.5, y: activityIndicator.frame.origin.y, width: loadingView.frame.size.width - activityIndicator.frame.size.width - margin, height: activityIndicator.frame.size.height)

        loadingView.addSubview(activityIndicator)
        loadingView.addSubview(loadingTextLabel)
        container.addSubview(loadingView)
        uiView.superview?.addSubview(container)
        activityIndicator.startAnimating()
    }

    /*
     Show customized activity indicator (without text),
     actually add activity indicator to passing view

     @param uiView - add activity indicator to this view
     */
    func showActivityIndicator(uiView: UIView) {
        container.frame = uiView.frame
        container.center = uiView.center
        container.backgroundColor = UIColorFromHex(rgbValue: 0xffffff, alpha: 0.5)

        loadingView.frame = CGRect(x: 0, y: 0, width: 80, height: 80)
        loadingView.center = container.center
        loadingView.backgroundColor = UIColorFromHex(rgbValue: 0x444444, alpha: 0.7)
        loadingView.clipsToBounds = true
        loadingView.layer.cornerRadius = 10
        loadingView.layer.cornerRadius = 10
        loadingView.layer.shadowColor = UIColor.black.cgColor
        loadingView.layer.shadowOpacity = 1
        loadingView.layer.shadowOffset = .zero
        loadingView.layer.shadowRadius = 10

        loadingTextLabel.removeFromSuperview()

        activityIndicator.frame = CGRect(x: 0.0, y: 0.0, width: 40.0, height: 40.0);
        activityIndicator.style = UIActivityIndicatorView.Style.whiteLarge
        activityIndicator.center = CGPoint(x: loadingView.frame.size.width / 2, y: loadingView.frame.size.height / 2);

        loadingView.addSubview(activityIndicator)
        container.addSubview(loadingView)
        uiView.superview?.addSubview(container)
        activityIndicator.startAnimating()
    }

    /*
     Change text of activity indicator

     @param message - modified text
     */
    func changeTextToActivityIndicator(message: String) {
        loadingTextLabel.text = message
    }

    /*
     Hide activity indicator
     Actually remove activity indicator from its super view

     @param uiView - remove activity indicator from this view
     */
    func hideActivityIndicator(uiView: UIView) {
        activityIndicator.stopAnimating()
        container.removeFromSuperview()

        print("[DEBUG] Stop Activity Indicator at View - \(uiView)")
    }

    /*
     Define UIColor from hex value

     @param rgbValue - hex color value
     @param alpha - transparency level
     */
    func UIColorFromHex(rgbValue:UInt32, alpha:Double=1.0)->UIColor {
        let red = CGFloat((rgbValue & 0xFF0000) >> 16)/256.0
        let green = CGFloat((rgbValue & 0xFF00) >> 8)/256.0
        let blue = CGFloat(rgbValue & 0xFF)/256.0
        return UIColor(red:red, green:green, blue:blue, alpha:CGFloat(alpha))
    }

}

I tried to figure out why the indicator is not showing while returning back to original view by using Debug View Hierarchy and here are the results:

Is there anything I did wrong during segue transition? Thanks so much if someone could help me!

1
when you are back to your view may be your indicator code not called so put your code in viewwillappear method and it will works and remove your code from viewdidload.Vipin Pareek
Thanks @VipinPareek! But I have tried that and it doesn't work. It is not called in ViewDidLoad because it is a set of buttons inside the tableView, and moving to View B is triggered by tapping on those buttons.markandshare

1 Answers

0
votes

I assume it should be

@objc func remark(_ sender: UIButton) {
    ViewControllerUtils().showActivityIndicator(uiView: self.tableView)

    self.markDetailsDelegate?.getStudentList(paperId: sender.paperId!, schoolClass: sender.schoolClass!, studentToShow: sender.studentToShow, questionNo: sender.questionNo!, readOnlyFlag: false) { returnList, studentReturnList, returnMarkBox, returnMCOptionBox, returnStudentMarkList, error  in

        DispatchQueue.main.async {
            ViewControllerUtils().hideActivityIndicator(uiView: self.tableView)

            self.pdfFileList = returnList!
            self.studentList = studentReturnList!
            self.questionMarkBox = returnMarkBox!
            self.mcQuestionOptionBox = returnMCOptionBox!
            self.studentMarkList = returnStudentMarkList!
        }
    }
}