[英]Memory Problem with specific ViewController in Swift 5
I need some help with this problem.我需要一些帮助来解决这个问题。
I have this basic Scheme我有这个基本方案
When i tap 10 times the button (buttonTapped) in homecontroller and then dismiss everytime.当我点击 10 次家庭控制器中的按钮 (buttonTapped) 然后每次都关闭。
I think i create a cycle but i don't found it.我想我创造了一个循环,但我没有找到它。
My code:我的代码:
Home Controller:家庭电话 Controller:
class HomeController: UIViewController {
var user: User?
init(user: User) {
self.user = user
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
// show button on view
}
@objc func buttonTapped{
DriverService.shared.observeTrip(uid: "XXX") { (userDB) in
let controller = TripNavigation(user: userDB)
controller.modalPresentationStyle = .fullScreen
self.present(controller, animated: true, completion: nil)
}
}
}
TripNavigation code:旅行导航代码:
protocol TripProtocol: AnyObject {
func userHasChanged(_ user: User?)
}
class TripNavigation: UIViewController {
var user: User
weak var delegate: TripProtocol?
// array of childs
var listOfSteps: [UIViewController] = []
// segmented control to navigate in childs
let mySegmentedControl: UISegmentedControl = {
let sc = UISegmentedControl(items: ["1","2"])
return sc
}()
init(user: User) {
self.user = user
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
loadviews()
// here i make a addsubview for a button that call dissmisView() function (bottom of this class)
// i call dissmisView to test if memory deallocated
}
func checkFirebaseNews(){
// check new info from firebase and pass new data to childs
self.delegate?.userHasChanged(user)
}
// main function that load the childs
func loadviews(){
mySegmentedControl.frame = CGRect(x: 0, y: 95, width: view.frame.width, height: 30)
mySegmentedControl.addTarget(self, action: #selector(self.segmentedValueChanged(_:)), for: .valueChanged)
view.addSubview(mySegmentedControl)
// first child of TripNavigation
let step1 = Step1(user: user, nextStep: 1)
self.addChild(step1)
step1.willMove(toParent: self)
view.addSubview(step1.view)
step1.didMove(toParent: self)
step1.view.anchor(top:mySegmentedControl.topAnchor,left: view.leftAnchor, bottom: view.bottomAnchor, right: view.rightAnchor, paddingTop: 31)
delegate = step1
listOfSteps = [step1]
// second child of TripNavigation
let step2 = Step2(user: user, nextStep: -1)
self.addChild(step2)
step2.willMove(toParent: self)
view.addSubview(step2.view)
step2.didMove(toParent: self)
step2.view.anchor(top:mySegmentedControl.topAnchor,left: view.leftAnchor, bottom: view.bottomAnchor, right: view.rightAnchor, paddingTop: 31)
delegate = step2
listOfSteps.append(step2)
mySegmentedControl.selectedSegmentIndex = 0
showView(num: 0)
}
// segmented control manage
@objc func segmentedValueChanged(_ sender:UISegmentedControl!){
switch sender.selectedSegmentIndex{
case 0:
showView(num: 0)
case 1:
showView(num: 1)
default:
break
}
}
// aux functions
func showView(num: Int){
hideRestofViews(actual: num)
let step = listOfSteps[num]
step.view.isHidden = false
}
func hideRestofViews(actual: Int){
if listOfSteps.count >= 1 {
for (index, v) in listOfSteps.enumerated() {
if index != actual{
v.view.isHidden = true
}
}
}
}
@objc func dissmisView() {
print("<W call to dismissview")
for v in listOfSteps {
v.willMove(toParent: nil)
v.view.removeFromSuperview()
v.removeFromParent()
print(v)
v.dismiss(animated: false, completion: nil)
print("1")
}
print("<W all deleted")
self.dismiss(animated: true, completion: nil)
}
// called in child, to change to other view child
@objc func changeView(notification: NSNotification){
if let next = notification.object as? Int {
if next == -1{
dissmisView()
}else{
mySegmentedControl.selectedSegmentIndex = next
showView(num: next)
}
}
}
}
Example of Step1 child code: Step1子代码示例:
// Step1 and Step2 are practically the same
class Step1: UIViewController,TripProtocol {
var mapView = MKMapView()
var user: User?
var nextStep: Int
func userHasChanged(_ user: User?) {
self.user = user
}
init(user: User?, nextStep: Int) {
self.user = user
self.nextStep = nextStep
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
//configureMapView() ... configureUI... that show user data
}
@objc func nextStep(){
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "changeView"), object: nextStep)
}
}
Thanks so much everyone!!非常感谢大家!!
You can add the "TripNavigation" View Controllers to an array object in the HomeController then assign them to nil when dismissing them.您可以将“TripNavigation”视图控制器添加到 HomeController 中的数组 object,然后在关闭它们时将它们分配给 nil。
check this question: iOS view controller memory not released after it's been dismissed检查这个问题: iOS 查看 controller memory 在被解雇后未发布
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.