UIPickerView only populates with "?" - ios

So I'm trying to populate my two pickerViews from arrays, but only coming up with "?" I've tried some of the fixes for similar types on here but none of them have worked.
#IBOutlet var startPickerView: UIPickerView!
#IBOutlet var endPickerView: UIPickerView!
var startPickerData: [Int] = []
var endPickerData: [Int] = []
let startArray = (1...999).map { $0 }
let endArray = (2...1000).map { $0 }
let startPickerCellIndexPath = IndexPath(row: 1, section: 1)
let endPickerCellIndexPath = IndexPath(row: 1, section: 2)
var isStartPickerShown: Bool = false {
didSet {
startPickerView.isHidden = !isStartPickerShown
}
}
var isEndPickerShown: Bool = false {
didSet {
endPickerView.isHidden = !isEndPickerShown
}
}
override func viewDidLoad() {
super.viewDidLoad()
self.startPickerView.delegate = self
self.startPickerView.dataSource = self
self.endPickerView.delegate = self
self.endPickerView.dataSource = self
startPickerData = startArray
endPickerData = endArray
self.startPickerView.reloadAllComponents()
self.endPickerView.reloadAllComponents()
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 2
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return 1
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
switch indexPath {
case startPickerCellIndexPath:
if isStartPickerShown {
return 216.0
} else {
return 0.0
}
case endPickerCellIndexPath:
if isEndPickerShown {
return 216.0
} else {
return 0.0
}
default:
return 44.0
}
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
switch indexPath {
case startPickerCellIndexPath:
if isStartPickerShown {
isStartPickerShown = false
} else if isStartPickerShown {
isStartPickerShown = false
isStartPickerShown = true
} else {
isStartPickerShown = true
}
tableView.beginUpdates()
tableView.endUpdates()
case endPickerCellIndexPath:
if isEndPickerShown {
isEndPickerShown = false
} else if isEndPickerShown {
isEndPickerShown = false
isEndPickerShown = true
} else {
isEndPickerShown = true
}
tableView.beginUpdates()
tableView.endUpdates()
default:
break
}
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
// The number of rows of data
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
if pickerView.tag == 1 {
return startPickerData.count
} else {
return endPickerData.count
}
}
// The data to return fopr the row and component (column) that's being passed in
private func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> Int? {
let startView: Int = startPickerData[row]
let endView: Int = endPickerData[row]
if pickerView.tag == 1 {
return startView
} else {
return endView
}
}
}
I've been working on this for a day and a half and haven't been able to figure out why it won't work and I've already tried several fixes from here.

You need to change your private method at the very bottom to this:
// The data to return fopr the row and component (column) that's being passed in
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
let startView: Int = startPickerData[row]
let endView: Int = endPickerData[row]
if pickerView.tag == 1 {
return String(format: "%d", startView)
} else {
return String(format: "%d", endView)
}
}

Related

How to compare values of two different UIPickerView?

