I am modifying my paid for app to a free with IAP.
Some group types are free and some will need to be paid for.
On the tableView controller, there is a padlock UIImageView that displays each "locked" item if it is a part of a locked group.
When someone buys that group, or all, that padlock is meant to disappear. This padlock is not a part of the code that prevents the user from seeing the details as I have that code somewhere else and it works fine.
Initially, "Padlock" displays accurately. However, If I scroll up and down on the tableView, the padlocks will randomly disappear.
How to prevent this?
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
//
// We need to fetch our reusable cell.
//
let cell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: Resource.SpeciesCell)!
//
// Get all of the components of the cell.
//
let specieImage: UIImageView = cell.viewWithTag(Resource.SpeciesImageTag) as! UIImageView
let specieName: UILabel = cell.viewWithTag(Resource.SpeciesNameTag) as! UILabel
let specieGenus: UILabel = cell.viewWithTag(Resource.SpeciesGenusTag) as! UILabel
let specieFamily: UILabel = cell.viewWithTag(Resource.SpeciesFamilyTag) as! UILabel
// Set our name, family and genus labels from our data.
//
specieName.text = self.species[(indexPath as NSIndexPath).row].specie
specieFamily.text = ""
specieGenus.text = self.species[(indexPath as NSIndexPath).row].speciesSubgroup
// **** Adding Padlock Begins HERE ****
let padLock: UIImageView = cell.viewWithTag(Resource.SpeciesCategoryLabelTag) as! UIImageView
padLock.image = UIImage(named: "PadlockIcon")
padLock.alpha = 0.7
let speciesGroupFreeArray: Array<String>
let speciesGroupVertebratesArray: Array<String>
let speciesGroupInvertebratesArray: Array<String>
speciesGroupFreeArray = ["eels", "Mammals", "Annelids", "Bivalvians", "Cephalopods", "Cool oddities", "Crustacean", "Echinoderms", "Hydrozoans", "Isopods"]
speciesGroupVertebratesArray = ["Fish", "Sharks", "Rays", "Reptilia", "Syngnathiformes"]
speciesGroupInvertebratesArray = ["Corals", "Gastropods"]
let fishesPurchased = UserDefaults.standard.bool (forKey: "ReefLife5Fishes")
let sharksPurchased = UserDefaults.standard.bool (forKey: "ReefLife6Sharks")
let nudisPurchased = UserDefaults.standard.bool (forKey: "ReefLife7Nudis")
let turtlesPurchased = UserDefaults.standard.bool (forKey: "ReefLife8Turtles")
let seahorsesPurchased = UserDefaults.standard.bool (forKey: "ReefLife9Seahorses")
let coralsPurchased = UserDefaults.standard.bool (forKey: "ReefLife4Corals")
let vertebratesPurchased = UserDefaults.standard.bool (forKey: "ReefLife3Vertebrates")
let invertebratesPurchased = UserDefaults.standard.bool (forKey: "ReefLife2Invertebrates")
let fullPurchased = UserDefaults.standard.bool (forKey: "ReefLife1Full")
let categoryName = self.species[(indexPath as NSIndexPath).row].group
if fullPurchased == true {
padLock.isHidden = true
} else if speciesGroupVertebratesArray.contains(categoryName) {
if vertebratesPurchased == true {
padLock.isHidden = true
} else {
if categoryName == "Fish" {
if fishesPurchased == true{
padLock.isHidden = true
} else{
}
} else if (categoryName == "Sharks" || categoryName == "Rays" ) {
if sharksPurchased == true{
padLock.isHidden = true
} else{
}
} else if categoryName == "Syngnathiformes" {
if seahorsesPurchased == true{
padLock.isHidden = true
} else{
}
} else if categoryName == "Reptilia" {
if turtlesPurchased == true{
padLock.isHidden = true
} else{
}
}
}
} else if speciesGroupInvertebratesArray.contains(categoryName) {
if invertebratesPurchased == true {
padLock.isHidden = true
} else {
if categoryName == "Corals" {
if coralsPurchased == true{
padLock.isHidden = true
} else{
}
} else if categoryName == "Gastropods" {
if nudisPurchased == true{
padLock.isHidden = true
} else{
}
}
}
}
if speciesGroupFreeArray.contains(categoryName) {
padLock.isHidden = true
}
// **** Adding Padlock Ends HERE ****
//
// We now need to set our photo. First, we need to fetch the photo based on our specie
// id.
//
let photos = AppDelegate.getRLDatabase().getSpeciePhotos(self.species[(indexPath as NSIndexPath).row].id)
//
// Set the image for our UIImageView.
//
if photos.isEmpty != true
{
specieImage.clipsToBounds = true
specieImage.contentMode = .scaleAspectFill
specieImage.image = UIImage(named: photos[0].name)
// specieImage.image = UIImage(named: photos[0].name)?.resizeTo(specieImage.bounds)
}
else
{
specieImage.image = UIImage(named: Resource.UnknownImage)?.resizeTo(specieImage.bounds)
}
//
// Return our new cell.
//
return cell
}
Please try replace this
if speciesGroupFreeArray.contains(categoryName) {
padLock.isHidden = true
}
to
padLock.isHidden = speciesGroupFreeArray.contains(categoryName)
Your code only ever sets padlock.isHidden = true. If you get a recycled cell where the padlock is already hidden, there's nothing to unhide it.
You need to explicitly set the padlock isHidden state in all cases.
Given your somewhat contorted code for setting the isHidden property, the simplest way to fix your current code would be to set padlock.isHidden = false At the beginning of your cellForRowAt() method. Then, if none of the cases set isHidden to true, it will always be unbidden, even in a case where you are reconfiguring a recycled cell where the padlock was hidden.
EDIT:
This a key take-away for managing table views and collection views in iOS. Always assume that a cell comes to you with all views set to a non-default state. Your code always needs to explicitly set every view to a specific state.
Think of a table view cell as a paper patient info form at a doctor's office where the office recycles the forms, and doesn't erase the info left by the previous patient. You always have to erase the info left by the previous patient. If you don't have an allergy to peanuts, it's not enough to simply not check that box. You have to erase the previous check marks and other info, or the previous patient's info will get mixed up with yours.
That's what's happening with your padlock.isHidden state. You're assuming it starts out in the default state, but it may not.
Related
I am attempting to have a table view that lists multiple things and allows a user to go through and select multiple cells with checkboxes. My code works up until a certain point, the problem is that the app crashes with the following error
Fatal error: Unexpectedly found nil while unwrapping an Optional value
whenever I call the following code
swift let currentCell = recommendToFriendTableView.cellForRow(at: selectedRow[i]) as? RecommendToFriendsTableViewCell
Here is the method where we set up the cells
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if (tableView == self.friendListTableView) {
let cell: FriendListTableViewCell = tableView.dequeueReusableCell(withIdentifier: "FriendListCell") as! FriendListTableViewCell
let rowNumber = (indexPath as NSIndexPath).row
var name = ""
if searchActive {
name = filtered[rowNumber]
}
else {
name = names[rowNumber]
}
cell.friendNameLabel.text = name
cell.friendNameLabel.backgroundColor = tableViewBgColor
cell.friendNameLabel.textColor = textColor
cell.recommendToFriendButton.layer.borderWidth = 1
cell.recommendToFriendButton.layer.borderColor = tableViewBgColor.cgColor
cell.recommendToFriendButton.layer.cornerRadius = 6
cell.recommendToFriendButton.backgroundColor = buttonBgColor
cell.backgroundColor = tableViewBgColor
//set target for buttons
cell.recommendToFriendButton.tag = rowNumber
cell.recommendToFriendButton.addTarget(self, action:#selector(recommendToFriendButtonClicked), for: UIControl.Event.touchUpInside)
return cell
}
else {
let cell: RecommendToFriendsTableViewCell = tableView.dequeueReusableCell(withIdentifier: "RecommendToFriendsCell") as! RecommendToFriendsTableViewCell
let rowNumber = (indexPath as NSIndexPath).row
// set the content view background color
cell.contentView.backgroundColor = tableViewBgColor
// set the text color
cell.nameLabel.textColor = textColor
var dict_friend = NSMutableDictionary()
if searchActive {
dict_friend = filteredFriendsArray[rowNumber]
}
else {
dict_friend = friendsArray[rowNumber]
}
let name = dict_friend["name"] as! String
cell.nameLabel.text = name
let friendUID = dict_friend["uid"] as! String
cell.friendID = friendUID
let imageAddress = dict_friend["photo"] as? String
if imageAddress != "unavailable" && imageAddress != nil && imageAddress != ""{
//Swift forces us to wrap strings as optional to use them in logic
if let imageURL = imageAddress as String? {
//Swift forces us to wrap strings as optional to use them in logic
if let image = imageURL as String? {
//We convert the string into a URL and get the image
let url = URL(string: image)
URLSession.shared.dataTask(with: url!, completionHandler: { (data, response, error) in
if error != nil {
print(error!)
return
}
//We create a new async thread to download and update the image
DispatchQueue.main.async {
//imageView.image = UIImage(data: data!)
cell.photoImageView.image = UIImage(data:data!)
}
}).resume()
}
} else {
cell.photoImageView!.image = UIImage(named: "placeholder-profile-male.png")
}
} else {
cell.photoImageView!.image = UIImage(named: "placeholder-profile-male.png")
}
cell.checkBoxImageView.image = cell.checkBoxImageView.image!.withRenderingMode(.alwaysTemplate)
cell.checkBoxImageView.tintColor = textColor
// Style the profile photo to show in a circle
cell.photoImageView.layer.borderWidth = 0
cell.photoImageView.layer.borderColor = tableViewBgColor.cgColor
// Set cornerRadius = a square UIImageView frame size width / 2
// In our case, UIImageView height = width = 60 points
cell.photoImageView.layer.cornerRadius = 30
cell.photoImageView.clipsToBounds = true
cell.selectionStyle = .none // to prevent cells from being "highlighted"
return cell
}
}
This is the method where we interact with them. The crash happens on a cellForRow call for a cell that is out of view (aka dequeued)
var firstFriendName: String = ""
var numberOfFriends = 0
if let selectedRow = recommendToFriendTableView.indexPathsForSelectedRows {
numberOfFriends = selectedRow.count
for i in 0..<selectedRow.count {
let currentCell = recommendToFriendTableView.cellForRow(at: selectedRow[i]) as! RecommendToFriendsTableViewCell
let friendID = currentCell.friendID
idList.append(",\(friendID)")
}
let firstSelectedCell = recommendToFriendTableView.cellForRow(at: selectedRow[0]) as! RecommendToFriendsTableViewCell
firstFriendName = firstSelectedCell.nameLabel.text!
After about a day of experimenting, I've yet to figure out the actual problem (other than the observation that it appears to be in regards to calling a dequeued cell)
Any help is appreciated.
When this line
let currentCell = recommendToFriendTableView.cellForRow(at: selectedRow[i]) as! RecommendToFriendsTableViewCell
crashes this means you access a non-visble cell so either use
if let currentCell = recommendToFriendTableView.cellForRow(at: selectedRow[i]) as? RecommendToFriendsTableViewCell { }
or better use the dataSource array of the table to get the data that you want to gran wrongly from the cell
Can you guys give me some help to hide the image and name if the message it's from the same user... I want only to show it for the first message...and if that user send more not to show anymore until another Id appear... like whatsapp does it..
currently I m having like this to show u an example
[![enter image description here][1]][1]
var isTheSameUser = false
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let selectedChat = chat[indexPath.row]
let myId = String(describing:UserDefaults.standard.value(forKey: "user_id")!)
let messageUserId = String(describing:selectedChat.owner_id)
if messageUserId == myId {
return myMessageCell(indexPath: indexPath)
}else {
return userMessageCell(indexPath: indexPath)
}
}
func myMessageCell(indexPath :IndexPath) -> UITableViewCell {
let cell = self.mainTableView.dequeueReusableCell(withIdentifier: "MyMessageTableViewCell", for: indexPath) as! MyMessageTableViewCell
let selectedChat = self.chat[indexPath.row]
let myId = String(describing:UserDefaults.standard.value(forKey: "user_id")!)
// Show only for the first message
// photo image
if !isTheSameUser {
cell.profileImageView.isHidden = false
cell.profileNameLabel.isHidden = false
} else {
cell.profileImageView.isHidden = true
cell.profileNameLabel.isHidden = true
}
if let userInfo = getUserMemberOf(userId: messageUserId) {
cell.profileImageView.imageFromURL(urlString: userInfo["photo"] as! String)
} else {
cell.profileImageView.image = #imageLiteral(resourceName: "accountIcon")
}
cell.profileNameLabel.text = "\(String(describing: cell.userProfileInfo!["name"]!))"
return cell
You need check the previous chat messsage id like for every message
if indexPath.row != 0 {
let prevItem = chat[indexPath.row - 1]
let currentItem = chat[indexPath.row]
if prevItem.owner_id! == currentItem.owner_id! {
// hide label and image
}else {
// show them
}
}
else {
// show them
}
My problem: the text on some of my UILabels (the answers for the questions) in a particular cell are blank when I scroll down (only the 3rd through 7th labels, as you'll see in my code the first and second are always set and seem to magically work no matter what). It only happens for some cells, for most cells when they render the first time it's correct (not always, though).
I've been struggling with this for a few hours now and can't seem to fix it. I'm pretty sure it has to do with table cell reuse, but I set the data in a didSet block in my custom table cell and even tried the prepareForReuse() override as suggested here: Stop the reuse of custom cells Swift. Nothing seems to work, I still have some cells (only some, not all!) that lose some of their text when I scroll through my tableView. What am I missing?
Here is the didSet block for my custom cell class QuestionCustomCell (and if it helps, the NSLog printout does show the correct text that should be in the cell when I scroll down, but it doesn't render):
var cellQuestion: Question! {
didSet {
questionLabel.text = cellQuestion.topQuestion
questionLabel.sizeToFit()
//definitely at least 2 answers
switchLabel1.text = cellQuestion.theResponses[0]
switchLabel2.text = cellQuestion.theResponses[1]
if(cellQuestion.theResponses[2] == nil) {
switch3.isHidden = true
switchLabel3.isHidden = true
} else {
switch3.isHidden = false
switchLabel3.text = cellQuestion.theResponses[2]
let questionName : String = cellQuestion.topQuestion
NSLog("question: "+questionName+" response: "+cellQuestion.theResponses[2]!)
}
if(cellQuestion.theResponses[3] == nil) {
switch4.isHidden = true
switchLabel4.isHidden = true
} else {
switch4.isHidden = false
switchLabel4.text = cellQuestion.theResponses[3]
let questionName : String = cellQuestion.topQuestion
NSLog("question: "+questionName+" response: "+cellQuestion.theResponses[3]!)
}
if(cellQuestion.theResponses[4] == nil) {
switch5.isHidden = true
switchLabel5.isHidden = true
} else {
switch5.isHidden = false
switchLabel5.text = cellQuestion.theResponses[4]
let questionName : String = cellQuestion.topQuestion
NSLog("question: "+questionName+" response: "+cellQuestion.theResponses[4]!)
}
if(cellQuestion.theResponses[5] == nil) {
switch6.isHidden = true
switchLabel6.isHidden = true
} else {
switch6.isHidden = false
switchLabel6.text = cellQuestion.theResponses[5]
let questionName : String = cellQuestion.topQuestion
NSLog("question: "+questionName+" response: "+cellQuestion.theResponses[5]!)
}
if(cellQuestion.theResponses[6] == nil) {
switch7.isHidden = true
switchLabel7.isHidden = true
} else {
switch7.isHidden = false
switchLabel7.text = cellQuestion.theResponses[6]
let questionName : String = cellQuestion.topQuestion
NSLog("question: "+questionName+" response: "+cellQuestion.theResponses[6]!)
}
restorePriorAnswer()
}
}
And here is restorePriorAnswer() (I use it so the cells remember whether the switch was off or on when reused - that does work):
func restorePriorAnswer ( )
{
if(cellQuestion.theAnswer != nil)
{
self.cellDelegate.restorePrior(forCell: self, forShortName: cellQuestion.shortName, subAction: "\(cellQuestion.theAnswer!.answerSelect)")
print("Prior answer was \(cellQuestion.theAnswer!.answerSelect)")
switch(cellQuestion.theAnswer!.answerSelect)
{
case 0:
switch1.isOn = true
break
case 1:
switch2.isOn = true
break
case 2:
switch3.isOn = true
break
case 3:
switch4.isOn = true
break
case 4:
switch5.isOn = true
break
case 5:
switch6.isOn = true
break
case 6:
switch7.isOn = true
break
default:
self.cellDelegate.restorePrior(forCell: self, forShortName: "Control", subAction: "restorePriorAnswer (Bad Select Value)")
break
}
}
else
{
switch1.setOn(false, animated: false)
switch2.setOn(false, animated: false)
switch3.setOn(false, animated: false)
switch4.setOn(false, animated: false)
switch5.setOn(false, animated: false)
switch6.setOn(false, animated: false)
switch7.setOn(false, animated: false)
}
}
And here is my cellForRowAtIndexPath:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell:QuestionCustomCell = self.tableView.dequeueReusableCell(withIdentifier: cellReuse, for: indexPath) as! QuestionCustomCell
if((currentQuestion?.canSubsume())!) {
if((currentQuestion?.shouldDoSubsume())!) {
//since this apparently refreshes random rows, we need to hard-code which row goes where
if(indexPath.row == 0) {
cell.cellQuestion = currentQuestion
} else {
let rowQuestion: Question = (currentQuestion?.getSubsumeList().getQuestion(shortID: currSubsumeArray![indexPath.row - 1]))!
cell.cellQuestion = rowQuestion
}
} else {
//there should only be one cell at this point - the first one
cell.cellQuestion = currentQuestion
//print out the first question, just to make sure...
let logStringOne : String = "the current question: " + (currentQuestion?.topQuestion)!
NSLog(logStringOne)
let logString : String = "the first subsumed question: " + (currentQuestion?.subsumeList!.firstQuestion)!
NSLog(logString)
}
} else {
cell.cellQuestion = currentQuestion
}
cell.selectionStyle = UITableViewCellSelectionStyle.none
cell.cellDelegate = self
return cell
}
Please let me know if I'm missing any code you think is helpful to solve the problem. Everything else works besides the labels - the switches remember if they were on or off when scrolling back and forth, the appropriate switches are hidden if their appropriate slot in the answers array is nil, and all other text is as it should be - except some of the labels for the answers, which is the problem. As I mentioned, I tried the prepareForReuse() method but it didn't do anything, so I took it out.
I apologize, it was staring me in the face for several hours and I didn't realize it. In the didSet block I had hidden the labels if they weren't supposed to be used, like this:
if(cellQuestion.theResponses[2] == nil) {
switch3.isHidden = true
switchLabel3.isHidden = true
} else {
switch3.isHidden = false
switchLabel3.text = cellQuestion.theResponses[2]
}
but in the else block, I didn't unhide them...when a cell was loaded fresh and not reused, it had no issue because the label had never been hidden previously. But in a reused cell, it was, and so the label didn't exist for those cells that were reused.
So, each of these if/else blocks should have a switchLabelx.isHidden = falsein them, with x being the appropriate number. Not that I wish staring at code for hours on anyone, but hopefully someone will find this useful.
im having a real nightmare with my project where i need to save cell contents to an object, for each object in an array. I cant get this to work by looping through table cells adn array objects and trying to match them all up.
So my next idea was to add didFinishEditing related functions into the cellForRowAt function?
Im not sure this would work either, but this is what i have:
Each row here has a label for the set, a picker for the reps that can be scrolled to a number, and a textfield to put a weight. Then i save each row as an object storing the set, rep and weight.
Issue is when editing this, how can i save these again overwriting the old values? Hence my plan above to use didFinishEditing methods.
My previous plan was the code below, but i cant figure out the annotated part. So i was hoping someone had guidance on how i can approach saying when editing rather than this save button function that doesnt work!
func saveUserExerciseSets() {
if userExercise == nil {
print("CREATING A FRESH SET OF SETS FOR THE NEW EXERCISE")
for cell in self.customSetsTable.visibleCells as! Array<NewExerciseTableViewCell> {
print("SAVING THESE CELLS \(customSetsTable.visibleCells)")
let newUserExerciseSet = UserExerciseSet(context: self.managedObjectContext)
newUserExerciseSet.setPosition = Int64(cell.setNumber.text!)!
newUserExerciseSet.setReps = Int64(cell.repsPicker.selectedRow(inComponent: 0))
newUserExerciseSet.parentExerciseName = self.userExerciseName.text
if self.localeIdentifier == "en_GB" {
let kgWeight = Measurement(value: Double(cell.userExerciseWeight.text!)!, unit: UnitMass.kilograms)
newUserExerciseSet.setWeight = kgWeight as NSObject?
newUserExerciseSet.initialMetricSystem = self.localeIdentifier
} else if self.localeIdentifier == "en_US" {
let lbsWeight = Measurement(value: Double(cell.userExerciseWeight.text!)!, unit: UnitMass.pounds)
newUserExerciseSet.setWeight = lbsWeight as NSObject?
newUserExerciseSet.initialMetricSystem = self.localeIdentifier
}
let fetchRequest: NSFetchRequest<UserExercise> = UserExercise.fetchRequest()
fetchRequest.predicate = NSPredicate(format: "name == %#", self.exerciseNameToAddTo!)
do {
let parentExercise = try self.managedObjectContext.fetch(fetchRequest).first
parentExercise?.addToExercisesets(newUserExerciseSet)
print("SET ADDED TO EXERCISE")
} catch {
print("Fetching Routine Failed")
}
}
} else if self.userExercise != nil {
print("UPDATING EXISTING SETS FOR THE EXISTING EXERCISE")
let cells = self.customSetsTable.visibleCells as! Array<NewExerciseTableViewCell>
for cell in cells {
let exerciseSets = self.userExercise?.exercisesets?.allObjects as! [UserExerciseSet]
let sortedexerciseSets = exerciseSets.sorted { ($0.setPosition < $1.setPosition) }
let cellsSet = sortedexerciseSets //match the sortedexerciseSets set object to the cell index positions
cellsSet.setPosition = Int64(setsCell.setNumber.text!)!
cellsSet.setReps = Int64(setsCell.repsPicker.selectedRow(inComponent: 0))
if self.localeIdentifier == "en_GB" {
let kgWeight = Measurement(value: Double(cell.userExerciseWeight.text!)!, unit: UnitMass.kilograms)
cellsSet.setWeight = kgWeight as NSObject?
} else if self.localeIdentifier == "en_US" {
let lbsWeight = Measurement(value: Double(cell.userExerciseWeight.text!)!, unit: UnitMass.pounds)
cellsSet.setWeight = lbsWeight as NSObject?
}
cellsSet.parentExerciseName = self.userExerciseName.text
}
}
do {
try self.managedObjectContext.save()
print("THE SET HAS BEEN SAVED")
} catch {
fatalError("Failure to save context: \(error)")
}
delegate?.didFinishEditing()
self.dismiss(animated: true, completion: nil)
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as? NewExerciseTableViewCell
else {
fatalError("Unexpected Index Path")
}
cell.backgroundColor = UIColor.customBackgroundGraphite()
cell.textLabel?.textColor = UIColor.white
cell.repsPicker.dataSource = self
cell.repsPicker.delegate = self
configure(cell, at: indexPath)
return cell
}
func configure(_ cell: NewExerciseTableViewCell, at indexPath: IndexPath) {
// configuring cells when theres a loaded exercise causes the issues --------------------
if self.userExercise != nil {
print("RESTORING CELLS FOR THE EXISTING EXERCISE")
let unsortedExerciseSets = self.userExercise?.exercisesets?.allObjects as! [UserExerciseSet]
let exerciseSets = unsortedExerciseSets.sorted { ($0.setPosition < $1.setPosition) }
let cellsSet = exerciseSets[indexPath.row]
cell.setNumber.text = String((indexPath.row) + 1)
let indexRow = Int(cellsSet.setReps)
print("INDEX ROW INT IS \(indexRow)")
cell.repsPicker.selectRow(indexRow, inComponent: 0, animated: true) //fix this crashing issue!
let localeIdentifier = Locale(identifier: UserDefaults.standard.object(forKey: "locale") as! String)
let setWeight = cellsSet.setWeight as! Measurement<UnitMass>
let formatter = MassFormatter()
formatter.numberFormatter.locale = localeIdentifier
formatter.numberFormatter.maximumFractionDigits = 2
if localeIdentifier.usesMetricSystem {
let kgWeight = setWeight.converted(to: .kilograms)
let finalKgWeight = formatter.string(fromValue: kgWeight.value, unit: .kilogram)
let NumericKgResult = finalKgWeight.trimmingCharacters(in: CharacterSet(charactersIn: "0123456789.").inverted)
cell.userExerciseWeight.text = NumericKgResult
} else {
let lbsWeight = setWeight.converted(to: .pounds)
let finalLbWeight = formatter.string(fromValue: lbsWeight.value, unit: .pound)
let NumericLbResult = finalLbWeight.trimmingCharacters(in: CharacterSet(charactersIn: "0123456789.").inverted)
cell.userExerciseWeight.text = NumericLbResult
}
} else if self.userExercise == nil {
print("NEW SET CELL ADDED FOR FRESH EXERCISE")
cell.setNumber.text = String((indexPath.row) + 1)
}
}
Try something like this to match the setIds correctly. That's where I think the issue is.
for x in sortedexerciseSets {
if x.setPosition == Int64(setsCell.setNumber.text!)! {
//save
}
}
Proper way to do it would be to have an array of those sets (I guess, since you tagged core-data, they are instances of NSManagedObject?). When user does ANY change in the cell (write new value in the text field or scroll to another value for reps) you need to update the approproate object in your array immediately. Then you could call save on NSManagedObjectContext when you're sure you want to save changes, or just call rollback on the context to cancel all changes.
I have this problem, I have a tableview with 3 different kind of news manage by segmented control. When I scrolled the news stays for example in the fifth new, if I click in the second segment, appears in the position 5 . Is not showing the news from the segment 1(the new one),at row 0 (beginning) , stays in the position I leave when I was scrolling. Why is happening this? what I'm doing wrong?. I'm using one tableview for the 3 different kinds of news and reload the tableview data every time I change the segment.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
NSLog("selectedSegmentIndex: \(self.sectionSegmentedControl.selectedSegmentIndex) - Row: \(indexPath.row)")
let cell:UITableViewCell = self.tableview.dequeueReusableCellWithIdentifier("Cell")!
// Grab the elements using the tag
let labelTitle:UILabel? = cell.viewWithTag(1) as! UILabel?
let labelSection:UILabel? = cell.viewWithTag(2) as! UILabel?
let labelDate:UILabel? = cell.viewWithTag(3) as! UILabel?
let imageView:UIImageView? = cell.viewWithTag(4) as! UIImageView?
// Check which segment to get data from
switch self.sectionSegmentedControl.selectedSegmentIndex {
case 0:
// If segment is 0, take data from cover News
if (indexPath.row <= self.coverNews.count - 1){
//Current new to display
let currentNewToDisplay = self.coverNews[indexPath.row]
//let currentNewToDisplay = self.news[indexPath.row]
// Get the image and assign to the imageView
if let actualImageView = imageView {
// Imageview actually exists
if currentNewToDisplay.imageUrl != "" {
// Image url exists, so download it
let imageUrl:NSURL? = NSURL(string: currentNewToDisplay.imageUrl)
// Download image with SDWebImage library
if let url = imageUrl {
actualImageView.sd_setImageWithURL(url)
}
}
}
// Get the news title and assign to the label
if let actualLabelTitle = labelTitle {
let title = currentNewToDisplay.title
actualLabelTitle.text = title
actualLabelTitle.numberOfLines = 0
actualLabelTitle.minimumScaleFactor = 0.1
}
// Get the news date and assign to the label
if let actualLabelDate = labelDate {
let character = "| "
actualLabelDate.text = character + currentNewToDisplay.date_short
}
// Get the news section and assign to the label
if let actualabelSection = labelSection {
actualabelSection.text = currentNewToDisplay.section
}
}
case 1:
// If segment is 1, take data from toprated News
if (indexPath.row <= self.topratedNews.count - 1){
let currentNewToDisplay2 = self.topratedNews[indexPath.row]
// Get the image and assign to the imageView
if let actualImageView2 = imageView {
// Imageview actually exists
if currentNewToDisplay2.imageUrl != "" {
// Image url exists, so download it
let imageUrl2:NSURL? = NSURL(string: currentNewToDisplay2.imageUrl)
// Download image with SDWebImage library
if let url2 = imageUrl2 {
actualImageView2.sd_setImageWithURL(url2)
}
}
}
// Get the news title and assign to the label
if let actualLabelTitle2 = labelTitle {
actualLabelTitle2.text = currentNewToDisplay2.title
actualLabelTitle2.numberOfLines = 0
actualLabelTitle2.minimumScaleFactor = 0.1
}
// Get the news date and assign to the label
if let actualLabelDate2 = labelDate {
let character2 = "| "
actualLabelDate2.text = character2 + currentNewToDisplay2.date_short
}
// Get the news section and assign to the label
if let actualabelSection2 = labelSection {
actualabelSection2.text = currentNewToDisplay2.section
}
}
case 2:
if (indexPath.row <= self.latestNews.count - 1){
// If segment is 2, take data from latestNews News
let currentNewToDisplay3 = self.latestNews[indexPath.row]
// Get the image and assign to the imageView
if let actualImageView3 = imageView {
// Imageview actually exists
if currentNewToDisplay3.imageUrl != "" {
// Image url exists, so download it
let imageUrl3:NSURL? = NSURL(string: currentNewToDisplay3.imageUrl)
// Download image with SDWebImage library
if let url3 = imageUrl3 {
actualImageView3.sd_setImageWithURL(url3)
}
}
}
// Get the news title and assign to the label
if let actualLabelTitle3 = labelTitle {
actualLabelTitle3.text = currentNewToDisplay3.title
actualLabelTitle3.numberOfLines = 0
actualLabelTitle3.minimumScaleFactor = 0.1
}
// Get the news date and assign to the label
if let actualLabelDate3 = labelDate {
let character3 = "| "
actualLabelDate3.text = character3 + currentNewToDisplay3.date_short
}
// Get the news section and assign to the label
if let actualabelSection3 = labelSection {
actualabelSection3.text = currentNewToDisplay3.section
}
}
default:
break
}
// Set insets to zero
cell.layoutMargins = UIEdgeInsetsZero
return cell
}
// MARK: Segmented Control
#IBAction func segmentedChanged(sender: UISegmentedControl) {
switch self.sectionSegmentedControl.selectedSegmentIndex {
case 0:
// If segment is 0, return rows for coverNews array
if (self.coverNews.count == 0) {
loadNews()
}else{
dispatch_async(dispatch_get_main_queue(), {
self.tableview.reloadData()
})
}
case 1:
// If segment is 1, return rows for topratedNews array
if (self.topratedNews.count == 0) {
loadNews()
}else{
dispatch_async(dispatch_get_main_queue(), {
self.tableview.reloadData()
})
}
case 2:
// If segment is 2, return rows for latestNews array
if (self.latestNews.count == 0) {
loadNews()
}else{
dispatch_async(dispatch_get_main_queue(), {
self.tableview.reloadData()
})
}
default:
break
}
}
// MARK: Load News
func loadNews(){
switch(sectionSegmentedControl.selectedSegmentIndex){
case 0:
self.model.getFeedNews("cover")
case 1:
self.model.getFeedNews("toprated")
case 2:
self.model.getFeedNews("latest")
default:
break
}
}