Swift / is there any equivalent to UITableViewRowAction for a UICollectionView? - ios

I have a UICollectionView with a button within a cell. I want the User to share the UIImage Image that is inside the CollectionViewCell.
At the Moment I have this code:
class EventsCollectionViewCell: UICollectionViewCell {
#IBOutlet weak var eventsImageView: UIImageView!
#IBAction func cellDetailButton(sender: AnyObject) {
var alertView:UIAlertView = UIAlertView()
alertView.title = "Alert!"
alertView.message = "Message"
alertView.delegate = self
alertView.addButtonWithTitle("OK")
alertView.show()
}
I use this code for a tableView within another project, but I don't know how to use it in a CollectionViewCell:
override func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [UITableViewRowAction]? {
let shareRaceAction = UITableViewRowAction(style: .Default, title: "Share") {
(action: UITableViewRowAction, indexPath: NSIndexPath) -> Void in
let sheet = UIAlertController(title: nil, message: "Teilen mit", preferredStyle: .ActionSheet)
let race = self.races[indexPath.row]
//
let twAction = self.newAction(SLServiceTypeTwitter, race: race)
sheet.addAction(twAction)
//
let fbAction = self.newAction(SLServiceTypeFacebook, race: race)
sheet.addAction(fbAction)
//
let cancelAction = UIAlertAction(title: "Abbrechen", style: .Cancel, handler: nil)
sheet.addAction(cancelAction)
self.presentViewController(sheet, animated: true, completion: nil)
}
shareRaceAction.backgroundColor = UIColor.blueColor()
return [shareRaceAction]
}
Help is very appreciated.

Related

How to change the title of an UIAlertAction

How can I change the title of an UIAlertAction when I click the button ?
I want to click that button and from "Enable" to make it "Disable" for example.
I spent a lot of time trying to achieve this but I can't manage to do it.
Here is a small Demo with my issue: https://github.com/tygruletz/ChangeTitleOfAlertAction
Here is my code:
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
}
extension ViewController: UITableViewDelegate, UITableViewDataSource{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 5
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
tableView.tableFooterView = UIView()
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = "Row \(indexPath.row)"
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
showOptions()
}
func showOptions(){
var enable = "Enable"
let disable = "Disable"
let applyOn = UIAlertAction(title: enable, style: .default, handler: { (action: UIAlertAction!) in
enable = disable
})
let actionSheet = configureActionSheet()
actionSheet.addAction(applyOn)
self.present(actionSheet, animated: true, completion: nil)
}
func configureActionSheet() -> UIAlertController {
let actionSheet = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
let cancel = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
actionSheet.addAction(cancel)
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiom.pad ){
actionSheet.popoverPresentationController?.sourceView = self.view
actionSheet.popoverPresentationController?.sourceRect = CGRect(x: self.view.bounds.midX, y: self.view.bounds.midY, width: 0, height: 0)
actionSheet.popoverPresentationController?.permittedArrowDirections = []
}
return actionSheet
}
}
And here is a capture of screen:
Thank you if you try to help me !
Please follow below code:
Define property in your UIViewController
var selectedIndexPath:IndexPath!
Add argument in showOptions method
func showOptions(indexPath:IndexPath){
var status = "Enable"
if selectedIndexPath == indexPath{
status = "Disable"
}
let applyOn = UIAlertAction(title: status, style: .default, handler: { (action: UIAlertAction!) in
if self.selectedIndexPath == indexPath{
self.selectedIndexPath = nil
}else{
self.selectedIndexPath = indexPath
}
})
let actionSheet = configureActionSheet()
actionSheet.addAction(applyOn)
self.present(actionSheet, animated: true, completion: nil)
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
showOptions(indexPath: indexPath)
}
Note:
If you are going with this approach, Then you will never faced cell usability issue.

Why handle clicking on TableView Swift IOS worth cell rows are the previous rows clicked? [duplicate]

