Populating UIPickerView with CoreData attribute -- Swift4 IOS11 - ios

I have tried so much what I found here on StackOverflow like this, but nothing worked for me… I would like to use the Values from a Core Data Attribute for a PickerView.
My Entity is called "Task" with the Attribute "name".
I know I need to fetch the data and I already did that, but I don’t know how to just get the values of my Attribute as an Array.
At the moment I use A UIPickerView like this:
var var1 = [""]
let var2 = ["---","1","2","3","4","5","6","7"]
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if(component==0){
return var1[row]
}
return var2[row]
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if(component==0){
return var1.count
}
return var2.count
}
public func numberOfComponents(in pickerView: UIPickerView) -> Int{
return 2
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if(component==0){
test1 = var1[row]
}
test2 = var2[row]
}
This is how I fetch my Data for an UITableView:
// GetData
func getData() {
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
do {
tasks = try context.fetch(Task.fetchRequest())
}
catch{
print("Fetching Failed")
}
}
So I hope someone can help me, fetching the right attribute. I'm really new to Swift/Programming I started with swift 3 Days ago.. so a little code example would be great for me to understand how it works... Thanks in advance
EDIT: (How I populate the data in table view)
var tasks : [Task] = []
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
let task = tasks[indexPath.row]
cell.textLabel?.text = task.name
return cell
}
Update:
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> Task {
return tasks[row]
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return tasks.count
}
public func numberOfComponents(in pickerView: UIPickerView) -> Int{
return 1
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
test1 = tasks[row]
}

Related

Multiple pickerviews in single viewController

Is it possible to have a single pickerView in swift which changes its value based on the button pressed. I could not figure out a way to implement more than one parameter through pickerView in a single ViewController. An alternative solution like a dropdown menu is fine too. Example/functional code would be great if provided. This is for a quiz app which would take multiple parameters.
class ViewController: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate {
#IBOutlet weak var pickerView: UIPickerView!
#IBOutlet weak var selectionBtn: UIButton!
let animals = ["Lion", "Dog", "Monkey", "Cat", "Bat"]
override func viewDidLoad() {
pickerView.isHidden = true
pickerView.delegate = self
pickerView.dataSource = self
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
#IBAction func selectPressed(_ sender: UIButton) {
if pickerView.isHidden {
pickerView.isHidden = false
}
}
public func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
public func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return animals.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return animals[row]
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
selectionBtn.setTitle(animals[row], for: .normal)
pickerView.isHidden = true
}
}
Yes by having more than 1 data source
let animals1 = ["Lion", "Dog", "Monkey", "Cat", "Bat"]
let animals2 = ["Lion", "Dog", "Monkey", "Cat", "Bat"]
var mainData = [String]()
public func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
public func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return mainData.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, fo rComponent component: Int) -> String? {
return mainData[row]
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
selectionBtn.setTitle(mainData[row], for: .normal)
pickerView.isHidden = true
}
assign mainData to say animal1
and reload
pickerView.reloadAllComponents()
Keep a separate array and put your array into it according to your logic. Use that array in pickerview. Try This:
let animals = ["Lion", "Dog", "Monkey", "Cat", "Bat"]
let secondAnimals = ["Lion1", "Dog1", "Monkey1", "Cat1", "Bat1"]
let pickerArray = [String]()
#IBAction func selectPressed(_ sender: UIButton) {
pickerArray = animals //change it according to your logic
pickerView.reloadAllComponents()
pickerView.isHidden = !pickerView.isHidden
}
public func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return pickerArray.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return pickerArray[row]
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
selectionBtn.setTitle(pickerArray[row], for: .normal)
pickerView.isHidden = true
}
You can have two arrays to populate the picker like this
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int{
if numb == 1
{
return firstArray.count
}
else
return secondArray.count
}
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if numb == 1
{
return firstArr[row]
}
else
{
return secondArr[row]
}
}
Whenever you have to change the data source for datepicker, make sure after that you are calling method
picker.reloadAllComponents()
Take flag and use appropriate data source.
let say you added 2 PickerView to your View
- set the 1st picker´s tag as 1 & 2 for the 2nd picker under the Attributes Inspector
- CTRL + drag from each picker to the top yellow View Controller icon and choose dataSource.Repeate the same choosing delegate
- repeate the above for the other picker too
- add pickerview & pickerviewdelegation to your ViewController class:
class ViewController: UIViewController,UIPickerViewDataSource,UIPickerViewDelegate {
in your ViewController class, create empty arrays for the pickers:
var picker1Options = []
var picker2Options = []
on viewDidLoad() method, populate the arrays with your content:
picker1Options = ["p1 1","p1 2","p1 3","p1 4","p1 5"]
picker2Options = ["p2 1","p2 2","p2 3","p2 4","p2 5"]
implement the delegate & pickerview methods:
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if (pickerView.tag == 1){
return picker1Options.count
}else{
return picker2Options.count
}
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! {
if (pickerView.tag == 1){
return "\(picker1Options[row])"
}else{
return "\(picker2Options[row])"
}
}
Hope this will help.
let arrAny : [String] = [String]()
button action:
#IBAction func btn2Pressed(_ sender: UIButton) {
arrAny = ["Lion1", "Dog1", "Monkey1", "Cat1", "Bat1"]
if pickerView.isHidden {
pickerView.isHidden = false
}
}
#IBAction func btn1Pressed(_ sender: UIButton) {
arrAny = ["Lion", "Dog", "Monkey", "Cat", "Bat"]
if pickerView.isHidden {
pickerView.isHidden = false
}
}
pickerView delegate:
public func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
public func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return arrAny.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return arrAny[row]
}

