Table View Cell Content Repeating While I reload data - ios

My table view cell is repeating when scroll while waiting to reload Data . After reload all item are reset and all repeating content are remove . Here a video showing the problem , anyone know why and how can i fixed it ? As you can see in the video the hdsdjhjdhhsdsjshhsdhsjhdjd is repeating again on the top?
https://www.dropbox.com/s/e0arcajkuuot8xa/Reflector%20Recording.mp4?dl=0
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell:StatusTableCell! = tableView.dequeueReusableCellWithIdentifier("statusCell", forIndexPath: indexPath) as! StatusTableCell
if (cell == nil) {
cell.uploadDate = nil
cell.uploadStatus.text = nil
cell.statusUploader.setTitle("", forState: .Normal)
}
cell.photoImage.hidden = true
self.photoHidden = true
print("\n\n\n\n")
cell.layoutIfNeeded()
cell.likesButton.setImage(UIImage(named: "Likes"), forState: .Normal)
cell.likesButton.setTitle("0", forState: UIControlState.Normal)
print("\n\n\n\n")
//Makes The Cell Of Text View Detect Link
cell.uploadStatus.dataDetectorTypes = .Link
cell.uploadStatus.delegate = self
do {
print(date2)
cell.statusUploader.setTitle("\(user2[indexPath.row])", forState: UIControlState.Normal)
if isLoadingLikes == false {
//Modified Height Based ON Status NOTE: STILL BUGGY
cell.uploadStatus.text = status2[indexPath.row]
cell.uploadStatus.frame.size.height = textViewHeight(cell.uploadStatus)
test = cell.uploadStatus.frame.size.height
self.tableView(tableView, heightForRowAtIndexPath: indexPath)
//Likes Button Data
let uploadLikes = likes2[indexPath.row]
cell.likesButton.tag = indexPath.row
cell.likesButton.setTitle("\(uploadLikes)", forState: UIControlState.Normal)
//Add An Action Connector To Likes Button
cell.likesButton.addTarget(self, action: Selector("likesFunction:"), forControlEvents: .TouchUpInside)
cell.moreButton.addTarget(self, action: Selector("moreFunction:"), forControlEvents: .TouchUpInside)
print(liked2)
if liked2[indexPath.row] == "liked" {
cell.likesButton.setImage(UIImage(named: "Likes2"), forState: .Normal)
}else {
cell.likesButton.setImage(UIImage(named: "Likes"), forState: .Normal)
}
}
print("----------------------------- Row \(indexPath.row)")
print("Checking Date Array\(date2[indexPath.row])")
print("Check NSDATE \(NSDate().timeIntervalSinceDate(date2[indexPath.row]))")
print("Checking TIME FORMATTER \(timeAgoSinceDate(date2[indexPath.row], numericDates: true))")
print("Status = \(status2[indexPath.row])")
cell.uploadDate.text = timeAgoSinceDate(date2[indexPath.row], numericDates: true)
let stringWithNSDataDetector: String = cell.uploadStatus.text
let error: NSError? = nil
let dataDetector: NSDataDetector = try NSDataDetector(types: NSTextCheckingType.Link.rawValue)
//Check if (error) before
var allMatches: [AnyObject] = [AnyObject]()
dataDetector.enumerateMatchesInString(stringWithNSDataDetector, options: NSMatchingOptions.Anchored, range: NSMakeRange(0, stringWithNSDataDetector.characters.count), usingBlock: { (match:NSTextCheckingResult?, flags:NSMatchingFlags, pointer:UnsafeMutablePointer<ObjCBool>) -> Void in
print("Link \(match!.resultType == .Link)")
if match!.resultType == .Link {
allMatches.append(match!.URL!)
self.photoHidden = false
cell.photoImage.hidden = false
print(match!.URL!)
}
})
print("ALL Matches \(allMatches)")
print("Test \(test) -- row : \(indexPath.row)")
print(cell.uploadStatus.frame.size.height)
}
catch {
print("Error Loading Status -- (StatusTableView)")
}
print("----------------------------- End \n")
cell.setNeedsDisplay()
return cell
}
And here is another
func textViewHeight (textView:UITextView) -> CGFloat{
textView.scrollEnabled = false
let fixedWidth = textView.frame.size.width
textView.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.max))
let newSize = textView.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.max))
var newFrame = textView.frame
newFrame.size = CGSize(width: max(newSize.width, fixedWidth), height: newSize.height)
textView.frame = newFrame;
return textView.frame.height
}
internal func textViewHeightForText(text: String?, andWidth width: CGFloat) -> CGFloat {
let calculationView = UITextView()
//IMPORTANT - have to specify the name/size of your font
let attributedText = NSAttributedString(string: (text != nil) ? text! : "", attributes: [NSFontAttributeName : UIFont(name: "Helvetica Neue", size: 16.0)!])
calculationView.attributedText = attributedText
let height = calculationView.sizeThatFits(CGSize(width: width, height: CGFloat.max)).height
return height
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
let width = tableView.frame.size.width - 79
if photoHidden == false {
return textViewHeightForText(status2[indexPath.row], andWidth: width) + 260
}else {
return textViewHeightForText(status2[indexPath.row], andWidth: width) + 140
}
}
override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
let cell = tableView.dequeueReusableCellWithIdentifier("statusCell", forIndexPath: indexPath) as! StatusTableCell
cell.uploadStatus.text = status2[indexPath.row]
cell.uploadStatus.frame.size.height = textViewHeight(cell.uploadStatus)
test = cell.uploadStatus.frame.size.height
self.tableView(tableView, heightForRowAtIndexPath: indexPath)
//If it is last row of the loaded table views , it will loading it got more than one current object else finish loading
if (indexPath.row == objectCount - 1) && isLoadingMoreCell == false
{
self.isLoadingMoreCell = true
self.tableView.tableFooterView = footerView
footerLoading.center.x = self.footerView.frame.width/2
footerLoading.startAnimating()
loadMoreCell()
}
}

