Update UILabel inside UITableViewCell without full page refresh using Swift - ios

I have a particular conundrum where I need a specific UILabel inside a UITableViewCell to update every minute. Currently, every minute, the whole entire cell refreshes and displays beneath the previous one, see below, all I want to do is refresh that UILabel called watchTime:
Here's my tableView where I initialize the watch time minute count from the model
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "watchTimeCell", for: indexPath) as! WatchTimeCell
if userModel.count > indexPath.row {
//this is the value i want to update
cell.watchTime.text = "\(String(describing: userModel[indexPath.row].watchTime!))"
}
return cell
}
And here's how I update my cell currently:
#objc func updateCounting(){
watchTime += 1
if watchTime % 60 == 0 {
let userRef = Database.database().reference().child("users").child(uid!).child("watchTime")
userRef.runTransactionBlock({ (currentData: MutableData) -> TransactionResult in
let newValue: Int
if let existingValue = (currentData.value as? NSNumber)?.intValue {
newValue = existingValue + 1
} else {
newValue = 1
}
currentData.value = NSNumber(value: newValue)
//this is the line where I reload the cell
DispatchQueue.main.async(execute: {
self.watchTableView.reloadData()
})
return TransactionResult.success(withValue: currentData)
})
watchTime = 0
}
}
What's the best way to go about this? Thanks!
EDIT: Added numberOfRowsInSection
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return userModel.count
}

What you're doing is essentially correct for a table view. You update the model and call reload to propagate that thru cellForRowAt to the table view. You could, in this situation, save some overhead by calling reloadRows(at:with:) so as to reload only the one cell.
Except...
You have only one cell. But a one-cell table view is ridiculous. What's its purpose? To make the interface scrollable? Then just make a scroll view. Now you can update the label directly.

I would create that one cell, with a reference to it in the ViewController that is holding the tableView.
let mainCell = WatchTimeCell()
Inside the WatchTimeCell class I would add a public func to update the time count
public func updateTimeCountLabel(_ count: Int) {
self.nameOfLabel.text = "\(count)"
}
Then within the updateCounting() I would call the updateTimeCountLabel inside the WatchTimeCell.
self.mainCell.updateTimeCountLabel(newValue)
But there is something happening within the numberOfRowsForSection, could you post that?

Related

After tableView scrolled data puts in cells in wrong order

in my View:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TransactionTableCell", for: indexPath) as! TransactionTableCell
let newItem = getTransactionsInSection(section: sectionHeader[indexPath.section])[indexPath.row]
cell.configure(item: newItem)
}
in my TransactionTableCell
func configure(item: TransactionModel) {
guard let withdrawalBonuses = item.withdrawalBonuses,
withdrawalBonuses < 0,
let accruedBonuses = item.accruedBonuses,
accruedBonuses > 0 else {
configureWithOneOperation(item)//shows one line of operation
return
}
//show 2 lines of operations
firstOperationAmountLabel.text = "+\(Int(accruedBonuses))"
secondOperationAmountLabel.text = "\(Int(withdrawalBonuses))"
}
When I scroll the cell , second operation line is appears in wrong cells where its shouldn't be, even If I reload my table , that also has this problem.
You should use prepareForReuse() method
Simply just clear data of your labels:
override func prepareForReuse() {
super.prepareForReuse()
firstOperationAmountLabel.text = nil
secondOperationAmountLabel.text = nil
}
There are few things to check here.
Make sure you reset all fields before configure a new cell.
If you have created a cell using xib or storyboard, make sure you haven't filled labels with static text.
Is your guard statements passing for every item?
Else block for guard configures cell with a single operation, Is it handling all ui elements in cell?

UITableViewCell dequeuereusablecellwithidentifier returns the same cell