I have custom UITableViewController with two custom UITableViewCell
Each of them contains UIPickerView
I want to compare values of these UIPickerViews
(I make the Maps App, and i wanna make the route, so i need do compare two points, and if they are different then "Make The Route" button will be set to Enabled State)
How can i do this? I tried to use didSet values, but it didn't work
Here are my classes:
class PlaceForRouteCell: UITableViewCell, UIPickerViewDelegate, UIPickerViewDataSource {
#IBOutlet weak var picker: UIPickerView!
// Выбираем все места в базе данных
let places = realm.objects(Place.self)
var selectedPlace = Place()
func getSelectedPlace() -> Place {
return selectedPlace
}
//число "барабанов"
func numberOfComponents(in pickerView: UIPickerView) -> Int { return 1 }
//число элементов в "барабане"
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
//если БД пуста, то предупредить об этом
return places.count != 0 ? places.count : 1
}
//содержимое "барабанов"
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
if (places.count != 0) {
if (places.count == 1) { return "Добавьте еще одно место" }
return places[row].userName
}
return "Сохраненных мест нет"
}
//обрабатываем выбранный элемент
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if (places.count != 0) {
print(picker.tag)
selectedPlace = places[row]
// print("выделена строка №\(row), элемент \(places[row])'")
}
}
func setup() { picker.delegate = self }
}
And
class TableForRouteViewController: UIViewController, UITableViewDataSource, UIPickerViewDelegate{
// Выбираем все места в базе данных
let places = realm.objects(Place.self)
#IBOutlet weak var makeTheRouteButton: UIBarButtonItem!
#IBOutlet var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.tableFooterView = UIView(frame: CGRect(x: 0, y: 0,
width: tableView.frame.size.width, height: 1))
tableView.dataSource = self
let cell = tableView.cellForRow(at: IndexPath(row: 0, section: 1)) as! PlaceForRouteCell
cell.picker.selectRow(1, inComponent: 0, animated: true)
var cellA = tableView.cellForRow(at: IndexPath(row: 0, section: 0)) as! PlaceForRouteCell {
didSet {
print("первая ячейка изменилось")
}
}
var cellB = tableView.cellForRow(at: IndexPath(row: 0, section: 1)) as! PlaceForRouteCell
// print("tag of A: \(cellA.picker)")
// print("tag of B: \(cellB.picker.tag)")
var valueOfA = cellA.getSelectedPlace() {
didSet {
print("значение в первой ячейке изменилось")
}
}
print(valueOfA.userName)
var valueOfB = cellB.getSelectedPlace() {
didSet {
print("значение в первой ячейке изменилось")
}
}
print(valueOfB.userName)
if (places.count < 2 ) { makeTheRouteButton.isEnabled = false }
}
#IBAction func makeTheRouteButtonPressed(_ sender: UIBarButtonItem) {
let cellA = tableView.cellForRow(at: IndexPath(row: 0, section: 0)) as! PlaceForRouteCell
let pointA = cellA.selectedPlace
let cellB = tableView.cellForRow(at: IndexPath(row: 0, section: 1)) as! PlaceForRouteCell
let pointB = cellB.selectedPlace
print("point A: \(pointA.userName), point B: \(pointB.userName)")
}
// var arePlacesEqual : Bool = comparing() {
// didSet {
// print("значения поменялись")
// }
// }
func comparing() -> Bool {
let cellA = tableView.cellForRow(at: IndexPath(row: 0, section: 0)) as! PlaceForRouteCell
let cellB = tableView.cellForRow(at: IndexPath(row: 0, section: 1)) as! PlaceForRouteCell
let valueOfA = cellA.selectedPlace.userName
let valueOfB = cellB.selectedPlace.userName
if (valueOfA == valueOfB) { return true }
return false
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return 1 }
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "placeForRouteCell", for: indexPath) as! PlaceForRouteCell
cell.picker.tag = indexPath[0]
cell.setup()
return cell
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
switch(section) {
case 0:return "Точка А"
case 1:return "Точка Б"
default :return ""
}
}
// количество секциий
func numberOfSections(in tableView: UITableView) -> Int { return 2 }
}
I created tableView with pickerView in cell.
In didSelectRow method i added NotificationCenter sender
My tableViewCell class:
let picker_array = ["one", "two", "three"]
class TableViewCell: UITableViewCell, UIPickerViewDelegate, UIPickerViewDataSource {
#IBOutlet weak var picker: UIPickerView!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
self.picker.delegate = self
self.picker.dataSource = self
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return picker_array.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return "\(picker_array[row])"
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
NotificationCenter.default.post(name: Notification.Name("Notification"), object: nil)
}
}
In viewDidLoad i added NotificationCenter listener.
My ViewController class:
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tableView: UITableView!
let dummy_data = [1,2]
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(methodOfReceivedNotification(notification:)), name: Notification.Name("Notification"), object: nil)
}
#objc func methodOfReceivedNotification(notification: Notification) {
for index in dummy_data {
let indexPath = IndexPath(row: index - 1, section: 0)
let cell = tableView.cellForRow(at: indexPath) as! TableViewCell
let selectRow = picker_array[cell.picker.selectedRow(inComponent: 0)]
print(selectRow)
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dummy_data.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! TableViewCell
return cell
}
}
When i change pickerView, console print current value from cells
I think it will help

