Swift Search Results segue to other View controller - ios

When I search in my searchbar, I want to click on a result and then go to another view controller. I found a similar queston on this site (Swift Search Result Controller in search results segue to another view controller) but it didn't worked out for me.
With my current code there is a working segue, but it is the table view segue (instead of the results segue).
Does someone know how I do this and explain it in an easy way?
Here's my tableviewcontroller code:
class elementstableviewcontroller: UITableViewController,
UISearchResultsUpdating{
var namen = ["Waterstof","Helium","Litium"]
var searchcontroller: UISearchController!
var resultsController: UISearchController!
var filterednamen = [String]()
override func viewDidLoad() {
super.viewDidLoad()
self.searchcontroller = UISearchController(searchResultsController: nil)
self.tableView.tableHeaderView = self.searchcontroller.searchBar
self.searchcontroller.searchResultsUpdater = self
self.searchcontroller.dimsBackgroundDuringPresentation = false
definesPresentationContext = true
self.navigationItem.hidesBackButton = false;
self.navigationController?.isNavigationBarHidden = false
}
func updateSearchResults(for searchController: UISearchController) {
self.filterednamen = self.namen.filter { (naam:String) -> Bool in
if naam.lowercased().contains(self.searchcontroller.searchBar.text!.lowercased()) {
return true
}else{
return false
}
}
self.tableView.reloadData()
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if !searchcontroller.isActive || searchcontroller.searchBar.text == "" {
return self.namen.count
}else {
return self.filterednamen.count
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! CustomCell
cell.name.text = namen[indexPath.row]
if !searchcontroller.isActive || searchcontroller.searchBar.text == "" {
cell.name.text = self.namen[indexPath.row]
}else{
cell.name.text = self.filterednamen[indexPath.row]
}
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
myIndex2 = indexPath.row
performSegue(withIdentifier: "segue2", sender: self)
}
}
and here's my second view controller code:
import UIKit
import GoogleMobileAds
class Elementenuitgelegd: UIViewController, GADBannerViewDelegate{
#IBOutlet var banner: GADBannerView!
#IBOutlet var uitleg5: UILabel!
#IBOutlet var groep: UILabel!
#IBOutlet var periode: UILabel!
#IBOutlet var uitleg4: UILabel!
#IBOutlet var uitleg3: UILabel!
#IBOutlet var uitleg2: UILabel!
#IBOutlet var uitleg1: UILabel!
#IBOutlet var titlelabel: UILabel!
var distance: Double = 0;
var speed: Double = 0;
var time: Double = 0;
override func viewDidLoad() {
super.viewDidLoad()
titlelabel.text = namen[myIndex2]
uitleg1.text = afkortingen[myIndex2]
uitleg2.text = atoommassas[myIndex2]
uitleg3.text = atoomnummers[myIndex2]
uitleg4.text = electronenconfig[myIndex2]
periode.text = periodes[myIndex2]
groep.text = groepen[myIndex2]
self.navigationItem.hidesBackButton = true;
self.navigationController?.isNavigationBarHidden = true
//banner
let request = GADRequest()
request.testDevices = [kGADSimulatorID]
banner.adUnitID = "ca-app-pub-8478021432040036/4295805958"
banner.rootViewController = self
banner.delegate = self
banner.load(request)
//keyboard weg deel 1
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(startscreen.dismissKeyboard))
//Uncomment the line below if you want the tap not not interfere and cancel other interactions.
//tap.cancelsTouchesInView = false
view.addGestureRecognizer(tap)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//keyboardweg deel 2
func dismissKeyboard() {
view.endEditing(true)
}
}
Here's my customcell controller code:
import UIKit
class CustomCell: UITableViewCell {
#IBOutlet var name: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
[First(tableview),second(searching for Neon and clicking on it), third(getting hydrogen("waterstof" in Dutch)1

Related

Updating Label in Cell

I have a TableView which rows contain label and two buttons. What I wanna do is that when a user clicks the first button "Set Name", a pop up view comes up in which he can input text from keyboard. After hitting "Set", pop up view is dismissed and label inside a row containing the clicked button changes to the input text. I set the delegates but I cannot make label to change.
TableView:
import UIKit
class SetGame: UIViewController, UITableViewDelegate, UITableViewDataSource
{
var numOfPlayers = Int()
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return numOfPlayers
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! TableViewCell
cell.Name.text = "Player \(indexPath.row + 1)"
cell.btn1.tag = indexPath.row
cell.btn2.tag = indexPath.row
return cell
}
override func viewDidLoad()
{
super.viewDidLoad()
self.tableView.separatorStyle = UITableViewCellSeparatorStyle.none
}
override func didReceiveMemoryWarning()
{
super.didReceiveMemoryWarning()
}
#IBAction func setName(sender: UIButton)
{
let thisVC = storyboard?.instantiateViewController(withIdentifier: "SetName") as! SetName
thisVC.delegate = self
present(thisVC, animated: true, completion: nil)
}
#IBAction func setFingerprint(_ sender: UIButton)
{
}
#IBAction func unwindToSetGame(_ segue: UIStoryboardSegue)
{
print("unwinded to SetGame")
}
#IBOutlet weak var tableView: UITableView!
}
extension SetGame: nameDelegate
{
func named(name: String)
{
let indexP = IndexPath(row: 0, section: 0)
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexP) as! TableViewCell
cell.Name.text = "bkjhvghcjhkv"
//wanted to see if it changes first cell. But doesn't work
}
}
TableViewCell Class:
import UIKit
class TableViewCell: UITableViewCell
{
override func awakeFromNib()
{
super.awakeFromNib()
}
override func setSelected(_ selected: Bool, animated: Bool)
{
super.setSelected(selected, animated: animated)
}
#IBOutlet weak var Name: UILabel!
#IBOutlet weak var btn1: UIButton!
#IBOutlet weak var btn2: UIButton!
}
Pop up View:
import UIKit
protocol nameDelegate
{
func named(name: String)
}
class SetName: UIViewController
{
var delegate: nameDelegate!
override func viewDidLoad()
{
super.viewDidLoad()
window.layer.borderWidth = 1
window.layer.borderColor = UIColor.white.cgColor
}
override func didReceiveMemoryWarning()
{
super.didReceiveMemoryWarning()
}
#IBAction func closePopUp(_ sender: Any)
{
if input.text != ""
{
delegate.named(name: input.text!)
}
dismiss(animated: true, completion: nil)
}
#IBOutlet weak var input: UITextField!
#IBOutlet weak var window: UIView!
}
Replace this
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexP) as! TableViewCell
with
let cell = tableView.cellForRow(at:indexP) as! TableViewCell

BEMcheckbox check/uncheck issue in tableview in swift 3

I am using BEMcheckbox. when i click it, it animates and show a hidden label but when I scroll my tableview my checkbox is automatically deselected. also when I scroll it doesn't select any checkbox automatically. what I want is when I scroll my tableview the checkbox which are checked remains checked and which are unchecked remains unchecked. my code is below. my view controller class.
class markAttendanceViewController: UIViewController , UITableViewDataSource , UITableViewDelegate{
#IBAction func selectall(_ sender: UIButton) {
sender.isSelected = !sender.isSelected
if sender.isSelected {
checkImageView.isHidden = false
checkboxLabel.layer.borderColor = UIColor.blue.cgColor
} else{
checkImageView.isHidden = true
checkboxLabel.layer.borderColor = UIColor.lightGray.cgColor
}
table.reloadData()
}
#IBOutlet weak var checkImageView: UIImageView!
#IBOutlet weak var checkboxLabel: UILabel!
#IBAction func backToAttendanceView(_ sender: AnyObject) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
var controller: UIViewController!
controller = storyboard.instantiateViewController(withIdentifier: "listViewController") as! listViewController
(controller as! listViewController).receivedString = "Mark Attendance"
let navController = UINavigationController(rootViewController: controller)
let revealController = self.revealViewController() as! RevealViewController
revealController.rightViewController = navController
revealController.rightViewController.view.addGestureRecognizer(revealController.panGestureRecognizer())
self.present(revealController, animated: true, completion: nil)
}
#IBOutlet weak var table: UITableView!
#IBOutlet weak var button: UIButton!
//var items:Array = [String]()
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.setNavigationBarHidden(true, animated: true)
checkboxLabel.layer.borderWidth = 1
checkboxLabel.layer.borderColor = UIColor.lightGray.cgColor
// items = ["Dashboard","Mark Attendance","Update Attendance","delete Attendance","Time Table","Academic Calendar","Reports","About Us","Logout","rbivwe","whefo","ewsow","webkgwo","wbiebfkwbei","ejwvabei","vdkgdvkJDB"]
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 20
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "attendanceTableViewCell") as! attendanceTableViewCell
// cell.studentname?.text = items[indexPath.row]
cell.serialnumber?.text = "\(indexPath.row + 1)"
if button.isSelected {
cell.present.isHidden = false
cell.box.setOn(true, animated: true)
} else
{
cell.box.setOn(false, animated: false)
cell.present.isHidden = true
}
return cell
}
}
My tableview cell class.
class attendanceTableViewCell: UITableViewCell,BEMCheckBoxDelegate {
#IBOutlet weak var present: UILabel!
#IBOutlet weak var box: BEMCheckBox!
#IBOutlet weak var studentname: UILabel!
#IBOutlet weak var serialnumber: UILabel!
#IBOutlet weak var view: UIView!
override func awakeFromNib() {
box.delegate = self
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
view.layer.masksToBounds = false
view.layer.cornerRadius = 2.0
view.layer.shadowOffset = CGSize(width: -1, height: 1)
view.layer.shadowOpacity = 0.2
// Configure the view for the selected state
}
func didTap(_ checkBox: BEMCheckBox) {
if box.on {
present.isHidden = false
} else {
present.isHidden = true
}
}
}
If someone still need a solution for this. The only way I got it work is to add checkBox state each time you tap on it and then check the state in cellForRowAt function. My suggestion:
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, BEMCheckBoxDelegate {
//...
var checkboxesState: [Int: Bool] = [:]
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = mainTableView.dequeueReusableCell(withIdentifier: "productCell", for: indexPath) as! ProductCell
cell.checkBox.delegate = self
cell.checkBox.tag = indexPath.row
if let isOn = checkboxesState[indexPath.row] {
if isOn {
cell.checkBox.on = true
} else {
cell.checkBox.on = false
}
} else {
cell.checkBox.on = false
}
//... other code
return cell
}
func didTap(_ checkBox: BEMCheckBox) {
checkboxesState.updateValue(checkBox.on, forKey: checkBox.tag)
}
//...
}