I am creating a UITableView that enables the user to add a variable amount of data. Table looks like this initially:
When the user clicks on the "+" button, i would like to add a new cell with a UITextField for entering data. This new cell is a Custom UITableViewCell called "RecordValueCell". Here's what is looks like:
//Custom UITableViewCell
class RecordValueCell : UITableViewCell {
#IBOutlet weak var textField: UITextField!
#IBOutlet weak var deleteButton: UIButton!
var onButtonTapped : ((_ sender : UIButton)->Void)?
#IBAction func deleteButtonTouched(_ sender: Any) {
guard let senderButton = sender as? UIButton else {
return
}
onButtonTapped?(senderButton)
}
}
However when i try to add another cell, using the tableView.dequeueReusableCell(withIdentifier: ) function, it seems to return the same cell. And here is what my UI looks like:
Empty space at the top of the section where my new cell should be. Here is the code to add the cell:
func addNewValueCell() {
guard let reusableValueCell = self.tableView.dequeueReusableCell(withIdentifier: "valueCell") as? RecordValueCell else {
fatalError("failed to get reusable cell valueCell")
}
var cell = Cell() //some custom cell Object
//add the gray horizontal line you see in the pictures
reusableValueCell.textField.addBorder(toSide: .Bottom, withColor: UIColor.gray.cgColor, andThickness: 0.5)
reusableValueCell.onButtonTapped = { (sender) in
self.removeValue(sender: sender)
}
cell.cell = reusableValueCell
self.sections[self.sections.count - 1].cells.insert(cell, at: 0)
//When i put a break point at this spot, i find that reusableValueCell is the same object as the cell that is already being used.
tableView.reloadData()
reusableValueCell.prepareForReuse()
}
When i debug it, i find that dequeueReusableCell(withIdentifier: ) returns the exact same RecordValueCell multiple times.
Here is my cellForRowAt:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = self.sections[indexPath.section].cells[indexPath.row].cell else {
fatalError("error getting cell")
}
return cell
}
numberOfRowsInSection
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.sections[section].cells.count
}
First of all, you will need to set the View Controller Class that this table is contained in as the table's UITableViewDataSource
tableView.dataSource = self // view controller that contains the tableView
Create an array of strings as member of your View Controller class which contains the data for each cell:
var strings = [String]()
Then you will need to implement the following method for the UITableViewDataSource protocol:
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return strings.count
}
You should also be dequeueing the cells in your cellForRowAt method like so:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: yourIdentifier) as! YourCellClass
cell.textLabel = strings[indexPath.row]
return cell
}
Then whenever the user enters into the textField, their input will be appended to this array:
let input = textField.text
strings.append(input)
tableView.reloadData()
Once the data is reloaded, the cell will be added to the table automatically since the number of rows are defined by the String array's length and the label is set in the cellForRowAt method.
This feature is very easy to implement if you will do in a good way.
First, you have to create two TableCell. First to give the option to add a record with plus button and second for entering a value with textfield. Now always return first cell (AddRecordTableCell) in the last row in tableView, and return the number of rows according to entered values like
return totalValues.count + 1

CollectionView in TableView displays false Data swift

