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!