Related

Can't remove view from superview on reusable tableview cell

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: EventCommentsCustom = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! EventCommentsCustom
guard let release = array[exist: indexPath.section] else { return cell }
if release.user == "condition" {
let image = UIImage()
let imageView = UIImageView(image: image)
imageView.sd_setImage(with: URL(string: "https://example.com/" + TegKeychain.get("profile_pic")!))
imageView.frame = CGRect(x: 20, y: 10, width: 50, height:50)
imageView.layer.borderWidth = 0.4
imageView.layer.masksToBounds = false
imageView.layer.borderColor = UIColor.gray.cgColor
imageView.layer.cornerRadius = 25
imageView.clipsToBounds = true
imageView.tag = 3
cell.addSubview(imageView)
let button = UIButton(frame: CGRect(x: 90, y: 10, width: 200, height: 50))
button.contentHorizontalAlignment = .left
button.setTitleColor(UIColor.lightGray, for: .normal)
button.setTitle(NSLocalizedString("Say something...", comment: ""), for: .normal)
button.addTarget(self, action: #selector(EventComments.openInput), for: .touchUpInside)
button.tag = 3
cell.addSubview(button)
} else {
if let viewWithTag = cell.viewWithTag(3) {
if viewWithTag is UIImageView {
print("DONE")
viewWithTag.removeFromSuperview()
}
}
if let viewWithTag = cell.viewWithTag(3) {
if viewWithTag is UIButton {
print("DONE")
viewWithTag.removeFromSuperview()
}
}
}
return cell
}
I am trying to remove views that I created with a tag in a reusable tableview cell.
However, I still can see UIButton and UIImageview when first reused (5. section of tableview), then It starts to remove properly
Why don't they get removed at the first reuse?
I guess that reusing in your case could mean that the image view and button get added twice for a cell. You only remove one of them though. I think you should take a different approach (like different prototype cells as #vadian stated) into consideration but for now (assuming my assumption is correct) you could try this to fix your problem:
Replace ...
if let viewWithTag = cell.viewWithTag(3) {
if viewWithTag is UIImageView {
print("DONE")
viewWithTag.removeFromSuperview()
}
}
if let viewWithTag = cell.viewWithTag(3) {
if viewWithTag is UIButton {
print("DONE")
viewWithTag.removeFromSuperview()
}
}
With ...
while let viewToRemove = cell.viewWithTag(3) {
if viewToRemove is UIImageView || viewToRemove is UIButton {
viewToRemove.removeFromSuperview()
}
}
Update -
The approach with different cell types would look something like this:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let release = array[exist: indexPath.section] else { return cell }
if release.user == "condition" {
let cell = tableView.dequeueReusableCell(withIdentifier: "OneIdentifier", for: indexPath) as! OneCustomCellType
// configure your cell
return cell
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: "AnotherIdentifier", for: indexPath) as! AnotherCustomCellType
// configure your cell
return cell
}
}

