来自UITable的内存问题

时间:2016-05-28 08:42:08

标签: ios xcode swift

由于内存问题(使用的内存太多),我的应用程序崩溃了。当我从TableView打开足够多的对象时会发生这种情况。我在互联网上搜索了这个问题,我可以看到它可能是因为内存永远不会被释放。但是我如何发布呢?

这是我的代码。

TableExerciseViewController

class TableExercisesViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

var choosenCellIndex = 0
var filteredExercises = [Exercise]()

let searchController = UISearchController(searchResultsController: nil)

@IBOutlet weak var searchBar: UISearchBar!

@IBOutlet weak var tableView: UITableView!

override func viewDidLoad() {
    super.viewDidLoad()

    searchController.searchResultsUpdater = self
    searchController.dimsBackgroundDuringPresentation = false

    searchController.searchBar.placeholder = "Look up an exercise..."

    definesPresentationContext = true
    tableView.tableHeaderView = searchController.searchBar
}

override func viewDidAppear(animated: Bool) {
    if let row = tableView.indexPathForSelectedRow {
        self.tableView.deselectRowAtIndexPath(row, animated: false)
    }
}


override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}




func filterContentForSearchText(searchText: String, scope: String = "All") {
    filteredExercises = ExerciseManager.sharedInstance.getExercises().filter {
        exercise in return exercise.name.lowercaseString.containsString(searchText.lowercaseString)
    }

    tableView.reloadData()
}


//Returns the size of the arraylist
 func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {


    if searchController.active && searchController.searchBar.text != "" {
        return filteredExercises.count
    }
    return ExerciseManager.sharedInstance.getExercises().count
}

//Returns the selected Cell
 func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    let cell = tableView.dequeueReusableCellWithIdentifier("Exercise Cell", forIndexPath: indexPath) as! ExerciseCustomCell
    let exercise: Exercise
    if searchController.active && searchController.searchBar.text != "" {
        exercise = filteredExercises[indexPath.row]
    } else {
        exercise = ExerciseManager.sharedInstance.getExercises()[indexPath.row]
    }

    cell.imgExercise?.image = exercise.exerciseImage1
    cell.lblExerciseName?.text = exercise.name
    cell.lblExerciseMuscleGroup?.text = exercise.muscle
    cell.lblExerciseTools?.text = "Equipment: \(exercise.tool)"

    return cell
}

 func numberOfSectionsInTableView(tableView: UITableView) -> Int {
    return 1
}


//Sends the data through the selected identifier
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {

    choosenCellIndex = indexPath.row

    // Start segue with index of cell clicked
    self.performSegueWithIdentifier("Show Exercise", sender: self)

}

//Prepares the data for the segue and the next viewcontroller
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {

    // get a reference to the second view controller
    let exerciseViewController = segue.destinationViewController as! ExerciseViewController

    // set a variable in the second view controller with the data to pass
    if searchController.active && searchController.searchBar.text != "" {
        exerciseViewController.exercise = filteredExercises[choosenCellIndex]
    } else {
        exerciseViewController.exercise = ExerciseManager.sharedInstance.getExercises()[choosenCellIndex]
    }

}

deinit {
    debugPrint("TableExerciseView deinitialized...")
}

}

extension TableExercisesViewController: UISearchResultsUpdating {
func updateSearchResultsForSearchController(searchController: UISearchController) {
    filterContentForSearchText(searchController.searchBar.text!)
}

ExerciseViewController

class ExerciseViewController: UIViewController {
weak var exercise: Exercise?
var receivedCellIndex = 0

@IBOutlet weak var scrollView: UIScrollView!

@IBOutlet weak var lblExerciseName: UILabel!

@IBOutlet weak var lblExerciseMuscleGroup: UILabel!

@IBOutlet weak var lblStartDescription: UILabel!

@IBOutlet weak var lblLastDescription: UILabel!


@IBOutlet weak var imgExerciseAnimation: UIImageView!

@IBOutlet weak var imgExerciseStartPosition: UIImageView!

@IBOutlet weak var imgExerciseLastPosition: UIImageView!

var timer = NSTimer()
var counter = 1


override func viewDidLoad() {
    super.viewDidLoad()

    //Sets the color of the back button in navigation bar
    self.navigationController!.navigationBar.tintColor = UIColor.whiteColor();

    //Sets the labels
    lblExerciseName.text = exercise?.name
    lblExerciseMuscleGroup.text = exercise!.muscle
    lblStartDescription.text = "1. \(exercise!.startDescription)"
    lblLastDescription.text = "2. \(exercise!.lastDescription)"


    //Sets the antimation and the images
    imgExerciseAnimation.image = exercise?.exerciseImage1
    imgExerciseStartPosition.image = exercise?.exerciseImage1
    imgExerciseLastPosition.image = exercise?.exerciseImage2

    //Timer
    self.timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: #selector(ExerciseViewController.demonstrateExercise), userInfo: nil, repeats: true)

}

override func viewWillDisappear(animated: Bool) {
    super.viewWillDisappear(animated)
    self.timer.invalidate()
}

func demonstrateExercise() {
    if counter == 1 {
        imgExerciseAnimation.image = exercise?.exerciseImage2
        counter += 1
    } else {
        counter = 1
        imgExerciseAnimation.image = exercise?.exerciseImage1
    }
}
 }

2 个答案:

答案 0 :(得分:1)

我猜测占用内存的是ExerciseViewController中的运动图像。由于Swift使用ARC来管理内存,因此您希望删除对这些图像的引用(并为此而行使),以便系统可以从内存中释放它们。

override func viewDidDisappear(animated: Bool) {
    lblExerciseName.text = nil
    lblExerciseMuscleGroup.text = nil
    lblStartDescription.text = nil
    lblLastDescription.text = nil

    imgExerciseAnimation.image = nil
    imgExerciseStartPosition.image = nil
    imgExerciseLastPosition.image = nil
}

由于您的exercice变量是weak,并且没有任何内容引用它,系统现在将从内存中释放它,而不是每次用户访问新的ExerciseViewController时都会生成多个exercice副本。

答案 1 :(得分:0)

覆盖deinit函数 - 并在退出Exercise视图时检查它是否被调用。如果不是 - 我会在viewWillDisappear或Did functions中销毁计时器。