PickerView not getting the updated value from Array

First of all please correct my topic subject or suggest an edit for the taggin in case if I mentioned somthing wrong.
I'm working on a store App project and I stuck in the selecting subSection VC because of the UIPickerView not getting the updated value from the array of target!
Here below is my code
class SelectSectionVC : UIViewController, UITextFieldDelegate {
var delegate : SelectSectionDelegate!
var staticVariable = SelectionCell.shared
override func viewDidLoad() {
super.viewDidLoad()
getSection()
setupCell()
self.pickertextField.alpha = 0
self.DoneBtn.isHidden = true
self.pickerView.isHidden = true
pickertextField.addTarget(self, action: #selector(textField_CatchedData(_:)), for: .editingDidEnd )
}
#IBOutlet weak var CollectionView: UICollectionView!
#IBOutlet weak var pickerView: UIPickerView!{
didSet{ pickerView.delegate = self ; pickerView.dataSource = self }}
var selectedSection : SectionsObject?
var sectionsArray : [SectionsObject] = []
func getSection(){
SectionsAPI.getAllsections { (section) in
self.sectionsArray.append(section)
DispatchQueue.main.async {
self.CollectionView.reloadData()
}
}
}
// Products type Arrays
var type_FP : [String] = ["FP1", "FP2"]
var type_TP : [String] = ["TP1", "TP2"]
var type_JW = ["Rings", "Necklace", "Collar", "Bracelet", "Earring"]
var type_ACS = ["Hair Wrap", "Ring", "Strap", "Sunglasses", "Crown"]
var type_LP = ["Waist belt", "Wallet", "Handbag", "Suitcase", "Face Mask"]
var type_Watches = ["classic", "Leather", "Smart", "Digital"]
var generatedTypes : [String] = [] { didSet{print("# Types updated ==> ( \(generatedTypes) )")} }
func updateTypesarray(){
if selectedSection?.name == "Trending Products" {
self.generatedTypes = type_TP
}
else if selectedSection?.name == "Accessories" {
self.generatedTypes = type_ACS
}
else if selectedSection?.name == "Featured Products" {
self.generatedTypes = type_FP
}
else if selectedSection?.name == "Watches" {
self.generatedTypes = type_Watches
}
else if selectedSection?.name == "Jewellery Products" {
self.generatedTypes = type_JW
}
else if selectedSection?.name == "Leather Products" {
self.generatedTypes = type_LP
}else { print("# ((Nothing Happaned!!))") }
}
#IBOutlet weak var pickertextField: UITextField!{
didSet{
pickertextField.inputView = UIView() //what a Magic!!!... This code solved Keyboard dismiss problem after assign the textField as FirstResponder!
pickertextField.delegate = self
pickertextField.allowsEditingTextAttributes = false
pickertextField.becomeFirstResponder()
}
}
#objc func textField_CatchedData(_ sender : UITextField) {
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "Type Name"), object: nil, userInfo: ["text" : sender.text!])
}
var productsList: [productObject] = []
var RecommendedArray: [String] = ["TH-1791721_side","Image-2","touq2","TH-1791349","watch2","eswara","Image-1",] //to be updated later!
}
extension SelectSectionVC : UICollectionViewDelegate, UICollectionViewDataSource,UICollectionViewDelegateFlowLayout {
func setupCell() {
CollectionView.delegate = self; CollectionView.dataSource = self
CollectionView.register(UINib(nibName: "SelectionCell", bundle: nil), forCellWithReuseIdentifier: "cell")
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: self.CollectionView.frame.size.width - 25, height: self.CollectionView.frame.size.height/4 - 0.5)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat { // make spacing between each cell
return 2
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
sectionsArray.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = CollectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! SelectionCell
cell.isSelected = false
pickertextField.text = "Select product type" // Reset text to "Select product type" when press new cell"
cell.sectionName.text = sectionsArray[indexPath.row].name
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print("# secArray Count = \(sectionsArray.count)")
self.selectedSection = sectionsArray[indexPath.row]
updateTypesarray()
print("# //Selected cell => TypesArray => \(generatedTypes)")
pickertextField.becomeFirstResponder()
}
}
The problem is: title & number Of Rows In Component are not getting the value from (generatedTypes) array after it get updated when cell did selected!
extension SelectSectionVC : UIPickerViewDelegate, UIPickerViewDataSource {
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return generatedTypes.count
}
func pickerView(_ pickerView: UIPickerView, attributedTitleForRow row: Int, forComponent component: Int) -> NSAttributedString? {
return NSAttributedString(string: self.generatedTypes[row], attributes: [NSAttributedString.Key.foregroundColor: UIColor.yellow])
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return generatedTypes[row]
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
self.pickertextField?.text = generatedTypes[row]
self.pickerView.isHidden = true
self.DoneBtn.isHidden = false
self.pickertextField.endEditing(true)
print("# pickerTextField... has ended editing!")
}
I did many many breakpoints and I'm sure that [generatedTypes] array has a value..but I don't know why it always called inside pickerView before ti get updated!
please help me
Thank you in advance
You may need to reload the picker end of updateTypesarray
func updateTypesarray(){
......
self.pickerView.reloadAllComponents()
}

