Reputation: 806
My app is crashing because of a memory issue (Too much memory used). It happens when i open enough of the objects from the TableView. I has searched the internet for the problem, and i can see it might be because the memory never is released. But how do i release it?
Here is my code.
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
}
}
}
Upvotes: 0
Views: 156
Reputation: 2770
Override deinit function - and check if its called when you exit the Exercise view. If not - i would destroy the timer in viewWillDisappear or Did functions.
Upvotes: 0
Reputation: 454
I'm guessing that what's taking up the memory are the exercise images in your ExerciseViewController. Since Swift uses ARC to manage memory, you'll want to remove references to those images (and exercice for that matter) so that the system can release them from memory.
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
}
Since your exercice variable is weak
, and nothing is referencing to it, the system will now free it from memory instead of having multiple copies of exercices build up every time the user visits a new ExerciseViewController.
Upvotes: 1