This question already has an answer here:
Issue with UITableView: Action only works every second time
(1 answer)
Closed 3 years ago.
I already the TableView for displaying JSON Values from API. But the result of the click does not match the existing title, but it is worth the title from the previous click. More clearly see the picture
Code InfoViewCell.swift
This code for cell in tableview
import UIKit
class InfoViewCell: UITableViewCell {
#IBOutlet weak var imgInfo: UIImageView!
#IBOutlet weak var lblInfo: UILabel!
#IBOutlet weak var lblBerita: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
Code Info.swift this code for models
class Info {
var id_informasi: Int?
var tgl_informasi: String?
var judul: String?
var berita: String?
var foto: String?
init(id_informasi:Int?,judul: String?,berita: String?,foto: String?) {
self.id_informasi = id_informasi
self.judul = judul
self.berita = berita
self.foto = foto
}
}
Code InfoViewController.swift
import UIKit
import Alamofire
import AlamofireImage
class InformasiViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var tableInfo: UITableView!
var activityIndicator:UIActivityIndicatorView = UIActivityIndicatorView()
var infoes = [Info]()
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return infoes.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellInfo", for: indexPath) as! InfoViewCell
//getting the hero for the specified position
let inpo: Info
inpo = infoes[indexPath.row]
//displaying values
cell.lblInfo.text = inpo.judul
cell.lblBerita.text = inpo.berita
//displaying image
Alamofire.request(inpo.foto!).responseImage { response in
debugPrint(response)
if let image = response.result.value {
cell.imgInfo.image = image
}
}
return cell
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
let info: Info
info = infoes[indexPath.row]
//building an alert
let alertController = UIAlertController(title: info.judul, message: "", preferredStyle: .alert)
//the confirm action taking the inputs
let confirmAction = UIAlertAction(title: "Enter", style: .default) { (_) in
}
//the cancel action doing nothing
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel) { (_) in }
//adding action
alertController.addAction(confirmAction)
alertController.addAction(cancelAction)
//presenting dialog
present(alertController, animated: true, completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
let defaultValues = UserDefaults.standard
let token = defaultValues.string(forKey: "token")
//the Web API URL
let URL_GET_DATA = "https://api.landslidepad.com/api/admin_desa/informasi_penting?token=" + token!
activityIndicator.center = self.view.center
activityIndicator.hidesWhenStopped = true
activityIndicator.style = UIActivityIndicatorView.Style.gray
view.addSubview(activityIndicator)
activityIndicator.startAnimating()
//fetching data from web api
Alamofire.request(URL_GET_DATA, method: .get).responseJSON
{
response in
//printing response
print(response)
self.activityIndicator.stopAnimating()
//getting the json value from the server
if let result = response.result.value {
let jsonData = result as! NSDictionary
//if there is no error
if((jsonData.value(forKey: "message") as! String == "Sukses!")){
//getting the user from response
let user = jsonData.value(forKey: "values") as! NSArray
for i in 0..<user.count{
//adding hero values to the hero list
self.infoes.append(Info(
id_informasi: (user[i] as AnyObject).value(forKey: "id_informasi") as? Int,
judul: (user[i] as AnyObject).value(forKey: "judul") as? String,
berita: (user[i] as AnyObject).value(forKey: "berita") as? String,
foto: (user[i] as AnyObject).value(forKey: "foto") as? String
))
}
//displaying data in tableview
self.tableInfo.reloadData()
}else{
let alert = UIAlertController(title: "Ada yang salah?", message: "Silahkan Ulangi Kembali!.", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Yes", style: .default, handler: nil))
alert.addAction(UIAlertAction(title: "No", style: .cancel, handler: nil))
self.present(alert, animated: true)
}
}
}
self.tableInfo.reloadData()
// Do any additional setup after loading the view, typically from a nib.
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
I already tried to create func tableview didDeselectRowAt indexPath,
but the value I want to display is not in line with my expectations. I will pass this value to the detailed view
Thanks
When you click on a row, that row is selected — and the previous selected row is deselected. Well, you have implemented didDeselect, so the previous selected row is displayed. Instead, implement didSelect.
instead of this
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
let info: Info
info = infoes[indexPath.row]
//building an alert
let alertController = UIAlertController(title: info.judul, message: "", preferredStyle: .alert)
//the confirm action taking the inputs
let confirmAction = UIAlertAction(title: "Enter", style: .default) { (_) in
}
//the cancel action doing nothing
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel) { (_) in }
//adding action
alertController.addAction(confirmAction)
alertController.addAction(cancelAction)
//presenting dialog
present(alertController, animated: true, completion: nil)
}
please use this
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let info: Info
info = infoes[indexPath.row]
//building an alert
let alertController = UIAlertController(title: info.judul, message: "", preferredStyle: .alert)
//the confirm action taking the inputs
let confirmAction = UIAlertAction(title: "Enter", style: .default) { (_) in
}
//the cancel action doing nothing
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel) { (_) in }
//adding action
alertController.addAction(confirmAction)
alertController.addAction(cancelAction)
//presenting dialog
present(alertController, animated: true, completion: nil)
}