Find if there is a new line starting in the UILabel content at a specific point

I'm working on a project where I have a UILabel inside a UITableViewCell that arrange its cell size based on the content that will fits to its UILabel(UITableViewAutomaticDimension).Hence, This UITableView is has expandable collapsable cells ,thus I set the number of lines = 5 if my cell is collapsed. My requirement is to set the number of line = 4 if the fifth line contain a new line. Because of this complication as of now I get an empty space in my fifth line if it has a new line. My code as bellow.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell1", for: indexPath)
let description = cell.viewWithTag(tableViewCellTags.namelabel) as! UILabel
description.text = jsondata["text"] as! String
description.sizeToFit()
let seeMoreButton = cell.viewWithTag(tableViewCellTags.button) as! UIButton
seeMoreButton.addTarget(self, action: #selector(self.seeMoreClicked(button:)), for: UIControlEvents.touchDown)
cell.setNeedsUpdateConstraints()
cell.updateConstraintsIfNeeded()
description.numberOfLines = isHealerDetailCollapsed ? 5 : 0
loadTheInitialLabelText(descriptionContentLbl: description, descriptionSeeMoreBtn: seeMoreButton)
return cell
}else {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
return cell
}
}
func loadTheInitialLabelText(descriptionContentLbl:UILabel,descriptionSeeMoreBtn:UIButton) {
let DescriptionTextheight = descriptionContentLbl.text?.height(withConstrainedWidth: descriptionContentLbl.frame.width, font: descriptionContentLbl.font)
//let hac = "nednkewnlkednkewnklew".components(separatedBy: "")
// descriptionContentLbl.text
if descriptionContentLbl.intrinsicContentSize.height < DescriptionTextheight! {
descriptionSeeMoreBtn.isHidden = false
}else{
if(isSeemoreVisible){
descriptionSeeMoreBtn.isHidden = true
}
}
}
}
extension String {
func height(withConstrainedWidth width: CGFloat, font: UIFont) -> CGFloat {
let constraintRect = CGSize(width: width, height: .greatestFiniteMagnitude)
let boundingBox = self.boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, attributes: [NSFontAttributeName: font], context: nil)
return boundingBox.height
}
}

UITableCell Swipe/Slide Two or Multiple Cell

