Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I'd like to find out all UITableViewCells (number varies) which have an detailTextLabel with the text "Done" in it. How can I do this in Swift?
You should not do this. Neither in Swift nor in any other language. You should query the dataSource because that is where the true state is stored. If you scroll a cell offscreen it get's reused, and the text gets set to something else. You can't rely on that information. Even worse, if you rely on texts in your cell you never get the whole picture about your dataSource, because the cells that are offscreen simply don't exist.
Here's what you should do: Somewhere in your code you set the text to "Done" depending on the state of an object. Use the same decision to find all objects that are done.
For example, if your object has an isDone getter, you hopefully use something like this to create the cell:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("ProjectCell", forIndexPath: indexPath) as ProjectCell
let project = allProjects[indexPath.row]
if project.isDone {
cell.detailTextLabel?.text = "Done"
}
else {
cell.detailTextLabel?.text = nil
}
return cell
}
as you can see you decide depending on isDone if the "Done" text will be displayed.
So you can create a function that uses the same test to create an array that contains only projects that are done.
func projectsThatAreDone(allProjects: [Project]) -> [Project] {
let matchingProjects = allProjects.filter {
return $0.isDone
}
return matchingProjects
}
and you then use let doneProjects = projectsThatAreDone(allProjects)
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 days ago.
Improve this question
I was implementing multiple sliders in a page in ios 14.2. The UI had a tableview and 4 cells. Each cells had a slider. It was working fine in 14.2. But when I updated my iPhone os to 16.3.1, the sliders are not behaving properly.
When I try to move the first slider, the first and fourth slider is moving at the same time. And when second slider is moved, second and third sliders are getting moved. Have anyone encountered with this issue before.
You might be reloading/updating you tableView when slider changes. Do not reload table view.
Create a Model class for you cell
class MyModel {
var title:String?
var sliderValue:CGFloat
}
Pass the model to cell and update you model directly
class MyCustomCell:UITableViewCell{
var model:MyModel!
func configure(item:MyModel) {
self.model = item
}
#IBAction func sliderChanges(_ sender: UiSlider) {
self.model.sliderValue = sender.value
}
}
And finally pass the change your cell for indexPath method
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "MyCustomCell", for:indexPath) as? MyCustomCell
cell.configure(item:self.items[indexPath.row])
return cell
}
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 2 years ago.
Improve this question
i have a UITableViewController configured with a static table made up of 5 custom cells (this is meant to be a form).
cell 0 captures a date
cell 1 is a UICollectionView filled with icons representing activities. depending on which activity is selected, one of many custom UITableViewCell are loaded on the fly in cell 2 .
cell 2 can be simple (just a slider), a textfield or more complex (a UITableView)
cell 3 has a textfield to capture a description.
cell 4 is for additional notes
so far everything is working as expected. I select an activity in cell 1, the matching XIB is loaded in cell 2, data is captured, comment added etc and form is saved. Where i am challenged is in the case where based on the the input in cell 2, i would like to update cell 3 automatically. i got it working but i feel it isn't elegant or clean so would appreciate others input. in
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// main table cells pseudo code
switch indexPath.row {
case 0:
<#code#>
case 1:
// dequeue collectionviewcell
case 2:
// dequeue the relevant uitableviewcell based on selected cell in the uicollectionview
switch selectedIndexPath.row {
case 2:
<#code#>
default:
<#code#>
}
case 3:
// handle the description field
default:
<#code#>
}
a specific activity will load "eventFlushMedTableViewCell" which is meant to display a list of meds in a uitableview. based on which meds I select, i would like to take the name of the meds and put them in cell 3.
case 2:
let cell = tableView.dequeueReusableCell(withIdentifier: "eventFlushMedTableViewCell", for: indexPath) as! eventFlushMedTableViewCell
// fill the meds table with the list of Rx meds
cell.medsArray = medListArray.filter { $0.medRx == 1}.map {return $0.medName}
// return the selected values from the table
cell.returnValue = { selectedIndexPaths in
let indexList = selectedIndexPaths.map { $0.row }
self.selectedMedsName = indexList.map {cell.medsArray[$0]}
// force a reload of cell 3
let myIndexPath = IndexPath.init(row: 3, section: 0)
tableView.reloadRows(at: [myIndexPath], with: .none)
}
return cell
and cell 3 in the main table is dequeued and configured
case 3:
let cell = tableView.dequeueReusableCell(withIdentifier: "eventDescriptionCell", for: indexPath) as! eventDescriptionCell
if !selectedMedsName.isEmpty {
cell.eventDescriptionTextField.text = selectedMedsName.joined(separator: ", ")
}
something tells me the closure around (cell.returnValue {...}) in case 2:, even though it is working, isn't the right way of doing this... any advice ?
thanks
I think a good way of approaching this would be to create a custom delegate.
Let's name it ActivityCellDelegate. You can create it like this:
protocol ActivityCellDelegate: class {
func activitySelected(_ activity: Activity)
}
We use 'class' so we can make the delegate 'weak' reference. Otherwise XCode will cause trouble :).
Using an enum to represent different activities is a nice touch. You could also use a String as an identifier or an Int as an id.
enum Activity {
case activity1
case activity2
...
}
Add a delegate property to the TableViewCell:
weak var cellDelegate: ActivityCellDelegate?
Then, when dequeuing a cell, you set it's delegate to self cell.cellDelegate = self, and make the controller that has tableView as a subview conform to the delegate protocol.
extension TableViewController: ActivityCellDelegate {
func activitySelected(_ activity: Activity) {
//...in here you would probably reload the third cell in the table view. You could add an additional property in the ViewController in order to know which activity is currently selected.
}
}
In the end, when user selects a CollectionViewCell to choose an activity in collectionView:didSelectItemAtIndexPath: you should call the delegate method:
delegate?.activitySelected(.activity1)
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
I have a UICollectionView which displays content received from the web. The number of cells can be known only at runtime. Client's requirement is that each row in the collection view must have a different color.
For example, If I have to show 12 items in my UICollectionView then suppose if first row has 3 cells then the colour of all three cells should be red.
Cells of second row should be white and so on.
Could you please help me how to achieve it?
Thanks in advance.
on cellForRowAt, if you want to intercalate colors, you can check indexPath.row and update the background color.
if indexPath.item % 2 == 0 {
<#YourCell#>.backgroundColor = .blue
} else {
<#YourCell#>.backgroundColor = .green
}
Also, if you want random colors, you can check this answer: How to make a random color with Swift
Then you just set <#YourCell#>.backgroundColor the random color
In the case that the collectionViewCell has another collectionView on each cell, and those have to match the same color for each parent collectionView row, I'd suggest you to create a custom class for the parent collectionView cell, so that every collectionView child row can consume from it and set it's own backgroundColor.
Updated answer:
I'm supposing you have initially you have these variables like:
private let cellBackgroundColors: [UIColor] = [.yellow, .green, .blue, .purple]
private let numberOfRows = 3 (or you can assign it dynamically)
Second step, implement like this:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellIdentifier, for: indexPath) as! ToDoListCollectionCell
let index = indexPath.item / numberOfRows
if index < cellBackgroundColors.count {
cell.backgroundColor = cellBackgroundColors[index]
} else {
cell.backgroundColor = .white // Set your default color to handle this case
}
return cell
}
Happy Coding !!
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
I got these item properties and I need to populate the UI by setting the name on each UITableViewCell, each cell has the following properties:
Name
Description
Photo
Old Price
New Price
However, I don't know how I should proceed. Could you guys take a look and give me a hand, please?
Printed Item names:
HTML e CSS
Sistema de Banco de Dados
Programação com Arduino
Segredos do Hacker Ético
Google Android
Android Essencial
Desenvolvimento de Jogos Para Android
iOS: Programe para iPhone e iPad
A Guerra dos tronos
Crepusculo
ViewController:
import UIKit
class TelaCategorias: UIViewController, UITableViewDataSource, UITableViewDelegate {
//Class Instanciated
var item:[CategoriaIDItems]?
override func viewDidLoad() {
super.viewDidLoad()
for item in item!{
print(item.nome)
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return (item?.count)!
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "tableIDCategorias", for: indexPath) as! TelaCategoriasCell
cell.textLabel?.text = ?????
return cell
}
}
Append the item names to an array
In cellForRowAt indexPath:
cell.textLabel.text = yourArrayName[indexPath.row]
So you need to read up on setting up a data source for a table view.
Before you tackle YOUR table view, you might want to go through a Swift/iOS tutorial on table views and follow that so you get the gist of it.
Suggestion: Don't use the name "item" (singular) for your array. Use the name "items" plural. An item is a thing. Items is more than one thing.
Now define a struct that has fields for the properties that you want to display in your table view.
Make items be an array of those structs.
Write your tableView(_:cellForRowAt:) method so it fetches an item from the items array and uses that item to set the fields in your table view cell.
If you don't understand any of these steps you will need to do some study and read up on how to do this. Expect it to take a couple of days to sort this out. It's confusing the first time you tackle it, but you need to go through the exercise.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 years ago.
Improve this question
I would like some opinions on a idea I just had :
I have a bunch of UITableViewCell subclass. In my particular case it's just to add a UISwitch and have a property to access it.
Setting the switch's value is straight forward. Updating the Bool associated to this switch not so much.
I thought of adding a closure as a property of my cell so that I can just call it to update my bool in my UITableViewController subclass
Here is some the code I thought of :
class SwitchTableViewCell:UITableViewCell {
#IBOutlet var theSwitch:UISwitch!
var switchValueChangedBlock:((Bool) -> Void)?
override func awakeFromNib() {
theSwitch.addTarget(self, action: "switchValueChanged", forControlEvents: .ValueChanged)
}
deinit {
theSwitch.removeTarget(self, action: nil, forControlEvents: .AllEvents)
}
func setCallback(callback:(Bool) -> Void) {
switchValueChangedBlock = callback
}
func switchValueChanged() {
switchValueChangedBlock?(theSwitch.on)
}
}
class myTableViewController:UITableViewController {
var alarmEnabled:Bool = true
...
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell:UITableViewCell?
if indexPath.section == enableSection {
cell = tableView.dequeueReusableCellWithIdentifier(enableAlarmCellIdentifier,forIndexPath: indexPath)
let myCell = cell as! SwitchTableViewCell
myCell.theSwitch.on = alarmEnabled
myCell.setCallback({[unowned self] (boolValue:Bool) in
self.alarmEnabled = boolValue
})
}
}
...
}
As advantages I see following :
No need of delegate
No method called where I need to determine which value I need to update (I have multiple instances of my cell for different variables)
I can't grasp the possible drawbacks my idea could have and if in overall it's a bad or a good idea.
Personally I am kinda old school and simply prefer the delegation pattern over closures.
But for your question ... what you suggest is exactly what closures are made for. Just go for it.
You simply hand over to another class' object some piece of code (or the reference to some subroutine's entry point respectively) that you want to be executed when some event occours. That's what it's made for and that's what you are doing.