Saving the tableview text after edited swift

I have managed to create a tableview with an array or messages and when i tapped a tableview cell it shows an alertview and a uitextfield that you can change the text of the tableview. What i'm trying to do now is to save the tableview text ("message") when it changed. Because when I go to another view controller and go back it does not save. I am new on swift programming and wondering how can i achieve that. I have read some articles that i need to use nsuserdefaults but i am not familiar with that. here is my code below. Thanks guys.
class Messages: UITableViewController {
#IBOutlet var uitableView: UITableView!
var tField: UITextField!
var index: Int?
var msgArray: [String]!
var messages = ["Message 1", "Message 2", "Message 3", "Message 4", "Message 5", "Message 6"]
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return messages.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
let messagesCell = messages[indexPath.row]
cell.textLabel?.text = messagesCell
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let path = tableView.indexPathForSelectedRow
index = path?.row
changeMessage()
}
func changeMessage() {
let alert = UIAlertController(title: "Message", message: "Enter new preset message", preferredStyle: UIAlertControllerStyle.alert)
alert.addTextField(configurationHandler: configurationTextField)
let doneAction = UIAlertAction(title: "Done", style: UIAlertActionStyle.default, handler:{ (UIAlertAction) in
let modelString = self.tField.text
self.messages[self.index!] = modelString!
self.tableView.reloadData()
})
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
alert.addAction(doneAction)
alert.addAction(cancelAction)
self.present(alert, animated: true, completion: nil)
}
func configurationTextField(textField: UITextField!){
if (textField) != nil {
tField = textField
textField.text = messages[index!]
}
}
}
Try to use nsuserdefaults. In SWIFT 3
override func viewWillAppear(_ animated: Bool) {
//Get the array
if let array = UserDefaults.standard.object(forKey:"messages") as? Array<String> {
self.messages = array
}
}
func changeMessage() {
let alert = UIAlertController(title: "Message", message: "Enter new preset message", preferredStyle: UIAlertControllerStyle.alert)
alert.addTextField(configurationHandler: configurationTextField)
let doneAction = UIAlertAction(title: "Done", style: UIAlertActionStyle.default, handler:{ (UIAlertAction) in
let modelString = self.tField.text
self.messages[self.index!] = modelString!
UserDefaults.standard.set(self.messages, forKey: "messages") // Set the array with changes
self.tableView.reloadData()
})
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: nil)
alert.addAction(doneAction)
alert.addAction(cancelAction)
self.present(alert, animated: true, completion: nil)
}
let defaults = UserDefaults.standard
defaults.set("123", forKey: "oldString")
print("\(UserDefaults.standard.value(forKey: "oldString")!)")
This may help you.

Can't reload UITableView