Refresh pagination data in UITableView

I have implemented pagination in UITableView with WillDisplay method. Pagination process is working fine but if I need to reload a list on button click, then data is appending in the list. How to work around with this ?
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
if (indexPath.row + 1 == playlistViewModel.numberOfRowsInSection()) {
if playlistViewModel.isReload != false {
pageIncrement += 1
playlistViewModel.playListingApi(enterView: false, page: pageIncrement)
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
pageIncrement = 1
playlistViewModel.playListingApi(enterView: true, page: pageIncrement)
}
playlistViewModel.hitNextApiClosure = { [weak self] () in
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
self?.playlistViewModel.isReload = false
self?.playlistViewModel.playlistArray?.removeAll()
self?.playlistTableView.reloadData()
self?.pageIncrement = 1
self?.playlistViewModel.playListingApi(enterView: true, page: self?.pageIncrement ?? 1)
}
}
And ViewModel method is
func playListingApi(enterView: Bool, page: Int) {
self.isLoading = true
if (enterView){
playlistArray?.removeAll()
isReload = false
}
playlistService.getPlayList(page: "\(page)", limit: "20") { (result) in
self.isLoading = false
switch result {
case .success(let data):
self.playlist = data as? Playlist
guard let data = self.playlist?.data?.blocks else {
self.errorMessage = AlertMessage.somethingWentWrong
return
}
for playlistData in data {
self.playlistArray?.append(playlistData)
self.isReload = true
}
if (data.count == 0){
self.isReload = false
}
self.reloadTableBool = true
case .error(let message):
self.isReload = false
self.errorMessage = message
}
}
}
When you are reloading your tableView set page = 1 , empty tableView data source and reload tableView. Finally hitAPI for fresh set of data .
page = 1
mTblDataSource.removeAll()
mTableView.reloadData()
hitAPI()
Consider this one as a possible solution.
public class Pageable<T> {
public enum ObjectState {
case loading
case loaded
}
public private (set) var page: Int = 0
private var items: [T] = [T]()
private var state: ObjectState = .loading
private let itemsPerPage: Int
private var itemsReloaded: (() -> ())
public init(itemsPerPage: Int, items: [T] = [], itemsReloaded: #escaping (() -> ())) {
self.items = items
self.itemsPerPage = itemsPerPage
self.itemsReloaded = itemsReloaded
}
public var itemsCount: Int {
switch state {
case .loaded:
return items.count
case .loading:
return items.count + 1 // should be displaying cell with loading indicator
}
}
public var isLoaded: Bool {
return state == .loaded
}
public var isLoading: Bool {
return state == .loading
}
public func append(contentsOf items: [T]) {
state = items.count < itemsPerPage ? .loaded : .loading
self.items.append(contentsOf: items)
itemsReloaded()
}
public func incrementPage() {
page += 1
}
public func reset() {
page = 0
state = .loading
items = []
}
public func itemFor(_ index: Int) -> T? {
return items.indices.contains(index) ? items[index] : nil
}
}
struct Property {}
protocol SearchItemsDisplayLogic: class {
func reloadItemsViews()
}
protocol SearchItemsInteraction {
func loadMore(page: Int)
}
// MARK: View Related with UITableView example
lazy var refreshControl: UIRefreshControl = {
let refreshControl = UIRefreshControl()
refreshControl.addTarget(self, action: #selector(pullToRefresh(_:)), for: UIControl.Event.valueChanged)
return refreshControl
}()
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return presenter.itemsCount
}
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
presenter.viewWillDisplayCellAt(indexPath.row)
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if presenter.isLoadingCellNeeded(indexPath.row) {
return tableView.dequeueReusableCell(withIdentifier: "\(LoadingTableViewCell.self)", for: indexPath)
}
let cell = tableView.dequeueReusableCell(withIdentifier: "\(PropertyTableViewCell.self)", for: indexPath) as? PropertyTableViewCell
presenter.populate(cell: cell, indexPath: indexPath)
return cell ?? UITableViewCell(style: .default, reuseIdentifier: "\(UITableViewCell.self)")
}
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let property = presenter.property(indexPath.row) else {
return
}
}
protocol SearchItemsPresentation {
// MARK: Pagination logic
var itemsCount: Int { get }
// From the view.
func isLoadingCellNeeded(_ item: Int) -> Bool
func viewWillDisplayCellAt(_ item: Int)
func pullToRefresh()
func property(_ item: Int) -> Property?
// From the interactor.
func presentItems(items: [Property])
}
// MARK: - Presenter
class SearchItemsPresenter: SearchItemsPresentation {
weak var propertyDisplay: SearchItemsDisplayLogic?
lazy var interactor: SearchItemsInteraction? = {
return SearchItemsInteractor(presenter: self)
}()
var itemsCount: Int {
return pageable.itemsCount
}
private var pageable: Pageable<Property>!
init(viewController: SearchItemsDisplayLogic) {
self.propertyDisplay = viewController
pageable = Pageable(itemsPerPage: 15, itemsReloaded: {
self.propertyDisplay?.reloadItemsViews()
})
}
// TODO: presenter should not have UIKit!
func populate(cell: CellProtocol?, indexPath: IndexPath) {
guard let cell = cell else { return }
// populate
}
}
extension SearchItemsPresenter {
func property(_ index: Int) -> Property? {
return pageable.itemFor(index)
}
}
// MARK: Pageable
extension SearchItemsPresenter {
/// if it's loading show loading cell in the view.
func isLoadingCellNeeded(_ item: Int) -> Bool {
let isViewAtTheBottom = item == itemsCount - 1
return isViewAtTheBottom && pageable.isLoading
}
/// Called in `willDisplay` methods of the view.
func viewWillDisplayCellAt(_ item: Int) {
let isViewAtTheBottom = item == itemsCount - 1
if isViewAtTheBottom && pageable.isLoading {
interactor?.loadMore(page: pageable.page)
pageable.incrementPage()
}
}
func pullToRefresh() {
pageable.reset()
interactor?.loadMore(page: pageable.page)
pageable.incrementPage()
}
func presentItems(items: [Property]) {
pageable.append(contentsOf: items)
}
}
// MARK: - Interactor
class SearchItemsInteractor: SearchItemsInteraction {
private var presenter: SearchItemsPresentation
init(presenter: SearchItemsPresentation) {
self.presenter = presenter
}
func loadMore(page: Int) {
DispatchQueue.global(qos: .background).async {
sleep(1)
DispatchQueue.main.async {
// TODO: return some data
self.presenter.presentItems(items: [])
}
}
}
}

