Post

Replies

Boosts

Views

Activity

Reply to App icon in Launchpad displays bigger than others
MultilineHow much bigger, if you could measure for instance Xcode icon and yours. Some icons are transparent on some parts of their borders, making them look smaller. In my case, the Launchpad icon is 256*256 Xcode is the same size but looks like 230*230 Hi Claude. Thank you for the reply. I think it will be easier just to look at it: Screenshot - https://www.icloud.com/iclouddrive/05iQDEyZvyOaQWN0GRUc9-RJg#CleanShot_2021-01-18_at_15.57. Possibly because I have a canvas with 1024px and the icon size is 1024px as well. But how much smaller I should make an icon on the canvas to fix that?
Jan ’21
Reply to Invalid update: invalid number of rows in section 0 with NSFetchedResultsController
What is the log ? Is it this print: print(currency.numberOfObjects) Attach the log: LOG So, why 13 or 14 values printed ? Can't understand too. At the start the table is empty... Why there is always 13 numbers and not 1,5,6 etc... Which func is called when you click a cell in VC2 ? It's let cell = tableView.cellForRow(at: indexPath) as! PickCurrencyTableViewCell for currency in currencyArray { if currency.shortName == cell.shortName.text { currency.isPicked = !currency.isPicked coreDataManager.save() } } } There on VC2 it sorts the array of items and if shortName (EUR) equals to the shortName of pickedCell then it change it isPicked CoreData attribute from false to true. And if I was able to click again then from true to false. And save it to database after. The NSFetchedResultController is setup to filter and show in VC1 tableView only the state isPicked = true. Is it what you expect ? Not quite sure, because I expect behaviour like I pressed on cell in VC2 and VC1 should load that currency I picked based on isPicked state...
Jan ’22
Reply to How to simultaneously change textField.text in a prototype cells?
Hi Claude, thank you for the answer! What is cell ? Here is the full code for my cell. tableView shows items from NSFetchedResultsController based on predicate "isForConverter" = YES, which I set in another VC. override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "converterCell", for: indexPath) as! ConverterTableViewCell let currency = fetchedResultsController.object(at: indexPath) cell.shortName.text = currency.shortName cell.fullName.text = currency.fullName cell.numberTextField.delegate = self return cell } Then, when you change in one cell, I tried to create a global variable, then in textFieldDidEndEditing() assign that variable to a string from textField.text, then assign that variable in cellForRowAt() as cell.numberTextField.text = number and reload a tableView. As a result a received all cells display number just when tableView first loads and I can't edit any number. Also, why do you reset to "0" when editing ends ? Base textField.text string for my cell is 0, so when I click on cell I should be able to reset it to "", edit number and if I want to switch to edit another cell, I want that first cell to be 0 again. This is why I set it to 0. Take a look at the video: https://cln.sh/O3wGJE What I want: I need to be able to edit any cell's textField, type a number and all other cells as soon as I type the number, change their textField.text accordingly after calculation (for example the number I type in edited cell should be multiplied by 2 and displayed in all other cells. And I should be able to pick another cell, type number etc. take a look at the video: https://cln.sh/xjw5Od. Here if I pick any available cell, type number, then all other cells recalculate it's value based on what I typed in editable cell like live.
Jan ’22
Reply to How to simultaneously change textField.text in a prototype cells?
Thank you very much for your time spent on my question! Appreciate! You do not set the content of cell.numberTextField in cellForRowAt. Why ? This is because I want the content to be set by func which multiplies by 2 any number that was typed in currently active cell. And I don't know how I can separate active cell from all others each time I click on a new cell... Imagine I have 1, 2, 3 in 3 cells. Do you mean that when typing 5 in cell 3, cell 0 should become 2, cell 2 become 4 and cell 3 : 5 ? 8 ? 10 ? Then you type 20 in cell 0, what should be the result ? When typing 5 in cell 3 I want to receive 5x2 = 10 as an output in any other cells (cell 1 and cell 2) which is currently on the screen. Perform simple calculation (any number typed from active cell, multiple it by 2 and put the result in all other cells which is not active in the tableView as soon as I typed that number. Calculation should be displayed in a real time, not when I typed number and clicked done or closed the keyboard on active cell. you do not segregate between different cells. Why ? In this methods I just put some basic code and it should define behaviour for: textField.text = "" textField.textColor = UIColor.systemBlue as I click on cell, it becomes active, textField clears itself (by default it displays number 0) and color of active cell turns blue to distinguish which of the cell is active now. textField.text = "0" textField.textColor = UIColor.black As soon as I click on another cell to make it textField editable I turn the cell I was just editing into default 0 and text for black as for all non-editable cells What I would do: What would you do if your tableView was populated with Core Data from NSFetchedResultsController? Should I create from FRC an additional array for dataSource or I can use the one I receive from FRC? I define a dataSource I receive from FRC in my tableView cell as: override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "converterCell", for: indexPath) as! ConverterTableViewCell let currency = fetchedResultsController.object(at: indexPath) cell.shortName.text = currency.shortName cell.fullName.text = currency.fullName cell.numberTextField.delegate = self return cell }
Feb ’22
Reply to How to simultaneously change textField.text in a prototype cells?
what are the initial values in cells (from FRC ?) My FRC has a custom type called Currency. Currency is a CoreData entity which has attributes: shortName ("USD"), fullName ("American Dollar"), isPickedForConverterScreen (Bool, true), currentValue (Double: 75,44), and so on for other currencies. My tableView shows the Currency object only when isPickedForConverterScreen == true. tableView cell have 2 labels: for displaying shortName and fullName and a textField. Here is how I define it: let cell = tableView.dequeueReusableCell(withIdentifier: "converterCell", for: indexPath) as! ConverterTableViewCell let currency = fetchedResultsController.object(at: indexPath) cell.shortName.text = currency.shortName cell.fullName.text = currency.fullName return cell } You type something in a cell let's assume I have 2 cells in my tableView: USD, RUB. I click on USD cell - type number - RUB cell recalculate its textField.text as: number I typed in USD cell x RUB.CurrentValue. For example I typed 2, then 2 x 75,44 = 150,88 to display in RUB cell. Calculation should be performed live, not when I end editing USD cell What do you then get in all cells ? The thing is I need to perform a calculation for all cells based on number I typed in active cell x currentValue number stored for each Currency object. And I should be able to pick another cell with currency and calculate all other currencies based on value I typed + their currentValue So am I understood correct that my dataSource is the array of Currencies which I can receive as: let array: [Currencies] = fetchedResultsController.fetchedObjects I don't define it anywhere in my VC for now. Only when defying cell in cellForRow: let currency = fetchedResultsController.object(at: indexPath)
Feb ’22
Reply to How to format a number(text) in UITextField when user is typing?
Thank you very much, Claude! After playing with the code I found that this version is good for me: func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { let formatter = NumberFormatter() formatter.usesGroupingSeparator = true formatter.numberStyle = .decimal formatter.decimalSeparator = "." formatter.groupingSeparator = " " let completeString = textField.text!.replacingOccurrences(of: formatter.groupingSeparator, with: "") + string guard let value = Double(completeString) else { return false } numberFromTextField = value let formattedNumber = formatter.string(from: NSNumber(value: value)) ?? "" textField.text = formattedNumber if string.isEmpty { return true } return string == formatter.decimalSeparator } But I have one problem: while pressing backspace on keyboard the first press doesn't remove the last character in string, the second and the next presses do. I think the problem is in my if string.isEmpty { return true } line as I found out when you press the backspace it returns an empty string... Short gif with problem: https://cln.sh/OZOslI Any thoughts what's the problem might be?
Feb ’22
Reply to NSFetchedResultsController error: 'no object at index 5 in section at index 0'
Where do you do it ? Nowhere except at FRC delegate method didChange I showed in the initial post... Could you also show cellForRowAt delegate func ? Sure, there it is: override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "converterCell", for: indexPath) as! ConverterTableViewCell let currency = fetchedResultsController.object(at: indexPath) cell.flag.image = currencyManager.showCurrencyFlag(currency.shortName ?? "notFound") cell.shortName.text = currency.shortName cell.fullName.text = currency.fullName cell.numberTextField.tag = indexPath.row cell.numberTextField.delegate = self if let number = numberFromTextField, let pickedCurrency = pickedCurrency { cell.numberTextField.text = currencyManager.performCalculation(with: number, pickedCurrency, currency) } return cell } Also show you the method where I reload all rows except one in editing mode: func textFieldDidChangeSelection(_ textField: UITextField) { let activeTextFieldIndexPath = IndexPath(row: textField.tag, section: 0) pickedCurrency = fetchedResultsController.object(at: activeTextFieldIndexPath) guard let currencyObjects = fetchedResultsController.fetchedObjects?.count else {return} var nonActiveIndexPaths = [IndexPath]() for object in 0..<currencyObjects where object != textField.tag { nonActiveIndexPaths.append(IndexPath(row: object, section: 0)) } tableView.reloadRows(at: nonActiveIndexPaths, with: .none) } Then, after, you may call reloadData() once datasource is updated I found out that if I use reloadData() + 0.2 seconds after deletion, everything works good. But FRC should call reloadData automatically, I shouldn't use it manually... case .delete: if let indexPath = indexPath { tableView.deleteRows(at: [indexPath], with: .none) DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) { self.tableView.reloadData() } }
Feb ’22
Reply to NSFetchedResultsController error: 'no object at index 5 in section at index 0'
But difficult to say what to write exactly without the complete code of the class. Attached is the complete class code: Complete Code Usually, this is handled by doing the call (to self.tableView.reloadData()) in a completion handler of the calling and I can call just tableView.reloadData() in the completion hander, everything works perfect too, except the cell deletion animation lost its smoothness, it became fast and ugly. And if I use +0.2 seconds the animation saves the smoothness like it was. Also this error happens only when I delete a lot of cells one after another (> 10 cells) like on the GIF from initial post. If I will delete 1-2 cells - there won't be any error and no need to call tableView.reloadData().
Feb ’22
Reply to NSFetchedResultsController error: 'no object at index 5 in section at index 0'
Could you show code with reloadData() in completion handler, in case we can find a way to improve smoothness. Sure. I just add reloadData() to .delete case. Check the GIF with animation in that case: https://cln.sh/F551dX func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {         switch type {         case .update:             if let indexPath = indexPath {                 tableView.reloadRows(at: [indexPath], with: .none)             }         case .move:             if let indexPath = indexPath, let newIndexPath = newIndexPath {                 tableView.moveRow(at: indexPath, to: newIndexPath)             }         case .delete:             if let indexPath = indexPath {                 tableView.deleteRows(at: [indexPath], with: .none)                 tableView.reloadData()             }         case .insert:             if let newIndexPath = newIndexPath {                 tableView.insertRows(at: [newIndexPath], with: .none)             }         default:             tableView.reloadData()         }     } Then version with asyncAfter .now + 0.5. Check the GIF with animation: https://cln.sh/WK6F8r func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {         switch type {         case .update:             if let indexPath = indexPath {                 tableView.reloadRows(at: [indexPath], with: .none)             }         case .move:             if let indexPath = indexPath, let newIndexPath = newIndexPath {                 tableView.moveRow(at: indexPath, to: newIndexPath)             }         case .delete:             if let indexPath = indexPath {                 tableView.deleteRows(at: [indexPath], with: .none) DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {                 self.tableView.reloadData() }             }         case .insert:             if let newIndexPath = newIndexPath {                 tableView.insertRows(at: [newIndexPath], with: .none)             }         default:             tableView.reloadData()         }     } Can't you set a var fetchedCompleted that would be set true after fetch But where is the fetch ends? Where to call that var?
Feb ’22
Reply to NSFetchedResultsController error: 'no object at index 5 in section at index 0'
Claude, it seems I found out what the reason of that crash was. This is what my print() tryings gave: https://cln.sh/jpB5tG What is a pickedCurrency: this is a global variable of custom type Currency which I created to receive its attribute currentValue (Double, 87.88). I need that value only from the picked to edit cell. After I use that value for calculation in cellForRowAt() and result of the calculation fills all other cells which is not in edit now. I define pickedCurrency in textFieldDidBeginEditing() because there I receive the exact row of Currency I picked to edit: func textFieldDidBeginEditing(_ textField: UITextField) { pickedCurrency = fetchedResultsController.object(at: IndexPath(row: textField.tag, section: 0)) numberFromTextField = 0 textField.textColor = UIColor(named: "BlueColor") textField.placeholder = "0" textField.text = "" } And then use it's value in cellForRowAt to calculate all other cells values based on pickedCell value: override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "converterCell", for: indexPath) as! ConverterTableViewCell let currency = fetchedResultsController.object(at: indexPath) cell.flag.image = currencyManager.showCurrencyFlag(currency.shortName ?? "notFound") cell.shortName.text = currency.shortName cell.fullName.text = currency.fullName cell.numberTextField.tag = indexPath.row cell.numberTextField.delegate = self if let number = numberFromTextField, let pickedCurrency = pickedCurrency { cell.numberTextField.text = currencyManager.performCalculation(with: number, pickedCurrency, currency) } return cell } It seems when I delete a lot of cells and then click on random cell to edit it's not updates its IndexPath(row: textField.tag, section: 0)... And this is why when I call reloadData() it refreshes pickedCurrency. Maybe there is a way to receive Currency object I picked for editing in cellForRowAt()?
Feb ’22
Reply to How to set a UITableView Editing Mode from a swipe action?
Also I have one more related problem I can't fix there. My prototype cell has a numberTextField (0 by default). When I entering the edit mode I want it to be hidden and back to visible when edit mode is off. Here is the code for that behaviour in cellForRowAt(): cell.numberTextField.isHidden = tableView.isEditing ? true : false return cell But the textField is still visible when I entering the edit mode: https://cln.sh/0hXOKg Any solutions comes in mind? I tried to initialise cell as: let cell = tableView.dequeueReusableCell(withIdentifier: "converterCell") as! ConverterTableViewCell and assess its textfield property within turnEditing() but no luck.
Feb ’22