I am trying to design View where i can show elements in sync with my Firebase Database. Every time element in my array changes it gets duplicated. Tried to use
self.tableView.reloadData()
but nothing changes. Tried as well
self.tableView.beginUpdates()
self.tableView.reloadRowsAtIndexPaths(NSArray.init(object: indexPath) as! [NSIndexPath], withRowAnimation: .Automatic)
self.tableView.endUpdates()
and it didn't work as previously.
I have tried unsuccesfully to perform reloading tableView in main thread using function
performSelectorOnMainThread
I am posting my code for you guys so someone can help me. Im quite new to iOS programming and i can't figure out when to reload data in tableView. Even after reading Apple's Documentation.
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let alert = UIAlertController(title: "Akcja", message: "Wybierz akcję", preferredStyle: .ActionSheet)
let changeFieldNumberAction = UIAlertAction(title: "Zmień numer boiska", style: .Default, handler: {(action) in
self.showAlertOfChangingFieldNumber(indexPath)
})
let sendToRefereeAction = UIAlertAction(title: "Wskaż sędziego", style: .Default, handler: {(action) in
//self.championshitTournamentMode = false
})
let cancelAction = UIAlertAction(title: "Anuluj", style: .Cancel, handler: nil)
alert.addAction(cancelAction)
alert.addAction(changeFieldNumberAction)
alert.addAction(sendToRefereeAction)
self.presentViewController(alert, animated: true, completion: nil)
}
func showAlertOfChangingFieldNumber(indexPath: NSIndexPath) {
let fieldNumberAlert = UIAlertController(title: "Numer boiska", message: "Wpisz numer boiska", preferredStyle: .Alert)
fieldNumberAlert.addTextFieldWithConfigurationHandler({(textField: UITextField!) -> Void in
textField.placeholder = "Numer boiska"
textField.keyboardType = UIKeyboardType.NumberPad
})
let saveAction = UIAlertAction(title: "Zapisz", style: .Default, handler: {(action) -> Void in
let fieldNumberTextField = fieldNumberAlert.textFields![0] as UITextField
let fieldNumber = Int(fieldNumberTextField.text!)
self.updateGameFieldNumber(fieldNumber!, indexPath: indexPath)
})
let cancelAction = UIAlertAction(title: "Anuluj", style: .Cancel, handler: nil)
fieldNumberAlert.addAction(cancelAction)
fieldNumberAlert.addAction(saveAction)
self.presentViewController(fieldNumberAlert, animated: true, completion: nil)
}
func updateGameFieldNumber(fieldNumber: Int, indexPath: NSIndexPath){
let gameKey = games[indexPath.row].key
let ref = FIRDatabase.database().reference().child("games").child(gameKey)
games[indexPath.row].fieldNumber = fieldNumber
ref.updateChildValues(games[indexPath.row].toAnyObject() as! [NSObject : AnyObject])
//self.games.removeAtIndex(indexPath.row+1)
self.tableView.beginUpdates()
self.tableView.reloadRowsAtIndexPaths(NSArray.init(object: indexPath) as! [NSIndexPath], withRowAnimation: .Automatic)
self.tableView.endUpdates()
}
And my tableView delegate functions and function made for filling my array based on Firebase's database looks like that:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! GameViewCellTableViewCell
if games[indexPath.row].fieldNumber == 0 {
cell.fieldNumberLabel.text = "-"
} else {
cell.fieldNumberLabel.text = String(games[indexPath.row].fieldNumber)
}
cell.firstParticipantLabel.text = games[indexPath.row].firstParticipant
cell.secondParticipantLabel.text = games[indexPath.row].secondParticipant
cell.gameImage.image = UIImage(named: "tenisBall")
if games[indexPath.row].completed != true {
cell.backgroundColor = UIColor.init(red: 1, green: 109.0/255, blue: 95.0/255, alpha: 1)
} else {
cell.backgroundColor = UIColor.init(red: 160/255, green: 1, blue: 86/255, alpha: 1)
}
return cell
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.games.count
}
func getGames() {
let ref = FIRDatabase.database().reference().child("games")
ref.observeEventType(.Value, withBlock: {snapshot in
for item in snapshot.children {
let gameItem = GameItem(snapshot: item as! FIRDataSnapshot)
if(gameItem.tournamentName == self.tournamentName) {
self.games.append(gameItem)
}
}
self.tableView.reloadData()
})
}
It gets duplicated because instead of updating the value in your "games" array, you append the modified value to the array. This happens in the "getgames()" method.
inside the
func getGames()
after
self.games.append(gameItem)
dispatch_async(dispatch_get_main_queue(), {
self.tableView.reloadData()
})

Swift / UICollectionView / Share Button in cell

I have a UIViewController, with a UICollectionView with a (custom) UIButton at the reusableViewCell.
I have the following code for a TableView
override func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [UITableViewRowAction]? {
let shareRaceAction = UITableViewRowAction(style: .Default, title: "Share") {
(action: UITableViewRowAction, indexPath: NSIndexPath) -> Void in
let sheet = UIAlertController(title: nil, message: "Teilen mit", preferredStyle: .ActionSheet)
let race = self.races[indexPath.row]
//
let twAction = self.newAction(SLServiceTypeTwitter, race: race)
sheet.addAction(twAction)
//
let fbAction = self.newAction(SLServiceTypeFacebook, race: race)
sheet.addAction(fbAction)
//
let cancelAction = UIAlertAction(title: "Abbrechen", style: .Cancel, handler: nil)
sheet.addAction(cancelAction)
self.presentViewController(sheet, animated: true, completion: nil)
}
How can this Code be implemented for a UICollectionView with a custom button?
Help is very appreciated

Resources