I am trying to display IPFS image in swift using UIImageView
. When I run my code in xCode/Simulator the image shows fine.
. When I run my code in Xcode/My iPhone device connected via USB works. I do see the image
But when run the app on my phone (after app is installed via Xcode) the IPFS image is not shows for the UIImageView - what am I doing wrong?
func tableView(_ myTableViewAccount: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: TableViewCellAccount = myTableViewAccount.dequeueReusableCell(withIdentifier: "aCell") as! TableViewCellAccount
guard (self.accountsArray.count > 0) else { return cell }
print("accountArray=\(self.accountsArray) indexPath=\(indexPath.row)")
let count = self.accountsArray.count
if (indexPath.row < count) {
guard (self.accountsArray[indexPath.row].name != nil) else { return cell }
cell.accountImgView?.frame.size = CGSize(width: 50, height: 50)
cell.accountImgView.center = view.center
cell.accountImgView.layer.cornerRadius = 18
cell.accountImgView?.clipsToBounds = true
let activityIndicator = UIActivityIndicatorView()
activityIndicator.frame = cell.accountImgView.bounds
cell.accountImgView.addSubview(activityIndicator)
activityIndicator.backgroundColor = UIColor.white
activityIndicator.startAnimating()
let front_img_url = "https://cloudflare-ipfs.com/ipfs/QmYFDgVBMrRfEm5JpVSWeSDAfTUpboEiL8rZyGym24MNVu"
let frontImageURL = URL(string: front_img_url)
if frontImageURL != nil {
DispatchQueue.main.async {
let dataProdFrontImg = try? Data(contentsOf: frontImageURL!)
if let data_front_img = dataProdFrontImg { //fromn img
activityIndicator.stopAnimating()
activityIndicator.removeFromSuperview()
let accountImage = UIImage(data: data_front_img)
cell.accountImgView.image = accountImage
}
}
}
}
return cell
}
... Cell Table is defined like this
class TableViewCellAccount: UITableViewCell {
#IBOutlet weak var accountImgView: UIImageView!
override func awakeFromNib() {
super.awakeFromNib()
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
}
I moved away from UIImage View instead, I used
#IBOutlet weak var accountImgView: WKWebView?
that fixed my issue
Related
I m building a chat View in xCode with swift language.
I m create two custom cell one to sender message and another one to received message. The problem is when the text of message is greater than the width of the screen of iPhone. Then I need to configure the two views to increase the height if the text is too big.
So this is my view:
I configured the height of View Lbl Message >= 30 but if you see xCode set to RED that constraint and for me the error is in that part.
Anyway this is the result of my iPhone when application stil running:
If you check with more attention after the text "mio" in the blue cell you can see that there are other text but it is not displayed.
EDIT
I added ChatVC controller where is the UITableView:
//
// ChatVC.swift
// appUser
//
// Created by mac on 11/10/21.
// Copyright © 2021 Michele Castriotta. All rights reserved.
//
import UIKit
import SDWebImage
import SwiftyJSON
import AVFoundation
class ChatVC: UIViewController, UITableViewDelegate, UITableViewDataSource {
var aggiorna:Bool = false
var arrMsgs:[ChatModel] = []
var receiverId = ""
var storeName = ""
var userName = ""
var userId = ""
var strReason = ""
var strReasonID = ""
var strType = "User"
var strRighTitle = ""
var strPrname = ""
var daNotifica:Bool = false
#IBOutlet weak var viewWriteMessage: UIView!
#IBOutlet weak var lblTitleChat: UILabel!
#IBOutlet weak var txtMessage: UITextField!
#IBOutlet weak var tableViewChat: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
self.showProgressBar()
self.tableViewChat.separatorColor = UIColor.clear
self.viewWriteMessage.setCornerRadius(cornerRadius: 22, borderColor: nil, borderWidth: nil)
userId = kUserDefault.value(forKey: USERID) as! String
self.lblTitleChat.text = self.storeName
wsGetChatAgain()
}
func wsGetChatAgain() {
// showProgressBar()
var paramDict : [String:AnyObject] = [:]
paramDict["receiver_id"] = receiverId as AnyObject
paramDict["sender_id"] = userId as AnyObject
CommunicationManeger.callPostServiceReturnJson(apiUrl: RouterProd.get_chat.url(), parameters: paramDict, parentViewController: self, successBlock: { (responseData, message) in
DispatchQueue.main.async {
do {
let chats = try JSONDecoder().decode(ResponseChatModel.self, from: responseData as! Data)
if(chats.status == "1") {
self.arrMsgs = chats.result
DispatchQueue.main.async {
// Main thread, called after the previous code:
// hide your progress bar here
self.tableViewChat.reloadData()
self.hideProgressBar()
}
//self.scrollToBottom()
//self.lbl_ChatReason.text = self.strReason
}
}catch{
print("errore durante la decodifica dei dati: \(error)")
self.hideProgressBar()
//Utility.noDataFound("Errore", tableViewOt: self.tableViewChat, parentViewController: self)
}
}
}, failureBlock: { (error : Error) in
Utility.showAlertMessage(withTitle: EMPTY_STRING, message: (error.localizedDescription), delegate: nil,parentViewController: self)
self.hideProgressBar()
})
self.aggiorna = true
self.aggiornaChat()
}
func aggiornaChat(){
if(aggiorna){
DispatchQueue.main.asyncAfter(deadline: .now() + 15.0, execute: wsGetChatAgain)
}
}
#IBAction func btnBack(_ sender: Any) {
self.aggiorna = false
if(self.daNotifica == false){
self.navigationController?.popViewController(animated: true)
}else{
Switcher.updateRootVC()
}
}
//MARK: - Table View Methods
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.arrMsgs.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let message = self.arrMsgs[indexPath.row]
var messaggio = message.chatMessage
var orario = Utility.getDateStringFromString(dateString: message.date, inputFormate: "yyyy-MM-dd HH:mm:ss", outputFormate: "HH:mm")
if(message.senderID == userId){
//messaggio inviato dal utente
let cell = tableView.dequeueReusableCell(withIdentifier: "ChatCell", for: indexPath) as! ChatCell
cell.lblMessage.text = messaggio
cell.lblTime.text = orario
var maximumLabelSize: CGSize = CGSize(width: 280, height: 9999)
var expectedLabelSize: CGSize = cell.lblMessage.sizeThatFits(maximumLabelSize)
// create a frame that is filled with the UILabel frame data
var newFrame: CGRect = cell.lblMessage.frame
// resizing the frame to calculated size
newFrame.size.height = expectedLabelSize.height
// put calculated frame into UILabel frame
cell.lblMessage.frame = newFrame
return cell
}else{
//messaggio inviato dallo o runner
let cell = tableView.dequeueReusableCell(withIdentifier: "ChatCell2", for: indexPath) as! ChatCell2
cell.lblMessage.text = messaggio
var maximumLabelSize: CGSize = CGSize(width: 280, height: 9999)
var expectedLabelSize: CGSize = cell.lblMessage.sizeThatFits(maximumLabelSize)
// create a frame that is filled with the UILabel frame data
var newFrame: CGRect = cell.lblMessage.frame
// resizing the frame to calculated size
newFrame.size.height = expectedLabelSize.height
newFrame.size.width = expectedLabelSize.width
// put calculated frame into UILabel frame
cell.lblMessage.frame = newFrame
cell.lblTime.text = orario
return cell
}
}
#IBAction func sendMessage(_ sender: Any) {
if txtMessage.text == "Scrivi qui..." || txtMessage.text!.count == 0 {
GlobalConstant.showAlertMessage(withOkButtonAndTitle: APPNAME, andMessage: "Per favore scrivi del testo...", on: self)
} else {
wsSendMessage()
}
}
func wsSendMessage() {
self.showProgressBar()
var localTimeZoneIdentifier: String { return TimeZone.current.identifier }
var paramDict : [String:AnyObject] = [:]
paramDict["receiver_id"] = receiverId as AnyObject
paramDict["sender_id"] = userId as AnyObject
paramDict["chat_message"] = self.txtMessage.text! as AnyObject
paramDict["timezone"] = localTimeZoneIdentifier as AnyObject
paramDict["request_id"] = strReasonID as AnyObject
paramDict["type"] = strType as AnyObject
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
var dataOra = formatter.string(from:Date())
paramDict["date_time"] = "\(dataOra)" as AnyObject
CommunicationManeger.callPostService(apiUrl: RouterProd.insert_chat.url(), parameters: paramDict, parentViewController: self, successBlock: { (responseData, message) in
DispatchQueue.main.async {
let swiftyJsonVar = JSON(responseData)
print(swiftyJsonVar)
if(swiftyJsonVar["result"].stringValue == "successful") {
self.txtMessage.text = ""
self.view.endEditing(true)
self.wsGetChatAgain()
}
self.hideProgressBar()
}
}, failureBlock: { (error : Error) in
Utility.showAlertMessage(withTitle: EMPTY_STRING, message: (error.localizedDescription), delegate: nil,parentViewController: self)
self.hideProgressBar()
})
}
}
This is chatCell class
import UIKit
class ChatCell: UITableViewCell {
#IBOutlet weak var lblMessage: UILabel!
#IBOutlet weak var viewLblMessage: UIView!
#IBOutlet weak var lblTime: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
self.viewLblMessage.setCornerRadius(cornerRadius: 10, borderColor: nil, borderWidth: nil)
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
}
If you don't know the size of the text, don't add height to the view. You should add your constraints without adding height
According to https://developer.dji.com/api-reference/ios-uilib-api/Widgets/PreFlightStatusWidget.html:
"Tapping on status text will toggle between show and hide DUXPreflightChecklistController."
When I tap on the status text in the widget, the DUXPreflightChecklistController is not shown. Also, if I manually show the DUXPreflightChecklistController, there is a close button in the top right corner of the panel but tapping it does not hide the panel.
What is the proper way to configure this panel?
I'm using DJISDK 4.7.1 and DJIUXSDK 4.7.1 with Swift and iOS 12/xCode 10.0.
To provide a bit more detail, I do not want to use the Default Layout but I am using DUXStatusBarViewController. That is embedded in a UIView across the top of my app. I cannot find any properties for that controller that would allow me to hook it up to my instance of DUXPreflightChecklistController, which is also embedded in a UIView.
For: DUXPreflightChecklistController
I'd just solved that
var preflightChecklistController: DUXPreflightChecklistController!
weak var preFlightTableView: UITableView!
private var compassItemIndex: Int = -1
private var storageItemIndex: Int = -1
override func viewDidLoad() {
super.viewDidLoad()
preflightChecklistController = DUXPreflightChecklistController()
addChild(preflightChecklistController)
}
func renderChecklist() {
if let checklistVC = preflightChecklistController {
for subview in checklistVC.view.subviews {
if subview.isKind(of: UITableView.self) {
if let tableView = subview as? UITableView {
self.view.addSubview(tableView)
preFlightTableView = tableView
}
}
}
guard let checklistManager = checklistVC.checklistManager else { return }
let itemList = checklistManager.preFlightChecklistItems
for (index, item) in itemList.enumerated() {
if let _ = item as? DUXStorageCapacityChecklistItem {
storageItemIndex = index
}
if let _ = item as? DUXCompassChecklistItem {
compassItemIndex = index
}
}
preFlightTableView.reloadData()
checklistManager.startCheckingList()
}
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
renderChecklist()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
guard preFlightTableView != nil else { return }
if let compassCell = preFlightTableView.cellForRow(at: IndexPath(item: compassItemIndex, section: 0)) {
for view in compassCell.subviews {
if let button = view as? UIButton, button.titleLabel?.text == "Calibrate" {
button.addTarget(self, action: #selector(doActionForSpecifiedBTN(sender:)), for: .touchUpInside)
break
}
}
}
if let storageCell = preFlightTableView.cellForRow(at: IndexPath(item: storageItemIndex, section: 0)) {
for view in storageCell.subviews {
if let button = view as? UIButton, button.titleLabel?.text == "Format" {
button.addTarget(self, action: #selector(doActionForSpecifiedBTN(sender:)), for: .touchUpInside)
break
}
}
}
}
#objc func doActionForSpecifiedBTN(sender: UIButton) {
guard let btnTitle = sender.titleLabel else { return }
switch btnTitle.text {
case "Calibrate":
// your func goes here
case "Format":
// your func goes here
default:
break
}
}
I'm getting record from server using php
As i'm getting 11 record currently so i want in starting i will show just 6 records and remaining next 5 record will show when user reached at last cell while scrolling. So this process is in working form, but the problem is while running, it working so fast that before reaching last row all records are already showing while scrolling and the activity indicator is just animating at the bottom of tableView.
I don't know what is the problem.
Also i want when user reached at last cell, activity indicator start animating while loading data .
Here is my code
import UIKit
import AlamofireImage
struct property{
let property_Id : String
let propertyTitle : String
let imageURL : String
let user_Id : String
let area : String
let bed : String
let unit : String
let bath : String
let price : String
}
class searchRecordsViewController: UIViewController, UITableViewDelegate, UITableViewDataSource,favouriteButtonTableViewCellDelegate {
var y = 6
var m = 12
#IBOutlet weak var tableView : UITableView!
var RESULT : [NSDictionary] = []
var myProperty = [property]()
var myPropertyCopy = [property]()
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
//MARK: Getting dictionary data from previous controller
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.navigationItem.title = "Results"
self.navigationController?.navigationBar.tintColor = UIColor.black
//MARK: Getting dictionary data from previous controller
for item in RESULT {
let propertyInfo = property(property_Id: String(item["propertyId"]! as! Int), propertyTitle: item["propertyTitle"]! as! String, imageURL: item["imagePath"]! as! String, user_Id: String(item["userId"]! as! Int), area: item["area"]! as! String, bed: item["bed"]! as! String, unit: item["unit"]! as! String, bath: item["bath"]! as! String, price: item["price"]! as! String )
myProperty.append(propertyInfo)
}
//MARK: Inserting first 6 records in Array
for i in 0 ..< 6 {
if !(myProperty.indices.contains(i)) {
break
}
myPropertyCopy.append(myProperty[i])
}
}
func downloadImage(imagePath : String, theIMAGEVIEW : UIImageView) {
let myUrl = URL(string: URL_IP+imagePath);
//MARK: AlamofireImage to download the image
theIMAGEVIEW.af_setImage(withURL: myUrl!, placeholderImage: #imageLiteral(resourceName: "addProperty"), filter: nil, progress: nil, runImageTransitionIfCached: true, completion: nil)
}
func tableView(_ tableView:UITableView, numberOfRowsInSection section:Int) -> Int
{
return myPropertyCopy.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCell(withIdentifier: "RecordCell") as! searchrecordsTableViewCell
let property = myPropertyCopy[indexPath.row]
cell.area.text = property.area+" "+property.unit
if property.bath == ""{
cell.bath.text = property.bath
}
else{
cell.bath.text = property.bath+" Baths"
}
if property.bed == ""{
cell.bed.text = property.bed
}
else{
cell.bed.text = property.bed+" Baths"
}
cell.propertyTitle.text = property.propertyTitle
cell.price.text = convertAMOUNT(price : property.price)
downloadImage(imagePath: property.imageURL, theIMAGEVIEW: cell.myImageView)
//----
cell.delegate = self
return cell
}
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
if myPropertyCopy.count != myProperty.count{
let lastRow = myPropertyCopy.count - 1
if indexPath.row == lastRow {
let spinner = UIActivityIndicatorView(activityIndicatorStyle: .gray)
spinner.startAnimating()
spinner.frame = CGRect(x: CGFloat(0), y: CGFloat(0), width: tableView.bounds.width, height: CGFloat(44))
self.tableView.tableFooterView = spinner
self.tableView.tableFooterView?.isHidden = false
moreData()
}
}
}
func moreData(){
for i in y ..< m {
if !(myProperty.indices.contains(i)) {
break
}
myPropertyCopy.append(myProperty[i])
}
y = y + 10
m = m + 10
self.tableView.reloadData()
}
}
currently my TableView looks like
See output here
Thanks in Advance.
After a long practice i have done my problem, i have just added UIScrollView delegate function for checking if the user reached at last cell then start activityIndicator for 3 seconds and then load data and that's it.
As i have just very small amount of data that's why i'm start ing UIactivityIndicator for 3 seconds before getting data.
func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
// UITableView only moves in one direction, y axis
let currentOffset = scrollView.contentOffset.y
let maximumOffset = scrollView.contentSize.height - scrollView.frame.size.height
if maximumOffset - currentOffset <= 10.0 {
let spinner = UIActivityIndicatorView(activityIndicatorStyle: .gray)
if myPropertyCopy.count != myProperty.count {
//print("this is the last cell")
spinner.startAnimating()
spinner.frame = CGRect(x: CGFloat(0), y: CGFloat(0), width: tableView.bounds.width, height: CGFloat(44))
spinner.hidesWhenStopped = true
self.tableView.tableFooterView = spinner
self.tableView.tableFooterView?.isHidden = false
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
//MARK: Loading more data
self.moreData()
}
}
else{
self.tableView.tableFooterView?.isHidden = true
spinner.stopAnimating()
}
}
}
I am still new to swift and I would ask you for advice. Thank you in advance and sorry for my bad English.
My goal is:
User tap edit button in the table's row. UITextField appears instead cell. After entering value and pressing Return key UITextField disappears again and cell is recalculated.
editButton pressed -> hide priceCell & show UITextField & show keyboard & start editing/entering value (blinking cursor) -> stop editing/entering value execute by pressing Return key -> hide UITextField & shows priceCell & save entered value into array & reload edited row
I use this answer as starting blueprint.
I would like to also use .decimalPad keyboard to easier entering numeric value and limit user to use only numbers (and decimal point), but this exclude use Return key as stop editing, am I right?
I found this possible solution, but it seems to me complex for my problem...
my ViewController:
import UIKit
class PortfolioViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UITextFieldDelegate, PortfolioCellDelegate {
let getData = GetData()
...
override func viewDidLoad() {
super.viewDidLoad()
cellTableView.delegate = self
cellTableView.dataSource = self
cellTableView.register(UINib(nibName: "PortfolioCell", bundle: nil), forCellReuseIdentifier: "portfolioCell")
self.currencyControl.selectedSegmentIndex = MyVariables.currencyControlSelected
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let coinCell = tableView.dequeueReusableCell(withIdentifier: "portfolioCell", for: indexPath) as! PortfolioCell
...
coinCell.delegate = self
return coinCell
}
...
func portfolioButtonPressed(coinCell: PortfolioCell) {
let indexPath = self.cellTableView.indexPathForRow(at: coinCell.center)!
let selectedCell = cellTableView.cellForRow(at: indexPath) as! PortfolioCell
selectedCell.priceCell.isHidden = true
selectedCell.textCell.isHidden = false
selectedCell.textCell.delegate = self
func textFieldDidEndEditing(textField: UITextField) {
let owned: Double = Double(textField.text!)!
if owned >= 0 {
MyVariables.dataArray[indexPath.row].ownedCell = owned
} else {
MyVariables.dataArray[indexPath.row].ownedCell = 0.00
}
selectedCell.priceCell.isHidden = false
selectedCell.textCell.isHidden = true
self.cellTableView.reloadData()
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
selectedCell.textCell.resignFirstResponder()
return true
}
}
...
}
my custom cell:
import UIKit
protocol PortfolioCellDelegate {
func portfolioButtonPressed(coinCell: PortfolioCell)
}
class PortfolioCell: UITableViewCell {
var delegate: PortfolioCellDelegate?
...
#IBAction func editCellPressed(_ sender: UIButton) {
delegate?.portfolioButtonPressed(coinCell: self)
}
...
}
For now when button is pressed proper UITextField shows, but don't dismiss after Return key is pressed.
Or should I change it completely and use tap gestures?
To end editing in any kind of scrollView, simply use this
cellTableView.keyboardDismissMode = .onDrag
or
cellTableView.keyboardDismissMode = .interactive
It will hide keyboard when you interact with the tableView
For number keypad you can add toolbar as a textField's inputAccessoryView. On toolbar add cancel button to dismiss keyboard.
There is two way to go:
1.) Delegate
2.) IQKeyboardManager
1.)
Use UITextFieldDelegate
There is one particular callback named "textFieldShouldEndEditing"
In this method, return true.
2.)
User the IQKeyboardManager one liner library. This library manages all the TextFields and scrollviews automatically. You activate it with one line in AppDelegate so it's easy to use.
https://github.com/hackiftekhar/IQKeyboardManager
Working but not as sleek as want it to be and also I was not capable to make IQKeyboardManager works so I did use inputAccessoryView.
custom cell:
import UIKit
protocol PortfolioCellDelegate {
func portfolioButtonPressed(didSelect coinCell: PortfolioCell)
func portfolioButtonPressed(coinCell:PortfolioCell, editingChangedInTextCell newValue:String)
}
class PortfolioCell: UITableViewCell, UITextFieldDelegate {
var delegate: PortfolioCellDelegate?
...
#IBAction func editCellPressed(_ sender: UIButton) {
textCell.becomeFirstResponder()
delegate?.portfolioButtonPressed(didSelect: self)
}
#IBAction func textCellValueChanged(_ sender: UITextField) {
if (sender.text?.isEmpty)! {
delegate?.portfolioButtonPressed(coinCell: self, editingChangedInTextCell: "XXX")
} else {
let text = sender.text
delegate?.portfolioButtonPressed(coinCell: self, editingChangedInTextCell: text!)
}
}
override func awakeFromNib() {
super.awakeFromNib()
self.textCell.delegate = self
let flexiableSpace = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: nil, action: nil)
let doneButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.done, target: self, action: #selector(self.doneButtonAction))
let toolBar:UIToolbar = UIToolbar(frame: CGRect(x: 0, y: 0, width: frame.size.width, height: 35))
toolBar.barTintColor = UIColor(red:0.15, green:0.69, blue:0.75, alpha:1.0)
toolBar.tintColor = UIColor(red:0.93, green:0.93, blue:0.93, alpha:1.0)
toolBar.setItems([flexiableSpace, doneButton], animated: false)
textCell.inputAccessoryView = toolBar
textCell.keyboardType = UIKeyboardType.decimalPad
}
#objc func doneButtonAction() {
textCell.endEditing(true)
}
...
}
ViewController:
import UIKit
class PortfolioViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, PortfolioCellDelegate {
let getData = GetData()
...
override func viewDidLoad() {
super.viewDidLoad()
cellTableView.delegate = self
cellTableView.dataSource = self
cellTableView.register(UINib(nibName: "PortfolioCell", bundle: nil), forCellReuseIdentifier: "portfolioCell")
self.currencyControl.selectedSegmentIndex = MyVariables.currencyControlSelected
getData.delegate = self
timeStampLabel.text = MyVariables.timeStamp
}
override func viewDidAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.cellTableView.reloadData()
self.currencyControl.selectedSegmentIndex = MyVariables.currencyControlSelected
self.timeStampLabel.text = MyVariables.timeStamp
}
//MARK: - tableView
/***************************************************************/
...
func portfolioButtonPressed(coinCell: PortfolioCell, editingChangedInTextCell newValue: String) {
let indexPath = self.cellTableView.indexPathForRow(at: coinCell.center)!
let selectedCell = cellTableView.cellForRow(at: indexPath) as! PortfolioCell
selectedCell.priceCell.isHidden = false
selectedCell.textCell.isHidden = true
if newValue != "XXX" {
let owned: Double = Double(newValue)!
MyVariables.dataArray[indexPath.row].ownedCell = owned
}
selectedCell.priceCell.isHidden = false
selectedCell.textCell.isHidden = true
self.cellTableView.reloadRows(at: [indexPath], with: .automatic)
}
func portfolioButtonPressed(didSelect coinCell: PortfolioCell) {
let indexPath = self.cellTableView.indexPathForRow(at: coinCell.center)!
let selectedCell = cellTableView.cellForRow(at: indexPath) as! PortfolioCell
selectedCell.priceCell.isHidden = true
selectedCell.textCell.isHidden = false
}
...
}
It's easy: You should select that table view cell, then enable User Interaction Enabled in the attribute inspector.
I have an issue that has been vexing me for a while and I feel like I am so close. Here is the situation. I have a tableview that holds different calculus videos and I would like to give my students the ability to download the videos for playing offline. That part works fine. The problem I am having is that when the user clicks on the download button, the download button should hide and show an activity indicator as well as a progress bar (all of which are in a custom cell). I have two problems:
1) The download button does not automatically hide and show the activity view unless I scroll away from it and come back to it.
2) If I do scroll down all of a sudden random cells will not have the download button anymore.
This must be due to the fact that cells are being reused but I thought I was doing things properly although obviously there is a mistake. I will post the relevant code snippets below:
cellForRowAtIndexPath Code:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("VideoCell", forIndexPath: indexPath) as! TableViewCell
let currentVideo = videos[indexPath.section][indexPath.row]
cell.downloadButton.addTarget(self, action: "downloadButtonPressed:", forControlEvents: .TouchUpInside)
cell.video = currentVideo
return cell
}
Custom Table View Cell Code:
class TableViewCell: UITableViewCell {
#IBOutlet weak var videoTitleLabel: UILabel!
#IBOutlet weak var progressView: UIProgressView!
#IBOutlet weak var customAccessoryView: UIView!
#IBOutlet weak var downloadButton: UIButton!
#IBOutlet weak var activityIndicator: UIActivityIndicatorView!
let userDefaults = NSUserDefaults.standardUserDefaults()
var video: Video? {
didSet {
updateUI()
}
}
private func updateUI() {
guard let video = video else {
print("video should not be nil")
return
}
videoTitleLabel.text = video.title
if video.downloadStatus.isDownloading {
progressView.hidden = false
progressView.progress = video.downloadStatus.downloadProgress
downloadButton.hidden = true
activityIndicator.hidden = false
activityIndicator.startAnimating()
} else {
progressView.hidden = true
activityIndicator.stopAnimating()
}
if video.downloadStatus.isSaved {
activityIndicator.stopAnimating()
progressView.hidden = true
downloadButton.hidden = true
}
}
Download request
func downloadButtonPressed(sender: UIButton) {
let buttonPosition = sender.convertPoint(CGPointZero, toView: self.tableView)
guard let indexPath = self.tableView.indexPathForRowAtPoint(buttonPosition) else {
print("Error getting index path from button press")
return
}
let section = indexPath.section
let row = indexPath.row
print("Button pressed at section \(section) and row \(row)")//correct row and section
//Code to save Video to Documents directory goes here
let currentVideo = videos[section][row]
guard !currentVideo.downloadStatus.isSaved else {
print("Video is already saved")
return
}
guard let url = currentVideo.url else {
print("Video not found...url is invalid")
return
}
let destination = Alamofire.Request.suggestedDownloadDestination(directory: .DocumentDirectory, domain: .UserDomainMask)
Alamofire.download(.GET, url, destination: destination)
.progress { bytesRead, totalBytesRead, totalBytesExpectedToRead in
let progress = Float(totalBytesRead) / Float(totalBytesExpectedToRead)
currentVideo.downloadStatus.isDownloading = true
currentVideo.downloadStatus.downloadProgress = progress
}.response { request,response,data, error in
if let error = error {
print("Failed with error: \(error)")
} else {
print("Downloaded file successfully")
currentVideo.downloadStatus.isDownloading = false
currentVideo.downloadStatus.isSaved = true
self.saveDownloadStatusInDefaultsForVideo(currentVideo, isSaved: true)
}
print("Files currently in the documents directory:")
self.printDocumentsDirectoryContents() //file is there
}
}
In your class TableViewCell you're setting the property hidden of downloadButton to true under certain circumstances.
If you want the button to be visible by default set the property explicitly to false when reusing the cell