I want to ask how could I have done this feature you can see in this image:
I know the editActionsForRowAt but I think it's not the solution for the things I need to do, so I added UISwipeGestureRecognizer and my code look like this:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellId", for: indexPath) as! ConnectionTableCell
let users = self.users[indexPath.section]
let user = users.userInfo[indexPath.row]
cell.userImage.image = UIImage(named: user.imageUrl)
cell.name.text = user.name
cell.work.text = user.work
cell.selectionStyle = .none
cell.addGestureRecognizer(UISwipeGestureRecognizer(target: self, action: #selector(didSwipeForRow)))
return cell
}
func didSwipeForRow(recognizer: UIGestureRecognizer) {
if recognizer.state == UIGestureRecognizerState.ended {
let swipeLocation = recognizer.location(in: self.tableView)
if let swipedIndexPath = tableView.indexPathForRow(at: swipeLocation) {
let textConstant = tableView.frame.width + 10
let imageConstant = tableView.frame.width - 20
let swipeView = UIView()
swipeView.backgroundColor = UIColor.themeColor(color: .green)
let cell = tableView.cellForRow(at: swipedIndexPath) as! ConnectionTableCell
let height = cell.frame.height
let users = self.users[swipedIndexPath.section]
let user = users.userInfo[swipedIndexPath.row]
cell.addSubview(swipeView)
swipeView.frame = CGRect(x: 0, y: 0, width: imageConstant - 60, height: height)
cell.name.leftAnchor.constraint(equalTo: self.tableView.rightAnchor, constant: textConstant).isActive = true
cell.work.leftAnchor.constraint(equalTo: self.tableView.rightAnchor, constant: textConstant).isActive = true
cell.userImage.rightAnchor.constraint(equalTo: self.tableView.rightAnchor, constant: imageConstant).isActive = true
}
}
}
But the problem is when I swipe a cell its also affecting the reused cell as you can see in this image :
Any suggestions on how to solve this issue? Thanks in advance guys.

UITableView scroll freezes when scrolling fast

I am using custom tableview cells in a tableview. The data is loaded from the server and height calculation of that particular cell is done inside the cell only.
<iframe width="560" height="315" src="https://www.youtube.com/embed/h-FjYkSBuNM" frameborder="0" allowfullscreen></iframe>
I am attaching the code for tableview cell for row at indexpath, custom cell method and code for get request.
class QuesAnsFeedTableViewCell: UITableViewCell {
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
setup()
}
override func layoutSubviews() {
super.layoutSubviews()
self.questionLabel.preferredMaxLayoutWidth = questionLabel.frame.width
self.answerLabel.preferredMaxLayoutWidth = answerLabel.frame.width
super.layoutSubviews()
}
func setup(){
topLeftLabel = UILabel()
topLeftLabel.font = UIFont(name: regularFont, size: 12)
topLeftLabel.text = "Yesterday"
topLeftLabel.textColor = CommonFunctions.hexStringToUIColor(hex: lightGray)
topRightLabel = UILabel()
topRightLabel.font = UIFont(name: regularFont, size: 12)
topRightLabel.textColor = CommonFunctions.hexStringToUIColor(hex: lightGray)
topRightLabel.text = ""
topRightLabel.textAlignment = .right
questionLabel = UILabel()
questionLabel.font = UIFont(name: mediumFont, size: 14)
questionLabel.text = "First Ques Comes Here and ans will be below this question"
questionLabel.numberOfLines = 0
questionLabel.lineBreakMode = .byWordWrapping
userImageView = UIImageView()
userImageView.backgroundColor = .purple
userImageView.layer.cornerRadius = CGFloat(sidePadding)/2
userImageView.clipsToBounds = true
userNameLabel = UILabel()
userNameLabel.font = UIFont(name: regularFont, size: 12)
userNameLabel.text = ""
answerLabel = UILabel()
answerLabel.font = UIFont(name: regularFont, size: 14)
answerLabel.text = ""
answerLabel.numberOfLines = 0
answerLabel.lineBreakMode = .byWordWrapping
viewOtherAnswerLabel = UILabel()
viewOtherAnswerLabel.font = UIFont(name: mediumFont, size: 12)
viewOtherAnswerLabel.text = ""
viewOtherAnswerLabel.textAlignment = .center
viewOtherAnswerLabel.textColor = CommonFunctions.hexStringToUIColor(hex: lightGray)
writeAnswerLabel = UILabel()
writeAnswerLabel.font = UIFont(name: mediumFont, size: 14)
writeAnswerLabel.backgroundColor = CommonFunctions.hexStringToUIColor(hex: crispBlue)
writeAnswerLabel.text = "Write Answer"
writeAnswerLabel.textAlignment = .center
writeAnswerLabel.textColor = .white
tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.tappedCell(sender:)))
tapGesture.numberOfTapsRequired = 1
self.addGestureRecognizer(tapGesture)
// self.addSubview(likeButton)
// self.addSubview(descriptionLabel)
}
func updateData(data:NSDictionary) -> CGFloat{
if let viewCount = data["vc"] {
topRightLabel.text = "\(viewCount) read"
}
if let ques = data["q"] as? String{
topLeftLabel.frame = CGRect(x:sidePadding/2, y: 2*sidePaddingForCollectionCells, width: screenWidth/2-sidePadding, height: Int(CommonFunctions.calculateHeight(inString: topLeftLabel.text!, forFont: topLeftLabel.font, andWidthOfLabel: CGFloat(screenWidth/2))))
topRightLabel.frame = CGRect(x: screenWidth/2, y: 2*sidePaddingForCollectionCells, width: screenWidth/2-sidePadding/2, height: Int(topLeftLabel.frame.height))
let newHeight = CommonFunctions.calculateHeight(inString: ques,forFont:questionLabel.font,andWidthOfLabel:questionLabel.frame.width)
questionLabel.frame = CGRect(x:sidePadding/2 ,y: Int(topLeftLabel.frame.maxY)+sidePaddingForCollectionCells,width: screenWidth - sidePadding, height: Int(ceil(Float(newHeight))))
questionLabel.text = ques
self.addSubview(topLeftLabel)
self.addSubview(topRightLabel)
self.addSubview(questionLabel)
// questionLabel.attributedText = CommonFunctions.justifiedText(string: ques)
}
if let user = data.object(forKey: "user") as? NSDictionary{
if let usrName = user.value(forKey: "name"){
userNameLabel.text = "\(usrName)"
}
if let imgLink = user["image"] as? String{
if let url = URL(string: imgLink){
userImageView.sd_setImage(with: url,placeholderImage:#imageLiteral(resourceName: "placeholderImage"))
}
}
}
if let otherAnswer = data.value(forKey: "cc") {
viewOtherAnswerLabel.text = "View Other Answer \(otherAnswer)"
}
if let ans = data.value(forKey: "comt") as? String{
answered = true
userImageView.frame = CGRect(x: sidePadding/2, y: Int(questionLabel.frame.maxY)+2*sidePaddingForCollectionCells, width: sidePadding, height: sidePadding)
userNameLabel.frame = CGRect(x: 3*sidePadding/2+2*sidePaddingForCollectionCells, y:Int(questionLabel.frame.maxY)+sidePaddingForCollectionCells, width: screenWidth-2*sidePadding, height: Int(topLeftLabel.frame.height))
let newHeight = CommonFunctions.calculateHeight(inString: ans,forFont:answerLabel.font,andWidthOfLabel:answerLabel.frame.width)
let frame = CGRect(x: 3*sidePadding/2+2*sidePaddingForCollectionCells, y:Int(userNameLabel.frame.maxY) + sidePaddingForCollectionCells, width: screenWidth-2*sidePadding-2*sidePaddingForCollectionCells, height: Int(ceil(Float(newHeight))))
answerLabel.frame = frame
answerLabel.text = ans
viewOtherAnswerLabel.frame = CGRect(x: 0, y: Int(answerLabel.frame.maxY)+2*sidePaddingForCollectionCells, width: screenWidth, height: 2*sidePadding/3)
self.addSubview(userImageView)
self.addSubview(userNameLabel)
self.addSubview(answerLabel)
self.addSubview(viewOtherAnswerLabel)
writeAnswerLabel.removeFromSuperview()
return viewOtherAnswerLabel.frame.maxY
}
else{
answered = false
writeAnswerLabel.frame = CGRect(x: 0, y:Int(questionLabel.frame.maxY) + 2*sidePaddingForCollectionCells, width: screenWidth, height: sidePadding)
self.addSubview(writeAnswerLabel)
userImageView.removeFromSuperview()
userNameLabel.removeFromSuperview()
answerLabel.removeFromSuperview()
viewOtherAnswerLabel.removeFromSuperview()
return writeAnswerLabel.frame.maxY
}
}
TableView Code
class GenericView: UIView ,UITableViewDelegate,UITableViewDataSource {
var tableView:UITableView!
var viewFrame = CGRect()
var parentView = ""
var discussViewHeight = [Int:CGFloat]()
var nextUrlPath = ""
var currentUrlPath = ""
private var sliderLabelsText = ["Favourites","Sign In"]
private var tableBlocks = [NSDictionary]()
override init(frame: CGRect) {
super.init(frame: frame)
viewFrame = frame
setup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
if viewFrame != CGRect() {
setup()
}
}
public func updateView(){
viewFrame = self.frame
tableView.frame = (viewFrame)
getRequest()
}
func getRequest(){
currentUrlPath = baseUrl+nextUrlPath
if parentView == discussView{
// let url = baseUrl + nextUrlPath
Alamofire.request(currentUrlPath).responseJSON { response in
if let dict = response.result.value as? [String:AnyObject]{
if (dict["msc"]) as? String == "700", let blocks = dict["blocks"] as? NSArray{
self.nextUrlPath = (dict["next"] as? String ?? "")
for block in blocks{
if let blk = block as? NSDictionary{
if blk.value(forKey: "ty") as? String == "qa"{
self.tableBlocks.append(blk)
}
appDelegate.tableBlocks.append(blk)
}
}
DispatchQueue.main.async(execute: { () -> Void in
self.refreshControl.endRefreshing()
self.tableView.reloadData()
})
}
else{
DispatchQueue.main.async(execute: { () -> Void in
self.currentUrlPath = ""
self.getRequest()
})
}
}
}
return
}
}
func setup(){
backgroundColor = UIColor.white
tableView = UITableView(frame: viewFrame, style: .grouped)
tableView.delegate = self
tableView.dataSource = self
self.addSubview(tableView)
registerCells()
}
//MARK: TableView DataSource Methods
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if parentView == discussView{
return 1
}
return 0
}
func numberOfSections(in tableView: UITableView) -> Int {
if parentView == discussView{
return tableBlocks.count
}
return 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if (parentView == discussView){
var cell:QuesAnsFeedTableViewCell? = tableView.dequeueReusableCell(withIdentifier: quesAnsFeedViewCellIdentifier, for: indexPath) as? QuesAnsFeedTableViewCell
if (cell == nil){
cell = QuesAnsFeedTableViewCell(style: .default, reuseIdentifier: quesAnsFeedViewCellIdentifier)
}
cell?.selectionStyle = .none
discussViewHeight[indexPath.section] = (cell?.updateData(data: tableBlocks[indexPath.section]))!
cell?.setNeedsLayout()
cell?.layoutIfNeeded()
return cell!
}
return UITableViewCell()
}
//MARK: TableView Delegate Methods
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if parentView == discussView{
return discussViewHeight[indexPath.section] ?? 0
}
return 0
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
if parentView == discussView{
return sectionHeaderView
}
return UIView()
}
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
if parentView == discussView && indexPath.section+5 > tableBlocks.count{
if currentUrlPath != baseUrl + nextUrlPath{
getRequest()
}
}
}
}
I have deleted some code from classes just to keep the size of question small.
The call for next fetch will depend on the indexpath of cell which is currently being displayed and the function which fetches the content from server will be getRequest().
Any help is greatly appreciated