I'm trying to combine a CollectionViewwith a TableView, so fare everything works except one problem, which I cant fix myself.
I have to load some data in the CollectionViews which are sorted with the header of the TableViewCell where the CollectionView is inside. For some reason, every time I start the app, the first three TableViewCells are identical. If I scroll a little bit vertically, they change to the right Data.
But it can also happen that while using it sometimes displays the same Data as in on TableViewCell another TableViewCell, here again the problem is solved if I scroll a little.
I think the problem are the reusableCells but I cant find the mistake myself. I tried to insert a colletionView.reloadData() and to set the cells to nil before reusing, sadly this didn`t work.
My TableViewController
import UIKit
import RealmSwift
import Alamofire
import SwiftyJSON
let myGroupLive = DispatchGroup()
let myGroupCommunity = DispatchGroup()
var channelTitle=""
class HomeVTwoTableViewController: UITableViewController {
var headers = ["LIVE","Channel1", "Channel2", "Channel3", "Channel4", "Channel5", "Channel6"]
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(_ animated: Bool) {
self.navigationController?.navigationBar.isTranslucent = false
DataController().fetchDataLive(mode: "get")
DataController().fetchDataCommunity(mode: "get")
}
//MARK: Custom Tableview Headers
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return headers[section]
}
//MARK: DataSource Methods
override func numberOfSections(in tableView: UITableView) -> Int {
return headers.count
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
//Choosing the responsible PrototypCell for the Sections
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellBig", for: indexPath) as! HomeVTwoTableViewCell
print("TableViewreloadMain")
cell.collectionView.reloadData()
return cell
}
else if indexPath.section >= 1 {
// getting header Titel for reuse in cell
channelTitle = self.tableView(tableView, titleForHeaderInSection: indexPath.section)!
let cell = tableView.dequeueReusableCell(withIdentifier: "cellSmall", for: indexPath) as! HomeVTwoTableViewCellSmall
// anti Duplicate protection
cell.collectionView.reloadData()
return cell
}
else {
channelTitle = self.tableView(tableView, titleForHeaderInSection: indexPath.section)!
let cell = tableView.dequeueReusableCell(withIdentifier: "cellSmall", for: indexPath) as! HomeVTwoTableViewCellSmall
// anti Duplicate protection
cell.collectionView.reloadData()
return cell
}
}
}
}
My TableViewCell with `CollectionView
import UIKit
import RealmSwift
var communities: Results<Community>?
class HomeVTwoTableViewCellSmall: UITableViewCell{
//serves as a translator from ChannelName to the ChannelId
var channelOverview: [String:String] = ["Channel1": "399", "Channel2": "401", "Channel3": "360", "Channel4": "322", "Channel5": "385", "Channel6": "4"]
//Initiaize the CellChannel Container
var cellChannel: Results<Community>!
//Initialize the translated ChannelId
var channelId: String = ""
#IBOutlet weak var collectionView: UICollectionView!
}
extension HomeVTwoTableViewCellSmall: UICollectionViewDataSource,UICollectionViewDelegate {
//MARK: Datasource Methods
func numberOfSections(in collectionView: UICollectionView) -> Int
{
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
return (cellChannel.count)
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
{
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionCellSmall", for: indexPath) as? HomeVTwoCollectionViewCellSmall else
{
fatalError("Cell has wrong type")
}
//removes the old image and Titel
cell.imageView.image = nil
cell.titleLbl.text = nil
//inserting the channel specific data
let url : String = (cellChannel[indexPath.row].pictureId)
let name :String = (cellChannel[indexPath.row].communityName)
cell.titleLbl.text = name
cell.imageView.downloadedFrom(link :"link")
return cell
}
//MARK: Delegate Methods
override func layoutSubviews() {
myGroupCommunity.notify(queue: DispatchQueue.main, execute: {
let realm = try! Realm()
//Getting the ChannelId from Dictionary
self.channelId = self.channelOverview[channelTitle]!
//load data from Realm into variables
self.cellChannel = realm.objects(Community.self).filter("channelId = \(String(describing: self.channelId)) ")
self.collectionView.dataSource = self
self.collectionView.delegate = self
print("collectionView layout Subviews")
self.collectionView.reloadData()
})
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
selectedCommunity = (cellChannel[indexPath.row].communityId)
let home = HomeViewController()
home.showCommunityDetail()
}
}
Thanks in advance.
tl;dr make channelTitle a variable on your cell and not a global variable. Also, clear it, and your other cell variables, on prepareForReuse
I may be mistaken here, but are you setting the channelTitle on the cells once you create them? As I see it, in your viewController you create cells based on your headers, and for each cell you set TableViewController's channelTitle to be the title at the given section.
If this is the case, then the TableViewCell actually isn't receiving any information about what it should be loading before you call reloadData().
In general, I would also recommend implementing prepareForReuse in your HomeVTwoTableViewCellSmall, since it will give you a chance to clean up any stale data. Likely you would want to do something like set cellChannel and channelId to empty strings or nil in that method, so when the cell is reused that old data is sticking around.
ALSO, I just reread the cell code you have, and it looks like you're doing some critical initial cell setup in layoutSubviews. That method is going to be potentially called a lot, but you really only need it to be called once (for the majority of what it does). Try this out:
override the init with reuse identifier on the cell
in that init, add self.collectionView.dataSource = self and self.collectionView.delegate = self
add a didSet on channelTitle
set channelTitle in the viewController
So the code would look like:
var channelTitle: String = "" {
didSet {
self.channelId = self.channelOverview[channelTitle]!
self.cellChannel = realm.objects(Community.self).filter("channelId = \(String(describing: self.channelId)) ")
self.collectionView.reloadData()
}
}
This way you're only reloading your data when the cell is updated with a new channel, rather than every layout of the cell's views.
Sorry... one more addition. I wasn't aware of how your channelTitle was actually being passed. As I see it, you're using channelTitle as a global variable rather than a local one. Don't do that! remove channelTitle from where it is currently before implementing the code above. You'll see some errors, because you're setting it in the ViewController and accessing it in the cell. What you want is to set the channelTitle on the cell from the ViewController (as I outlined above). That also explains why you were seeing the same data across all three cells. Basically you had set only ONE channelTitle and all three cells were looking to that global value to fetch their data.
Hope that helps a little!
(also, you should be able to remove your else if block in the cellForRowAtIndexPath method, since the else block that follows it covers the same code. You can also delete your viewDidLoad, since it isn't doing anything, and you should, as a rule, see if you can get rid of any !'s because they're unsafe. Use ? or guard or if let instead)

Filter tableView rows doesn't reload tableView

My first iOS app works with simple custom cells, but enhancement to filter tableView rows is causing delays and frustration. Searched online for help on filter rows, read dataSource and delegate protocols in Apple Developer guides, no luck so far.
Using slider value to refresh table rows. Extracted data from line array (100 items) to linefilter array (20). Then want to refresh/reload the tableview.
Slider is declared with 0 and all line array items show up. moving the slider does not alter display. If slider is declared with say 1, then 20 filter items show.
Quite new to Apple/Xcode/Swift so have no Objective C knowledge.
Any answers will probably help me get there.
Jim L
Relevant selection of code :
#IBAction func moveSlider(sender: AnyObject) {
// Non-continuous ******
_ = false
// integer 0 to 5 ******
let slider = Int(lineSlider.value)
}
}
// Global Variable ******
var slider = 0
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
if slider == 0 {
return self.line.count
} else {
return self.linefilter.count
}
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell = self.tableView.dequeueReusableCellWithIdentifier("cell") as! myTableViewCell
if slider == 0 {
cell.myCellLabel.text = line[indexPath.row]
} else {
cell.myCellLabel.text = linefilter[indexPath.row]
}
cell.myImageView.image = UIImage(named: img[indexPath.row])
return cell
}
tableView.reloadata()
try to put
tableView.reloadData()
like this
let slider = Int(lineSlider.value)
tableView.reloadData()
}
in your moveSlider function

