I am attempting to use the Darkseal Downpicker inside a UITableView. I am programatically adding a UITextField and then adding the Downpicker as follows:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
var textField = UITextField()
let cell = UITableViewCell(style: .default, reuseIdentifier: nil)
cell.selectionStyle = .none
textField.text = "TEST"
textField.frame = CGRect(x: CGFloat(0), y: CGFloat(0), width: CGFloat(170), height: CGFloat(30))
var dp: DownPicker!
let test1 = ["test one", "test two"]
dp = DownPicker(textField: textField, withData: test1)
cell.contentView.addSubview(dp)
return cell
}
If I just add the textfield:
cell.contentView.addSubview(textField)
Then it displays the text field. However if I add the DownPicker as shown above:
cell.contentView.addSubview(dp)
I get nothing displayed, just an empty tableview. Any help understanding why the DownPicker is not displayed would be appreciated. Thanks.
You need to add both ur UITextField and ur DownPicker into the View. If it's anything like the UIPickerView then your DownPicker will only show when you select the UITextField. Also you need to add your DownPicker to the view rather then the cell.
view.addSubView(dp)
EDIT
"It takes any UITextField already present in your code (including those added to a Storyboard):" - https://github.com/Darkseal/DownPicker
EDIT 2
From looking at the docs what you want to do is add yourself as the observer on the DataPicker by doing the following inside the cellForRowAt func
dp.addTarget(self, action: #selector(dp_selected(sender:)), for: .valueChanged)
You want to add a func the class with cellForRowAt func inside it
func dp_selected(sender: AnyObject) {
guard let dp = sender as? DropDown else { return }
if let textfield = dp.getTextField() as? UITextField {
guard let indexPath = tableView.indexPath(for: textfield.superview) else { return }
}
}
This function will check if the sender is of type DropDown class and if it is will try to get the UITextField that it's attached to and if that is returned it will attemt to get the IndexPathat which it's being used at this can be nil if the cell is no longer visible on the screen but hopefully that will never be the case and have added a check to make sure it exists.
Related
I am trying to have a UICollectionView that holds different UIViews as its cells. Is this possible or do I have to make them UICollectionViewCells?
I don't have an objective-c example, but you should be able to get the concept from the code example below.
An example how you can create a cell that wraps a UIView and is more reusable
class ProfileView: UIView {
var imageView: UIImageView!
var name: UILabel!
}
class ProfileCollectionViewCell: UICollectionViewCell {
let profileView = ProfileView()
init() {
super.init()
configureConstraints()
}
func configureConstraints() {
// use a handy extension you've already built
contentView.addSubView(profileView)
profileView.pinToEdges(of: contentView)
}
}
func collectionView(_ collectionView: UICollectionView,
cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let row = self.objects[indexPath.row]
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "someId" for: indexPath) as? ProfileCollectionViewCell
cell?.profileView.imageView.image = row["image"]
cell?.profileView.name.text = row["name"]
return cell
}
note: you may need to manage 'resetting the cells state' before it gets reused with something like:
override prepareForReuse() {
super.prepareForReuse()
profileView.imageView.image = nil
profileView.name.text = ""
}
You have to return UICollectionViewCells. UICollectionView don't accept UIViews.
What you can do is create a generic UICollectionViewCell that can embed any UIView.
The reason is because collection view cells have specific composition for layout and recycling.
Also, you add child in your UIView directly on the view itself, collection view cells have a contentView, like UITableViewCells.
I have a CollectionViewCell and i am working on cellForItemAt method of it. I have a button in each Collection view cell which defines to 3 different section in my CollectionView.
I am adding below code to set the button target:
cell.buttonView.addTarget(self, action: #selector(buttonPressed(sender:)), for: UIControlEvents.touchUpInside)
Now, i have created a new method: #objc func buttonPressed(sender: UIButton) where i am adding a title to the UIAlertController like:
let alertController = UIAlertController(title: , message: "Below actions are", preferredStyle: .actionSheet)
So basically, each time any button is tapped in the cell, the Alert should open and also each time the title will be different for it.
How do i pass the title here dynamically?
If the title to be passed is button's title, then you can simply do this :-
#objc func buttonPressed(sender: UIButton){
let title = sender.title(for: .normal)
}
And if it is some other data in section, you can use tags on your buttons, and setting them to indexPath.row :-
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
cell.buttonView.tag = indexPath.row
}
And in your Button's action, access button's tag
#objc func buttonPressed(sender: UIButton){
let objectIndex = sender.tag
let object = yourArray[objectIndex]
let title = object.title
}
I have a UITableView that allows multiple selections. I'd like to pass the selections to the next "Q2ViewController" when user clicks the rightBarButtonItem "Next".
Note: I'm not using Storyboard. After searching through, I haven't found a solution without using storybaord.
var options = ["breakfast", "lunch", "dinner", "dessert"]
var selected = -1
override func viewDidLoad() {
super.viewDidLoad()
self.title = "Q1View"
self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Next", style: .Done, target: self, action: "didTapNext:")
self.tableView.allowsMultipleSelection = true
var nib = UINib(nibName: "OptionCell", bundle: nil)
tableView?.registerNib(nib, forCellReuseIdentifier: "OptionCellIdentifier")
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.options.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCellWithIdentifier("OptionCellIdentifier", forIndexPath: indexPath) as OptionCell
cell.textLabel?.text = self.options[indexPath.row]
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
println("You selected cell #\(indexPath.row)!")
}
}
Anywhere in your code you must create the "next" view controller. Either in your App Delegate or directly in the view controller shown above.
If you create the view controller outside the above one you will have to pass the above controller a reference to the destination view controller.
If you create the view controller inside the above one save a reference to it in an instance variable.
Or create a method that creates the VC on pressing the "Next" button and pushes the VC to the navigation controller.
You can use UITableView's indexPathsForSelectedRows() or similar to get the selection and then call a method/set a instance variable on the destination view controller.
But seriously, why don't you use storyboards?
I have a UITableView with edit mode enabled in my -viewDidLoad method. My problem is that I don't need the three-line 'move' symbol on the right of each cell.
[tableview setEditing:YES];
tableview.allowsSelectionDuringEditing=YES;
I need to either have a transparent disclosure button, or hide the disclosure button altogether. I have tried:
cell.editingAccessoryType = UITableViewCellAccessoryNone;
But this has no effect. Can anybody help me with this?
You can do that in your cell subclass using the below method. I don't think it will work as-is , you need to amend it. But this should be your lead.
- (void)willTransitionToState:(UITableViewCellStateMask)state {
[super willTransitionToState:state];
//check whether you need it.
if ((state & UITableViewCellStateShowingEditControlMask) == UITableViewCellStateDefaultMask) {
for (UIView *subview in self.subviews) {
//check for reorder control. it checks for delete button.
if ([NSStringFromClass([subview class]) isEqualToString:#"UITableViewCellDeleteConfirmationControl"]) {
subview.hidden = YES;
subview.alpha = 0.0;
}
}
}
}
Modify tableView(_:canMoveRowAt) and return false, this is an UITableViewDataSource method.
func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
return false
}
How do you get the row for a button in a view based table when you click the button? The row is not selected when the button is clicked, but I found that if you log sender.superview.superview in the button's action method, I get: NSTableRowView: 0x1001b3a90 - row: 2. So, the row is there in the log, but I don't know how to get at it programmatically. I have the button's action method in a subclass of NSTableCellView.
-[NSTableView rowForView:] says this in its documentation:
This is typically needed in the action method for an NSButton (or NSControl) to find out what row (and column) the action should be performed on.
In Swift 5.1 -
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
if let checkBoxCell = tableView.makeView(withIdentifier:NSUserInterfaceItemIdentifier(rawValue: "<ColumnIdentifier>"), owner: self) as! NSButton? {
checkBoxCell.tag = row;
checkBoxCell.target = self;
checkBoxCell.action = #selector(TableViewService.checkBoxAction)
return checkBoxCell
}
return nil
}
#objc func checkBoxAction(button:NSButton){
print(button.tag);
}
Here I'm giving you a simple example. In this I'm adding a UIButton in content view. When I clicked on button I call a Method and there I get Row number and call as I required
//Adding a button
UIButton *btnBuyer=[UIButton buttonWithType:UIButtonTypeCustom];
btnBuyer.frame=CGRectMake(238, 10, 26, 32);
btnBuyer.tag=indexPath.row;
[btnBuyer setImage:[UIImage imageNamed:#"buyIcon.png"] forState:UIControlStateNormal];
[btnBuyer addTarget:self action:#selector(goBuyTab:)forControlEvents:UIControlEventTouchUpInside];
[cellNew.contentView addSubview:btnBuyer];
And When User Clicks on this I got Id from the following method
-(void)goBuyTab:(UIButton *)sender{
NSLog(#"after click buy button function called goBuyTab");
NSLog(#"sender.tag in goBuyTab : %d",sender.tag);
int selectedRow=sender.tag;// This is row number
}
Hope this is what you required.
I share this code for Swift 4.
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
........
but.action = #selector(ViewController.buttonAction)
.........
}
#objc func buttonAction(but: NSButton){
let tablerow: NSTableRowView = but.superview?.superview as! NSTableRowView;
let index = table?.row(for: tablerow);
print("\(index));
}
in osx you can use this in your button cell action method in the controller:
- (IBAction)yourMethod:(NSButtonCell *)sender {
NSInteger selected = [yourTableView selectedRow];
NSLog(#"sender sends :%ld", selected);
}
you need to set an outlet from the controller to the NSTableView.