How do I change the image of button on click?

I have a preset image of a button in a custom cell, and I want that image to change when the button is clicked. How would I do that? I put a switch in the button, and it works. When it is clicked it will play a song, and when it is clicked again it will stop. I just want the image to change. How would I do that? The name of the button is playbutton.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = friendstable.dequeueReusableCellWithIdentifier("friendcell", forIndexPath: indexPath) as! FriendsMusicCell
cell.playbutton.tag = indexPath.row
cell.playbutton.addTarget(self, action: "playmusic:", forControlEvents: .TouchUpInside)
cell.customtitle.text = titleofsong[indexPath.row]
cell.customartist.text = artist[indexPath.row]
cell.customtitle.font = UIFont(name: "Lombok", size: 22)
cell.customtitle.textColor = UIColorFromRGB("4A90E2")
cell.customartist.font = UIFont(name: "Lombok", size: 16)
cell.customartist.textColor = UIColor.blackColor()
cell.customtitle.numberOfLines = 0;
cell.textLabel?.lineBreakMode = NSLineBreakMode.ByWordWrapping
cell.backgroundColor = UIColor.clearColor()
return cell
}
func playmusic(sender: UIButton!) {
let playButtonrow = sender.tag
print(titleofsong[playButtonrow])
switch(buttonState){
case 0:
let searchTerm: String = titleofsong[playButtonrow]
let itunesSearchTerm = searchTerm.stringByReplacingOccurrencesOfString(" ", withString: "+", options: NSStringCompareOptions.CaseInsensitiveSearch, range: nil)
if let escapedSearchTerm = itunesSearchTerm.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding) {
let urlPath = "https://itunes.apple.com/search?term=\(escapedSearchTerm)&media=music"
let url: NSURL = NSURL(string: urlPath)!
print("Search iTunes API at URL \(url)")
let task = NSURLSession.sharedSession().dataTaskWithURL(url) {(data, response, error) -> Void in
do {
if let dict: NSDictionary = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers) as? NSDictionary
{
let previewUrl = NSURL(string: (dict["results"]![0]["previewUrl"] as? String)!)!
print(previewUrl)
self.player = AVPlayer(URL: previewUrl)
self.player.rate = 1.0
self.player.play()
}
} catch let jsonError as NSError {
}
}
task.resume()
}
buttonState = 1;
break;
case 1:
player.pause()
buttonState = 0;
default: break
}
}
You don't need to declare playButton globally
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = friendstable.dequeueReusableCellWithIdentifier("friendcell", forIndexPath: indexPath) as! FriendsMusicCell
cell.playbutton.tag = indexPath.row
cell.playButton.setImage(playImage, forState: UIControlState.Normal)
cell.playButton.setImage(pauseImage, forState: UIControlState.Selected)
cell.playbutton.addTarget(self, action: "playmusic:", forControlEvents: .TouchUpInside)
cell.customtitle.text = titleofsong[indexPath.row]
cell.customartist.text = artist[indexPath.row]
cell.customtitle.font = UIFont(name: "Lombok", size: 22)
cell.customtitle.textColor = UIColorFromRGB("4A90E2")
cell.customartist.font = UIFont(name: "Lombok", size: 16)
cell.customartist.textColor = UIColor.blackColor()
cell.customtitle.numberOfLines = 0;
cell.textLabel?.lineBreakMode = NSLineBreakMode.ByWordWrapping
cell.backgroundColor = UIColor.clearColor()
return cell
}
in your playmusic function you can add the following line at the beginning
sender.selected = !sender.selected
It 's so easy. You can set image for uibutton with UIControlState
ex:
self.btnPlay.setImage(playImage, forState: UIControlState.Normal)
self.btnPlay.setImage(pauseImage, forState: UIControlState.Selected)
And When you click it, you change state of btnPlay:
self.btnPlay.selected = !self.btnPlay.selected

Resources