PickerView inside tableView cell

I have created a tableview which takes date difference and create that number of tableview cell, each table view cell consist of textview and and picker view against textview to pick value. The problem is when i pick value for the 1 position using PickerView then the selected value is also reflected on the other cell
code for the contorller
here hfDetailsArr contains total number of days difference
--function for getting date difference count {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd/MM/yyyy"
let currentCalendar = NSCalendar.current
dateFormatter.date(from: dateFormatter.string(from:date1 as Date))
let temp = currentCalendar.dateComponents([.day], from: dateFormatter.date(from: dateFormatter.string(from:date1 as Date))!, to: dateFormatter.date(from: dateFormatter.string(from:date2 as Date))!)
hfDetailsArr.removeAllObjects();
//print(temp.day!)
if !(temp.day! < 0) && (temp.day! != 0) {
for i in 0 ..< (temp.day! + 1){
let HFDetailsDates = currentCalendar.date(byAdding: .day, value: i, to: date1 as Date)
DataDetails = dateFormatter.string(from: HFDetailsDates!)
hfDetailsArr.add(DataDetails)
ApplyForDate.append( dateFormatter.string(from: HFDetailsDates!) + ",")
}
//print(ApplyForDate)
}
HFDEtailsTable.reloadData()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if hfDetailsArr.count < 0 && hfDetailsArr.count != 0 {
return 0
}else{
return hfDetailsArr.count
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell : HFDetailsCell! = tableView.dequeueReusableCell(withIdentifier: "cell") as! HFDetailsCell
cell.txtHFDateFeild.text = hfDetailsArr[indexPath.row] as? String
cell.cellDelegate = self
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("indeddsdsd \(indexPath.row)")
}
code for UITableview cell with pickerview inside it
protocol HFDetailsCellDelegate : class {
func ValueSelectedChage(sender:HFDetailsCell ,Id:String ,selectedCell:String)
}
class HFDetailsCell: UITableViewCell,UITextFieldDelegate,UIPickerViewDelegate,UIPickerViewDataSource{
#IBOutlet var txtHFPicker: UITextField!
#IBOutlet var txtHFDateFeild: UITextField!
#IBOutlet var pickerView: UIPickerView! = UIPickerView()
var HfDtailsOneArr = ["Select","Full Day Leave","Half Day Leave"]
var position = 0
//var intHFStatusDetail = ""
/// internal static var HFtableView = UITableView()
weak var cellDelegate: HFDetailsCellDelegate?
//var LeaveDataIDArr = [String?]()
override func awakeFromNib() {
txtHFDateFeild.delegate = self
pickerView.delegate = self
txtHFPicker.inputView = pickerView
pickerView.backgroundColor = UIColor.white
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
#IBAction func txtleaveType(_ sender: UITextField) {
}
//print("buttonclick")
// //UIpickerView
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
//Set number of rows in components
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return self.HfDtailsOneArr.count
}
//Set title for each row
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return HfDtailsOneArr[row]
}
// Update textfield text when row is selected
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
// self.cellDelegate?.ValueSelectedChage(sender:self, Id: HFDetailsLeaveCount(position: row), selectedCell: "")
txtHFPicker.text = HfDtailsOneArr[row]
print("pickerText:\(txtHFPicker.text!)")
}
func HFDetailsLeaveCount(position:Int)-> String {
switch position {
case 0:
return "0"
case 1:
return "8"
case 2:
return "4"
default:
return "nil"
}
}
}
in above image if i select value for date 04/08 then the same value is reflected for 12/08
-- any kind of help will be appreciated. Thank you
in table cell, on picker selection call ValueSelectedChage delegate method
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
self.cellDelegate?.ValueSelectedChage(sender:self, Id: HFDetailsLeaveCount(position: row), selectedCell: HfDtailsOneArr[row])
txtHFPicker.text = HfDtailsOneArr[row]
print("pickerText:\(txtHFPicker.text!)")
}
create a variable in viewcontroller to keep selected value
var hfSelectedDetails: [String: String?]?
in viewcontroller implement the delegate method
func ValueSelectedChage(sender:HFDetailsCell ,Id:String ,selectedCell:String) {
let indexpath = self.tableView.indexPathForRowAtPoint(cell.center)
let key = "\(indexpath.row)"
hfSelectedDetails[key] = selectedCell
....//other code if any
}
and in cellForRow add
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell : HFDetailsCell! = tableView.dequeueReusableCell(withIdentifier: "cell") as! HFDetailsCell
cell.txtHFDateFeild.text = hfDetailsArr[indexPath.row] as? String
cell.cellDelegate = self
let key = "\(indexPath.row)"
if let selectedValue = hfSelectedDetails[key] {
cell.txtHFPicker.text = selectedValue
} else {
cell.txtHFPicker.text = nil
}
return cell
}