Swift - Segue to wrong index when UISearchBar is active

I am new to code, and I just can't find the solution to this problem. Most of the answers on the internet are deprecated or unanswered.
I want to search something into my searchbar, after that I want to press on one of the results. When I click on the result I want it to give me the corresponding information in another viewcontroller.
Here's my problem: When I click on a result, the information in the other viewcontroller doesn't correspond with the information that the result gave me. What he does gives me is the information that corresponds to the tableview. So, it segues with a wrong index. Does anyone knows what the solution is?
Here's my code (tableviewcontroller with searchbar):
var myIndex = 0
extension UIColor { //themakleur
static let candyGreen = UIColor(red: 71.0/255.0, green: 81.0/255.0, blue:
89.0/255.0, alpha: 1.0)}
var watjeberekend = ["Omtrek Cirkel","Oppervlakte Cirkel","Lengte
Boog","Oppervlakte Sector","Oppervlakte Bol"]
class scheikunde: UITableViewController, UISearchResultsUpdating {
var scheikundeformules = ["Omtrek Cirkel","Oppervlakte Cirkel","Lengte Boog","Oppervlakte Sector","Oppervlakte Bol"]
var searchcontroller : UISearchController!
var filterednamen = [String]()
override func viewDidLoad() {
super.viewDidLoad()
self.searchcontroller = UISearchController(searchResultsController: nil)
self.tableView.tableHeaderView = self.searchcontroller.searchBar
self.searchcontroller.searchResultsUpdater = self
self.searchcontroller.dimsBackgroundDuringPresentation = false
definesPresentationContext = true
self.navigationItem.hidesBackButton = false;
self.navigationController?.isNavigationBarHidden = false
//navigationcontroller layout
navigationController?.navigationBar.barTintColor = UIColor(red: 71.0/255.0, green: 81.0/255.0, blue: 89.0/255.0, alpha: 1.0)
navigationController?.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName: UIColor.white]
navigationController?.navigationBar.layer.borderColor = UIColor.candyGreen.cgColor
navigationController?.navigationBar.layer.borderWidth = 0
//searchcontroller layout
searchcontroller.searchBar.layer.borderWidth = 0
searchcontroller.searchBar.layer.borderColor = UIColor.candyGreen.cgColor
UISearchBar.appearance().barTintColor = .candyGreen
UITextField.appearance(whenContainedInInstancesOf: [UISearchBar.self]).tintColor = .candyGreen
searchcontroller.searchBar.backgroundImage = UIImage(named: "themakleur.jpg")
let cancelButtonAttributes: [String: AnyObject] = [NSForegroundColorAttributeName: UIColor.white]
UIBarButtonItem.appearance(whenContainedInInstancesOf: [UISearchBar.self]).setTitleTextAttributes(cancelButtonAttributes, for: .normal)
}
func updateSearchResults(for searchController: UISearchController) {
self.filterednamen = self.scheikundeformules.filter { (naam : String) -> Bool in
if naam.lowercased().contains(self.searchcontroller.searchBar.text!.lowercased()) {
return true
}else{
return false}}
self.tableView.reloadData()
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if !searchcontroller.isActive || searchcontroller.searchBar.text == "" {
return self.scheikundeformules.count
}else {
return self.filterednamen.count
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! Custommath
cell.label.text = scheikundeformules[indexPath.row]
if !searchcontroller.isActive || searchcontroller.searchBar.text == "" {
//cell.textLabel?.text = self.namen[indexPath.row]
cell.label.text = self.scheikundeformules[indexPath.row]
}else{
//cell.textLabel?.text = self.filterednamen[indexPath.row]
cell.label.text = self.filterednamen[indexPath.row]
}
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
myIndex = indexPath.row
performSegue(withIdentifier: "segue", sender: self)
}
}
Here is my code from the viewcontroller:
import UIKit
class scheikundeformule: UIViewController{
#IBOutlet var uitleg6: UILabel!
#IBOutlet var formuleomschrijving: UILabel!
#IBOutlet var uitleg5: UILabel!
#IBOutlet var uitleg4: UILabel!
#IBOutlet var uitleg3: UILabel!
#IBOutlet var uitleg2: UILabel!
#IBOutlet var uitleg1: UILabel!
#IBOutlet var titlelabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
titlelabel.text = scheikundeformules[myIndex]
uitleg1.text = uitlegformules2[myIndex]
uitleg2.text = uitlegformules3[myIndex]
uitleg3.text = uitlegformules4[myIndex]
uitleg4.text = uitlegformules5[myIndex]
uitleg5.text = uitlegformules6[myIndex]
uitleg6.text = uitlegformules7[myIndex]
self.navigationItem.hidesBackButton = false;
self.navigationController?.isNavigationBarHidden = false
formuleomschrijving.text = watjeberekend[myIndex]
//keyboard weg deel 1
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(startscreen.dismissKeyboard))
//Uncomment the line below if you want the tap not not interfere and cancel other interactions.
//tap.cancelsTouchesInView = false
view.addGestureRecognizer(tap)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
Where is your function prepare for segue ? if you want to pass the data to the next view controller you need to send it in the fun prepare for segue, and remember that the indexpath.row needs to be used with the array that is the current datasource of the tableview, the solution will be something like this:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let destinationVC = segue.destination as? YourViewController {
if !searchcontroller.isActive {
destinationVC.name = filterednamen[myIndex]
} else {
destinationVC.name = scheikundeformules[myIndex]
} }
}
Add identifier for scheikundeformule view controller in storyboard like below :
Step 1:
Step 2:
change your tableview didSelectRow like below :
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
myIndex = indexPath.row
let scheikundeformuleController = self.storyboard?.instantiateViewController(withIdentifier: "scheikundeformule") as! scheikundeformule
scheikundeformuleController.myIndex = indexPath.row
self.present(scheikundeformuleController, animated: true, completion: nil)
}
Step 3:
You have to add var myIndex = 0 to your scheikundeformule controller. Like below :
class scheikundeformule: UIViewController{
var myIndex = 0
........Your code
}