I can't add a UIPickerview for gender in a registration form

I am creating a registration form and I have to include the gender inside a text field using a picker view. However, I am getting question marks instead of male and female.
Here is my code:
#IBOutlet weak var genderfield: UITextField!
let pickerView = UIPickerView()
let gender1 = ["Male", "Female"]
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return gender1.count
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return gender1[row]
}
func pickerView(_ pickerView:UIPickerView,didSelectRow row: Int,forComponent component: Int){
genderfield.text = gender1[row]
genderfield.resignFirstResponder()
}
And in ViewDidLoad:
pickerView.delegate = self
pickerView.dataSource = self
genderfield.inputView = pickerView
I don't think there is something wrong in my code. I have been googling for hours.
You get question marks because you have the wrong signature on your titleForRow delegate method.
Change:
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return gender1[row]
}
to:
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return gender1[row]
}
Note the addition of _ just after the (.
You can not added UIPickerViewDelegate, UIPickerViewDataSource.
so when you add delegate and data source of picker view its work fine.
like this:
extension RegisterVC : UIPickerViewDelegate, UIPickerViewDataSource{
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return gender1.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return gender1[row]
}
func pickerView(_ pickerView:UIPickerView,didSelectRow row: Int,inComponent component: Int){
genderfield.text = gender1[row]
genderfield.resignFirstResponder()
}

How put a custom view on a selected row for an uipickerview rxswift?

I use Pickerview with Rx and i would like to know how you can change view of the selected row with a custom view. i tried on a picker view without RX it works. But the same with Rx and Custom Adapter don't work. Do you have an idea to do this ?
Thanks for your answers :
For example without Rxswift :
func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView {
let customView = LimitItemPickerView(frame: CGRect.zero)
if pickerView.selectedRow(inComponent: component) == row {
customView.selected()
}
return customView
}
My implementation :
final class `PickerViewViewAdapter: NSObject, UIPickerViewDataSource, UIPickerViewDelegate, RxPickerViewDataSourceType, SectionedViewDataSourceType {
typealias Element = [MyMODEL]
private var items: [MyMODEL] = []
func model(at indexPath: IndexPath) throws -> Any {
return items[indexPath.row]
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return items.count
}
func pickerView(_ pickerView: UIPickerView, rowHeightForComponent component: Int) -> CGFloat {
return 80.0
}
func pickerView(_ pickerView: UIPickerView, viewForRow row: Int, forComponent component: Int, reusing view: UIView?) -> UIView {
let customView = MyCustomView(frame: CGRect.zero, model: items[row])
return customView
}
func pickerView(_ pickerView: UIPickerView, observedEvent: Event<Element>) {
UIBindingObserver(UIElement: self) { (adapter, items) in
adapter.items = items
pickerView.reloadAllComponents()
}.on(observedEvent)
}
}`
To use this :
let input = MYVIEWMODEL.Input(param1: key,
param2: key2,
param3: key3)
let output = myViewModel.transform(input: input)
output.limitsAvailable
.drive(limitPickerView.rx.items(adapter: PickerViewViewAdapter()))
.disposed(by: disposeBag)

UIPickerView depending on first component

So I have a UIPickerView with two components. The first one called "Cupboards", the second "Drawer". They have a one to many relationships in CoreData Cupboards <-->> Drawer. I would like that if I select a Cupboard, only the matching Drawers get displayed. I'm not sure how to get that working with the relationship.
That's what I have for showing the Cupboard:
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 2
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if(component==0){
return cupboards.count
}
xxxx
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if(component==0){
return cupboards[row].name
}
xxxx
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if(component==0){
}
}
Thank you in advance
Update:
Got it like that now, but I get no results.
var cupboardDrawers = [Drawer]()
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if(component==0){
let request: NSFetchRequest<Drawer> = Drawer.fetchRequest()
request.predicate = NSPredicate(format: "cupboard == %#", cupboards[row].name!)
do{
let result = try mgdContext.fetch(request)
cupboardDrawers = result
addEatDataPicker.reloadAllComponents()
}catch{
print(error.localizedDescription)
}
}
}
You need to create and update a cupboardDrawers array with the fetching results:
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 2
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if(component==0){
return cupboards.count
} else {
return cupboardDrawers.count
}
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if(component==0){
return cupboards[row].name
} else {
return cupboardDrawers[row].yourProperty
}
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if(component==0){
// you can add this part to a separate function and call it here
cupboardDrawers = []
let request = NSFetchRequest<Drawer>(entityName:”Drawer”)
request.predicate = YourPredicate with cupboards[row].name
do {
let items = context.fetch(request)
guard items.count > 0 else {
print(“no items found”)
return
}
cupboardDrawers = items
//reload your picker
} catch {
print(error)
}
}
}

Populate UIPickerView with items from class

I have the following class:
class JobItem {
var ItemID:String = String()
var Qty:Int = Int()
var Item:String = String()
}
I also have a collection of items in this class like so:
var jobitems: [JobItem] = []
I would like to populate my pickerview with just the Item part from each instance of the class in the array and I'm not sure how. I successfully filled it with data from a dummy array I created so it's working OK, just need that data in.
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return jobitems.count
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return as? String
}
Try this in your titleForRow, you just need to return the correct Item string with the correct row that can mapped to index of your array:
return jobitems[row].Item
Just takeout element from array to your instance class & populate what you wants,
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String {
var titleFoRow: String? = nil
var classObject: ModelClass? = nil
classObject = self.arrayCountryList[row]
self.titleFoRow = classObject.instanceVarName
return self.titleFoRow
}

Resources