How to make table view load all data at once and not change said data while scrolling?

I'm making a simple table view app to display and play all the iOS System sounds.
I have all of the sounds and ID's in a a dictionary(I now realize this was a bad way to do this) in the form of [ID(Int):Name(String)], the problem is that when I load my view it loads well, but if I scroll down the cells originally on top change. Same when scrolling from the bottom to the top.
For example, the view loads in and I can click and hear the various sounds from any of the cells I click on. Lets say the first cell is "SMS-Sound1" and the seconds is "SMS-Sound2". Now when I scroll down to where those cells are out of view and then scroll back to the the top they are named something different(Still from my data dictionary).
How would I fix this problem so that it loads the tableview and then the tableview data doesn't change?
Edit: I thought the problem could be in the fact that the for in loop was executed around 300,000 times but thats not the case, made an array of the IDS so it was only executed around 1000 times total and the problem persists
My Code:
Cell set up
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("soundCell", forIndexPath: indexPath)
let button = cell.viewWithTag(3) as! UILabel //UILabel in "SoundCell"
for i: Int in 999..<4100 {
//Lowest id sound is 1000, highest is 4095
if (sounds[i] != nil) && loadedSoundStrings.contains(sounds[i]!) == false {
button.text = sounds[i]
loadedSoundStrings.append(sounds[i]!)
cell.tag = i
break
}
}
return cell
}
Rows/sections
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return sounds.count
}
Variables:
let sounds =
[ 1000:"new-mail.caf",
1001:"mail-sent.caf",
1002:"Voicemail.caf",
1003:"ReceivedMessage.caf",
1004:"SentMessag.caf",
1005:"alarm.caf",
1006:"low-power.caf",
1007:"sms-received1.caf",
1008:"sms-received2.caf",
1009:"sms-received3.caf",
1010:"sms-received4.caf",
1011:"-(SMSReceived_Vibrate)",
1012:"sms-received1.caf",
1013:"sms-received5.caf",
1014:"sms-received6.caf",
1015:"Voicemail.caf",
1016:"tweet_sent.caf",
1020:"Anticipate.caf",
1021:"Bloom.caf",
1022:"Calypso.caf",
1023:"Choo_Choo.caf",
1024:"Descent.caf",
1025:"Fanfare.caf",
1026:"Ladder.caf",
1027:"Minuet.caf",
1028:"News_Flash.caf",
1029:"Noir.caf",
1030:"Sherwood_Forest.caf",
1031:"Spell.caf",
1032:"Suspense.caf",
1033:"Telegraph.caf",
1034:"Tiptoes.caf",
1035:"Typewriters.caf",
1036:"Update.caf",
1050:"ussd.caf",
1051:"SIMToolkitCallDropped.caf",
1052:"SIMToolkitGeneralBeep.caf",
1053:"SIMToolkitNegativeACK.caf",
1054:"SIMToolkitPositiveACK.caf",
1055:"SIMToolkitSMS.caf",
1057:"Tink.caf",
1070:"ct-busy.caf",
1071:"ct-congestion.caf",
1072:"ct-path-ack.caf",
1073:"ct-error.caf",
1074:"ct-call-waiting.caf",
1075:"ct-keytone2.caf",
1100:"lock.caf",
1101:"unlock.caf",
1102:"-(FailedUnlock)",
1103:"Tink.caf",
1104:"Tock.caf",
1105:"Tock.caf",
1106:"beep-beep.caf",
1107:"RingerChanged.caf",
1108:"photoShutter.caf",
1109:"shake.caf",
1110:"jbl_begin.caf",
1111:"jbl_confirm.caf",
1112:"jbl_cancel.caf",
1113:"begin_record.caf",
1114:"end_record.caf",
1115:"jbl_ambiguous.caf",
1116:"jbl_no_match.caf",
1117:"begin_video_record.caf",
1118:"end_video_record.caf",
1150:"vc~invitation-accepted.caf",
1151:"vc~ringing.caf",
1152:"vc~ended.caf",
1153:"ct-call-waiting.caf",
1154:"vc~ringing.caf",
1200:"dtmf-0.caf",
1201:"dtmf-1.caf",
1202:"dtmf-2.caf",
1203:"dtmf-3.caf",
1204:"dtmf-4.caf",
1205:"dtmf-5.caf",
1206:"dtmf-6.caf",
1207:"dtmf-7.caf",
1208:"dtmf-8.caf",
1209:"dtmf-9.caf",
1210:"dtmf-star.caf",
1211:"dtmf-pound.caf",
1254:"long_low_short_high.caf",
1255:"short_double_high.caf",
1256:"short_low_high.caf",
1257:"short_double_low.caf",
1258:"short_double_low.caf",
1259:"middle_9_short_double_low.caf",
1300:"Voicemail.caf",
1301:"ReceivedMessage.caf",
1302:"new-mail.caf",
1303:"mail-sent.caf",
1304:"alarm.caf",
1305:"lock.caf",
1306:"Tock.caf",
1307:"sms-received1.caf",
1308:"sms-received2.caf",
1309:"sms-received3.caf",
1310:"sms-received4.caf",
1311:"-(SMSReceived_Vibrate)",
1312:"sms-received1.caf",
1313:"sms-received5.caf",
1314:"sms-received6.caf",
1315:"Voicemail.caf",
1320:"Anticipate.caf",
1321:"Bloom.caf",
1322:"Calypso.caf",
1323:"Choo_Choo.caf",
1324:"Descent.caf",
1325:"Fanfare.caf",
1326:"Ladder.caf",
1327:"Minuet.caf",
1328:"News_Flash.caf",
1329:"Noir.caf",
1330:"Sherwood_Forest.caf",
1331:"Spell.caf",
1332:"Suspense.caf",
1333:"Telegraph.caf",
1334:"Tiptoes.caf",
1335:"Typewriters.caf",
1336:"Update.caf",
1350:"-(RingerVibeChanged)",
1351:"-(SilentVibeChanged)",
4095:"-(Vibrate)"]
var loadedSoundStrings = [String]()
You are instantiating all of the sounds for every single row when you actually want to only instantiate the sound for the rows that are loaded. To fix your order issue change your
cellForRowAtIdexPath
to this:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("soundCell", forIndexPath: indexPath)
let button = cell.viewWithTag(3) as! UILabel //UILabel in "SoundCell"
button.text = sounds[i]
cell.tag = indexPath.row
return cell
}
This gives you 1 sound per cell since you have NumberOfRowsInSection set to sounds.count Cell for row will be called for every sound you have.
If I understand your code correctly, you're going about it the wrong way. You have a dictionary of sounds that you load once. The cellForRowAtIndexPath function should be returning one tableViewCell with details for the one sound.
UITableView automatically discards cells that are off screen to conserve memory, and will reuse them for newly visible cells. That's why you call dequeueReusableCellWithIdentifier. Therefore you should just be doing:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("soundCell", forIndexPath: indexPath)
let button = cell.viewWithTag(3) as! UILabel //UILabel in "SoundCell"
//Lowest id sound is 1000, highest is 4095
let i = indexPath.row + 1000
button.text = sounds[i]
cell.tag = i
return cell
}
Since you are hardcoding the sound number range I have done the same.
A table view works best with an array, as an array has a defined order and you can quickly access a given element; a for loop in cellForRowAtIndexPath is seldom a good thing.
You have a couple of issues, however, as your sounds identifiers don't start from 0, you can't use the identifier as a direct index into the array, but also the identifiers aren't sequential, so you can't even use a simple offset (adding a constant value to the row number).
I think that the best solution is not to rely directly on intrinsic types as you are for your dictionary, but rather, create a struct for each sound and store an array of them. Something like this:
class MyViewController: UIViewController, UITableViewDelegate, UITableViewDatasource
struct Sound {
var id:Int
var fileName:String
}
var sounds=[Sound]()
func loadSounds() {
let soundsDict =
[1000:"new-mail.caf",
1001:"mail-sent.caf",
1002:"Voicemail.caf",
1003:"ReceivedMessage.caf",
1004:"SentMessag.caf",
1005:"alarm.caf",
1006:"low-power.caf",
1007:"sms-received1.caf",
1008:"sms-received2.caf",
...
]
for (id,fileName) in soundsDict {
self.sounds.append(Sound(id: id, fileName: fileName))
}
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("soundCell", forIndexPath: indexPath)
let button = cell.viewWithTag(3) as! UILabel //UILabel in "SoundCell"
button.text=self.sounds[indexPath.row].fileName
return cell
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.sounds.count
}
}

Resources