Swift - Having problems with SearchBar in a custom TableViewController

I am new to code and I want to make an Search function in my Custom TableViewController. I get an error (Thread 1: signal SIGABRT) when I type (in the search bar) in a letter which correspond to a letter in an list of names (var namen*) I made. When I type in a letter which not correspond to a letter in my list of names I don't get the error. I checked my IBoutlets but they were not the problem. Does someone know how to fix the error?
Here's my initial viewcontroller code: (some names are Dutch)
import UIKit
class elementstableviewcontroller: UITableViewController,
UISearchResultsUpdating{
#IBOutlet var tableview: UITableView!
var namen = ["Waterstof","Helium","Litium","Beryllium","Boor","Koolstof","Stikstof","Zuurstof","Fluor","Neon"]
var afkortingen = ["H","He","Li","Be","B","C","N","O","F","Ne"]
var atoommassas = ["Massa: 1,008","Massa: 4,003","Massa: 6,941","Massa: 9,012","Massa: 10,81","Massa: 12,01","Massa: 14,01","Massa: 16,00","Massa: 19,00","Massa: 20,18"]
var atoomnummers = ["Nummer: 1","Nummer: 2","Nummer: 3","Nummer: 4","Nummer: 5","Nummer: 6","Nummer: 7","Nummer: 8","Nummer: 9","Nummer: 10"]
var ladingen = ["Lading: +1,-1","Lading: 0","Lading: +1","Lading: +2","Lading: +3","Lading: +2,+4,-4","Lading: +1,+2,+3,+4,+5,-1,-2,-3","Lading: -2","Lading: -1","Lading: 0"]
var electronenconfig = ["Config: 1","Config: 2","Config: 2,1","Config: 2,2","Config: 2,3","Config: 2,4","Config: 2,5","Config: 2,6","Config: 2,7","Config: 2,8"]
var searchcontroller : UISearchController!
var resultscontroller = UITableViewController()
var filterednamen = [String]()
override func viewDidLoad() {
super.viewDidLoad()
self.resultscontroller.tableView.dataSource = self
self.resultscontroller.tableView.delegate = self
self.searchcontroller = UISearchController(searchResultsController: self.resultscontroller)
self.tableView.tableHeaderView = self.searchcontroller.searchBar
self.searchcontroller.searchResultsUpdater = self
self.searchcontroller.dimsBackgroundDuringPresentation = false
definesPresentationContext = true
}
func updateSearchResults(for searchController: UISearchController) {
self.filterednamen = self.namen.filter { (naam:String) -> Bool in
if naam.lowercased().contains(self.searchcontroller.searchBar.text!.lowercased()) {
return true
}else{
return false
}
}
self.resultscontroller.tableView.reloadData()
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if tableView == self.tableView{
return self.namen.count
}else {
return self.filterednamen.count
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! CustomCell
cell.afkorting.text = afkortingen[indexPath.row]
cell.name.text = namen[indexPath.row]
cell.atoommassa.text = atoommassas[indexPath.row]
cell.elektronenconfiguratie.text = electronenconfig[indexPath.row]
cell.atoomnummer.text = atoomnummers[indexPath.row]
cell.lading.text = ladingen[indexPath.row]
if tableView == self.tableView{
//cell.textLabel?.text = self.namen[indexPath.row]
cell.name.text = self.namen[indexPath.row]
}else{
//cell.textLabel?.text = self.filterednamen[indexPath.row]
cell.name.text = self.filterednamen[indexPath.row]
}
return cell
}
}
And here's my CustomCell code:
import UIKit
class CustomCell: UITableViewCell {
#IBOutlet var elektronenconfiguratie: UILabel!
#IBOutlet var atoomnummer: UILabel!
#IBOutlet var atoommassa: UILabel!
#IBOutlet var name: UILabel!
#IBOutlet var afkorting: UILabel!
#IBOutlet var lading: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
*namen = names and naam = name translated from Dutch to English
Try to implement filter functionality in shouldChangeTextIn SearchBar method as given below
func searchBar(_ searchBar: UISearchBar, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
self.filterednamen = self.namen.filter { (naam:String) -> Bool in
return naam.lowercased().contains(self.searchcontroller.searchBar.text!.lowercased())
}
self.resultscontroller.tableView.reloadData()
}
There are several problems with your code.
Firstly, you are creating an IBOutlet of a UITableView unnecessarily. Remove that from your code.
Secondly, you are using that table view for checking if you are searching or not. That is unneccesary, as you want to show search results in the same view controller, so the correct boolean check for that instead is:
!searchcontroller.isActive || searchcontroller.searchBar.text == ""
Lastly, the error occurs exactly because the last issue stated: you are setting the searchResultsController to a phantom table view, so it gets an assertion failure, as it can't find a cell identified "cell".
Here is the fixed code:
import UIKit
class FirstViewController: UITableViewController,
UISearchResultsUpdating{
var namen = ["Waterstof","Helium","Litium","Beryllium","Boor","Koolstof","Stikstof","Zuurstof","Fluor","Neon"]
var afkortingen = ["H","He","Li","Be","B","C","N","O","F","Ne"]
var atoommassas = ["Massa: 1,008","Massa: 4,003","Massa: 6,941","Massa: 9,012","Massa: 10,81","Massa: 12,01","Massa: 14,01","Massa: 16,00","Massa: 19,00","Massa: 20,18"]
var atoomnummers = ["Nummer: 1","Nummer: 2","Nummer: 3","Nummer: 4","Nummer: 5","Nummer: 6","Nummer: 7","Nummer: 8","Nummer: 9","Nummer: 10"]
var ladingen = ["Lading: +1,-1","Lading: 0","Lading: +1","Lading: +2","Lading: +3","Lading: +2,+4,-4","Lading: +1,+2,+3,+4,+5,-1,-2,-3","Lading: -2","Lading: -1","Lading: 0"]
var electronenconfig = ["Config: 1","Config: 2","Config: 2,1","Config: 2,2","Config: 2,3","Config: 2,4","Config: 2,5","Config: 2,6","Config: 2,7","Config: 2,8"]
var searchcontroller : UISearchController!
var filterednamen = [String]()
override func viewDidLoad() {
super.viewDidLoad()
self.searchcontroller = UISearchController(searchResultsController: nil)
self.tableView.tableHeaderView = self.searchcontroller.searchBar
self.searchcontroller.searchResultsUpdater = self
self.searchcontroller.dimsBackgroundDuringPresentation = false
definesPresentationContext = true
}
func updateSearchResults(for searchController: UISearchController) {
self.filterednamen = self.namen.filter { (naam:String) -> Bool in
if naam.lowercased().contains(self.searchcontroller.searchBar.text!.lowercased()) {
return true
}else{
return false
}
}
self.tableView.reloadData()
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if !searchcontroller.isActive || searchcontroller.searchBar.text == "" {
return self.namen.count
}else {
return self.filterednamen.count
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! CustomCell
cell.afkorting.text = afkortingen[indexPath.row]
cell.name.text = namen[indexPath.row]
cell.atoommassa.text = atoommassas[indexPath.row]
cell.elektronenconfiguratie.text = electronenconfig[indexPath.row]
cell.atoomnummer.text = atoomnummers[indexPath.row]
cell.lading.text = ladingen[indexPath.row]
if !searchcontroller.isActive || searchcontroller.searchBar.text == "" {
//cell.textLabel?.text = self.namen[indexPath.row]
cell.name.text = self.namen[indexPath.row]
}else{
//cell.textLabel?.text = self.filterednamen[indexPath.row]
cell.name.text = self.filterednamen[indexPath.row]
}
return cell
}
}

Memory issue from UITable

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
}
}
}
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.
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.

Resources