Swift dropDown library - swift

I am using the dropdown library. When you press a button, you want to develop it in a format where text changes on the button when you click an element.I can print but I don't know how to change the text of the button. And I want to change the sort order of the table view when I click that element. How should I do it?
func dropDown() {
sequenceDropDown.dataSource = ["Latest order
", "Priority"]
sequenceDropDown.show()
sequenceDropDown.anchorView = sequence
sequenceDropDown.bottomOffset = CGPoint(x: 0, y:(sequenceDropDown.anchorView?.plainView.bounds.height)!)
sequenceDropDown.selectedTextColor = .white
sequenceDropDown.selectionBackgroundColor = .mainColor
}
This is dropDown function.
output.loadData.bind(to: tableView.rx.items(cellIdentifier: "mainCell", cellType: MainCell.self)) { row, element, cell in
cell.nameLbl.text = element.nickname
cell.titleTxtField.text = element.title
cell.contentTxtView.text = element.description
cell.postImage.image = UIImage(named: element.media)
cell.timeLbl.text = element.date
cell.sirenBtn.rx.tap.subscribe(onNext: { _ in
self.selectIndexPath.accept(row)
}).disposed(by: self.disposeBag)
}.disposed(by: disposeBag)
This is binding tableview code.

setting button's title is easy myButton.setTitle("Play", for: .normal)
if you want to change sort of table view, you probably should map loadData observable to needed sort method, maybe it's even better to store ouput from loadData to some array and wrap it to observable or subject, bind it to table view and if you need to see sorted tableview just sort the array
(maybe I didn't get you case point completely)

Related

Trouble setting UIButton title of selected Action picker item, SWIFT

I am finding trouble to set title for button of action picker item.
ActionSheetMultipleStringPicker.show(withTitle: "Select Nationality", rows: [
nationalityArray], initialSelection: [selectedNationalityIdStr],
doneBlock: {
picker, indexes, values in
let selectedEmirate = "\(values)"
self.btnNationality.setTitle(selectedEmirate, for: .normal)
print("values = \(values)")
print("indexes = \(finalIntId)")
print("picker = \(picker)")
return
}, cancel:
{
ActionMultipleStringCancelBlock in return
}, origin: sender)
the print of Values inside the Action sheet picker is this
values = Optional(<__NSSingleObjectArrayI 0x600001ba1740>(Expat)
so when I write this below line to set title for a UIButton then it is setting up whole
self.btnNationality.setTitle("\(selectedEmirate)", for: .normal)
As you can see here, it is taking whole values string instead of only "expat":
Some one help me setting up only "expat" from the values of my action sheet picker please

find descendant buttons in nested container

I have placed buttons in multiple nested StackViews
I then placed the views within a CollectionView (yes I recognize this isn't necessarily the best or optimal way to do this).
I'm trying to figure out how I can programmatically find all my buttons.
If I do this, all I get is my StackView instead of getting the buttons (which are now 3rd level descendants). I'd love to not have to right a nested loop and instead find a function that helps me find all descendants of type UIButton.
for subview in buttonContainer.subviews {
let button = subview as? UIButton
if button != nil {
button!.setTitle("TEST", for: UIControl.State.normal)
}
}
The reason I'm doing this is just as an exercise to learn different methods, which is why I am ok nesting multiple stack views and then placing them within a CollectionView
You need to create a recursive method like:
func buttonsIn(_ view: UIView) {
if let button = view as? UIButton {
button.setTitle("TEST", for: .normal)
} else {
view.subviews.forEach({ buttonsIn($0) })
}
}
Usage:
buttonsIn(view)
Modify the recursive method as per your requirement.
I didn't test it but using recursion you should be able to accomplish this. Something like this may work for you:
func findButtonsIn(_ view: UIView) -> [UIButton] {
var buttons: [UIButton] = []
view.subviews.forEach({
if let button = $0 as? UIButton {
buttons.append(button)
} else {
buttons.append(contentsOf: self.findButtonsIn($0))
}
})
return buttons
}
Usage
findButtonsIn(yourView)
The function will return all found UIButtons as an array.
You could use
self.findButtonsIn(UIView()).enumerated().forEach({
$0.element.setTitle("\($0.offset)", for: .normal)
})
for example to set the buttons title according to the order they were found in.

tableViewSelectionDidChange with addSubview and removeFromSuperview in table row

I looked for posts for issues with all 3 functions listed in the title, but my problem is not discussed anywhere. Frankly, my problem is such that it defies logic IMHO.
On selection of a row in my view-based NSTableView, I want to show a "Save" button in my last (aka "Action") column. So on viewDidLoad() I created my orphan button. Then on tableViewSelectionDidChange() I remove it from the superview and add it to my column's NSTableCellView. When there's no row selected, there is no button to show. Simple. Below code works perfectly.
func tableViewSelectionDidChange(_ notification: Notification) {
let selectedRow = tableView.selectedRow
btnSave!.removeFromSuperview()
if selectedRow > -1,
let rowView = rowView(selectedRow),
let actionView = rowView.view(atColumn: Column.action.hashValue) as? NSTableCellView {
actionView.addSubview(btnSave!)
}
}
Wait. Did I say Perfect? It works as long as I use mouse to change the selected row, including selecting below the last row in table which removes selection and any button in previous selected row. However, when I use the keyboard Up/Down keys to change the selection, it does not work.
First I thought the function will get called only if I use mouse to change row selection. However, that's not true. That's true for tableViewSelectionIsChanging as per docs and as per facts. But for tableViewSelectionDidChange docs don't say it will only work when mouse is used and the facts bear that out. I put print statements and function does get called. I stepped through debugger as well. The mind boggling part is - the method to remove button from superview works, but the one to add button as subview does not work - and only if I use keyboard. How is it possible that the same exact code executes but I get two different outcomes?
Adding remaining functions
I use this to get selected row
private func rowView(_ rowIndex: Int, _ make: Bool = false) -> NSTableRowView? {
return tableView.rowView(atRow: rowIndex, makeIfNecessary: make)
}
I call this in viewDidLoad to create my orphan button
private func createButton() {
btnSave = NSButton(frame: NSRect(x: 10, y: 0, width: 22, height: 16))
btnSave?.title = "S"
btnSave?.setButtonType(.momentaryPushIn)
btnSave?.bezelStyle = .roundRect
}

Load data in new view when button is clicked with swift

I am developing an app, where I create buttons programmatically. When I click a button, it will request data from a database and show it in another view.
I use button.tag to determine what data to request, and I can only get the tag once the button is clicked.
However when I click the button, it shows nothing the first time. I must click it again to see the data which I want.
override func viewDidLoad() {
super.viewDidLoad()
//parseJSON(tagId)
createButton()
// Do any additional setup after loading the view, typically from a nib.
}
func createButton(){
var j:CGFloat=60
for var i:Int = 0 ; i < myImages.count;i = i+1 {
let myButton = UIButton()
myButton.setImage(UIImage(named: "carasusto.jpg"), forState: UIControlState.Normal)
myButton.setTitleColor(UIColor.blueColor(), forState: .Normal)
myButton.frame = CGRectMake(j, j+60, 50, 50)
myButton.tag = i //assign a tag to every button
myButton.addTarget(self, action: "segueToCreate:", forControlEvents: UIControlEvents.TouchUpInside)
self.view.addSubview(myButton)
j=j+60
print(myImages[i])
}
}
and
#IBAction func segueToCreate(sender: UIButton){
tagId = String(sender.tag)//tagId needs to fetch the information
parseJSON(tagId)
performSegueWithIdentifier("segueToView", sender:self)
}
func parseJSON(tagID:String){
Alamofire.request(.GET, "http://smarttags-001-site1.btempurl.com/SmartTagsRequests.aspx", parameters: ["AjaxFunc":"GetTagAttr","TagID":"\(tagID)"]).validate().responseJSON{ response in
switch response.result{
case .Success:
if let value = response.result.value {
let json = JSON(value)
print("JSON: \(json)")
self.TagName = json[0]["TagName"].stringValue
NSLog("\(self.TagName)")
self.ContentTitle = json[0]["ContentTitle"].stringValue
NSLog("\(self.ContentTitle)")
}
case .Failure(let error):
print(error)
}enter code here
}
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
var ViewTest : ViewTwo = segue.destinationViewController as! ViewTwo
var TagNameLabel = UILabel()
TagNameLabel.frame = CGRectMake(74, 112, 182, 64)
ViewTest.view.addSubview(TagNameLabel)
TagNameLabel.text = TagName
var ContentTitleLabel = UILabel()
ContentTitleLabel.frame = CGRectMake(74, 180, 182, 64)
ViewTest.view.addSubview(ContentTitleLabel)
ContentTitleLabel.text = ContentTitle
}
}
To follow up to MirekE's answer, here are some other steps you may want to consider:
Consider using Auto Layout in place of hard-coded frames, so your UI would adapt to different size classes.
Consider alternate approaches for showing an interactive list (of images) instead of programmatically adding buttons. For example, you could use a prototype (table view or collection view) cell. Cells are selectable and can take the place of a button. Other benefits include:
A scrollable container, should you have more buttons than would fit on screen.
A single segue (or selection) is handled by the storyboard prototype cell, instead of needing to make each programmatic "button" perform a segue (or action). Since you'd know which cell was selected, you'd no longer need a tag to figure that out.
Consider passing parameters to your destination view controller, instead of trying to instantiate and create controls in prepareForSegue. The destination's view is not loaded at that point.
Consider allowing the UI to feel more responsive, such as by performing the segue and showing placeholder details which you can then update once the network request completes. Otherwise, the user may have to wait for the network response before the segue occurs (which might make them think nothing happened and needlessly tap again, leading to an additional network request).
In general, Apple (or someone else) has already provided some way to do what you want, ideally leading to less code that you have to write, debug, test, and maintain to accomplish what you want your app to do.
Most likely cause of the problem is your call to parseJson followed by prepareForSegue. parseJson is asynchronous and you don't get data back from your service before prepareForSegue is called. As a first step, move the prepareForSegue to the completion block of the parseJson.

How to add to an array when button is pressed?

I've got custom buttons on a custom tableview cell, when button is pressed the image changes to checked/unchecked (see code below).
Issues is: How do I add the cell row data thats checked to an array that will be its own table (eg. a table with only checked data).
#IBAction func tickAction(sender: UIButton) {
println("SSSS")
if (sender.selected) {
sender.setImage(UIImage(named:"Unchecked.png"), forState: .Normal)
sender.selected = false
}
else {
sender.setImage(UIImage(named:"Checked.png"), forState: .Normal)
sender.selected = true
}
}
A solution would be to extend UITableViewCell into your own class that holds the other data or holds a reference to a model that holds the data.
Ideally, the view controller should hold the models and should get notified by a view that the action took place to act accordingly. The view controller should then add the data to the other array.