Set the value of UIPickerView right after its data is loaded

I have developed something very similar to DateCell Demo from Apple. https://developer.apple.com/library/ios/samplecode/DateCell/Introduction/Intro.html
The only difference is that I have a UIPickerView instead of a UIDatePicker. And whenever the cell is touched a new UIPickerView is instantiated and added to the cell below once touched again it is removed from the cell. And the part I have problem with is to select a specific item in the UIPickerView.
Here is some code:
var selectedPlatform = "Mac"
var platformPickerDataSource = ["iOS", "Mac", "PC", "Android"]
func updatePlatformPicker()
{
if let indexPath = platformPickerIndexPath {
let associatedPlatformPickerCell = tableView.cellForRowAtIndexPath(indexPath)
if let targetedPlatformPicker = associatedPlatformPickerCell?.viewWithTag(Constants.kPlatformPickerTag) as! UIPickerView? {
targetedPlatformPicker.dataSource = self
targetedPlatformPicker.delegate = self
// I cannot do selectRow(selectedPlatform, inComponent: 0,
animated : true) here since the row since the rows in the UIPickerView are not set
}
}
}
So my questions is, if you refer to the code from Apple, where can I set?
selectRow(selectedPlatform, inComponent: 0,
animated : true)
Edit: (I added the whole code, which is basically the swift version of Apple's DateCell Example and DatePicker replaced with a UIPickerView)
import UIKit
class PickerTableViewController: UITableViewController, UIPickerViewDataSource, UIPickerViewDelegate {
var platformPickerIndexPath : NSIndexPath?
var pickerCellRowHeight: CGFloat = 140
var selectedPlatform = "Mac"
var platformPickerDataSource = ["iOS", "Mac", "PC", "Android"]
private struct Constants {
static let kPlatformCellID: String = "platformCell"
static let kPlatformPickerID: String = "platformPicker"
static let kOtherCell: String = "otherCell"
static let kPlatformRow : Int = 1
static let kPlatformPickerTag : Int = 99
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
var rows = 3
if hasInlinePlatformPicker()
{
rows = 4
}
return rows
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell : UITableViewCell?
print("\(indexPath.row)")
var cellID = Constants.kOtherCell
if indexPathHasPicker(indexPath)
{
cellID = Constants.kPlatformPickerID
}
else if indexPathHasPlatform(indexPath)
{
cellID = Constants.kPlatformCellID
}
cell = tableView.dequeueReusableCellWithIdentifier(cellID)
var modelRow = indexPath.row
if (platformPickerIndexPath != nil && platformPickerIndexPath?.row <= indexPath.row) {
modelRow -= 1
}
if cellID == Constants.kPlatformCellID
{
cell?.textLabel?.text = "Select a platform"
cell?.detailTextLabel?.text = selectedPlatform
}
else if cellID == Constants.kOtherCell
{
cell?.textLabel?.text = "Other Cell"
}
return cell!
}
func indexPathHasPicker(indexPath: NSIndexPath) -> Bool
{
return hasInlinePlatformPicker() && platformPickerIndexPath?.row == indexPath.row
}
func indexPathHasPlatform(indexPath : NSIndexPath) -> Bool
{
var hasPlatform = false
if indexPath.row == Constants.kPlatformRow || (hasInlinePlatformPicker() && (indexPath.row == Constants.kPlatformRow + 1))
{
hasPlatform = true
}
return hasPlatform
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let cell = tableView.cellForRowAtIndexPath(indexPath)
if cell?.reuseIdentifier == Constants.kPlatformCellID
{
displayInlinePlatformPickerForRowAtIndexPath(indexPath)
}
else
{
tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
}
func displayInlinePlatformPickerForRowAtIndexPath(indexPath : NSIndexPath)
{
// display the platform picker inline with the table content
tableView.beginUpdates()
var before = false
if hasInlinePlatformPicker()
{
before = platformPickerIndexPath?.row < indexPath.row
}
let sameCellClicked = (platformPickerIndexPath?.row == indexPath.row + 1)
// remove any picker cell if it exists
if hasInlinePlatformPicker()
{
tableView.deleteRowsAtIndexPaths([NSIndexPath(forRow: platformPickerIndexPath!.row, inSection: 0)], withRowAnimation: .Fade)
platformPickerIndexPath = nil
}
if (!sameCellClicked)
{
// hide the old picker and display the new one
let rowToReveal = (before ? indexPath.row - 1 : indexPath.row)
let indexPathToReveal = NSIndexPath(forRow: rowToReveal, inSection: 0)
togglePlatformPickerForSelectedIndexPath(indexPathToReveal)
platformPickerIndexPath = NSIndexPath(forRow: indexPathToReveal.row + 1, inSection: 0)
}
tableView.deselectRowAtIndexPath(indexPath, animated: true)
tableView.endUpdates()
updatePlatformPicker()
}
func updatePlatformPicker()
{
if let indexPath = platformPickerIndexPath {
let associatedPlatformPickerCell = tableView.cellForRowAtIndexPath(indexPath)
if let targetedPlatformPicker = associatedPlatformPickerCell?.viewWithTag(Constants.kPlatformPickerTag) as! UIPickerView? {
targetedPlatformPicker.dataSource = self
targetedPlatformPicker.delegate = self
}
}
}
func togglePlatformPickerForSelectedIndexPath(indexPath: NSIndexPath)
{
tableView.beginUpdates()
let indexPaths = [NSIndexPath(forRow: indexPath.row + 1, inSection: 0)]
// check if 'indexPath' has an attached picker below it
if hasPickerForIndexPath(indexPath)
{
// found a picker below it, so remove it
tableView.deleteRowsAtIndexPaths(indexPaths, withRowAnimation: .Fade)
}
else
{
// didn't find a picker below it, so we should insert it
tableView.insertRowsAtIndexPaths(indexPaths, withRowAnimation: .Fade)
}
tableView.endUpdates()
}
func hasPickerForIndexPath(indexPath: NSIndexPath) -> Bool
{
var hasPlatformPicker = false
let targetedRow = indexPath.row + 1
let checkPlatformPickerCell = tableView.cellForRowAtIndexPath(NSIndexPath(forRow: targetedRow, inSection: 0))
let checkPlatformPicker = checkPlatformPickerCell?.viewWithTag(Constants.kPlatformPickerTag)
hasPlatformPicker = checkPlatformPicker != nil
return hasPlatformPicker
}
func hasInlinePlatformPicker() -> Bool
{
return platformPickerIndexPath != nil
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return (indexPathHasPicker(indexPath) ? pickerCellRowHeight : tableView.rowHeight)
}
// MARK: - Platform Picker View Data Source and Delegates
func numberOfComponentsInPickerView(pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return platformPickerDataSource.count
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return platformPickerDataSource[row]
}
func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
print("Platform Selected: \(platformPickerDataSource[row])")
var targetedCellIndexPath: NSIndexPath?
if hasInlinePlatformPicker() {
// inline picker: update the cell's above the picker cell
//
targetedCellIndexPath = NSIndexPath(forRow: platformPickerIndexPath!.row - 1, inSection: 0)
}
let cell = tableView.cellForRowAtIndexPath(targetedCellIndexPath!)
cell?.detailTextLabel?.text = platformPickerDataSource[row]
}
}

Resources