Adding a UICollectionViewController inside UiView [duplicate] - ios

This question already has answers here:
Adding a view controller as a subview in another view controller
(8 answers)
Closed 5 years ago.
Hi am new to Ios development and I am trying to develop a simple view with imageView, pickerView and collectionView.
I have a separate UICollectionViewcontroller, I want to add that UIcollectionviewController inside the UiView in New MainVC. When i run this two UIViewControllers separately they works fine. But i don't know how to add the UICollectionViewcontroller to VIView.Can someone help me to put my UICollectionviewcontroller inside the UIView or any suggestion to do this in a simple way.
NewMainVC
import UIKit
class NewMainVC: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate, UITextFieldDelegate {
#IBOutlet weak var DropDown: UIPickerView!
#IBOutlet weak var textBox: UITextField!
#IBOutlet weak var sensorCollection: UICollectionView!
var values : [AnyObject] = []
override func viewDidLoad() {
super.viewDidLoad()
self.values.append("Main Room" as AnyObject)
self.values.append("Dinning Room" as AnyObject)
self.values.append("Kitchen" as AnyObject)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return self.values.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
let titleRow = (values[row] as? String)!
return titleRow
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
if values.count > 0 && values.count >= row{
self.textBox.text = self.values[row] as? String
self.DropDown.isHidden = true
}
}
func textFieldDidBeginEditing(_ textField: UITextField) {
//when you select the text field the picker view will be visible
if(textField == self.textBox){
self.DropDown.isHidden = false
self.view.endEditing(true)
}
}
}
PhotosCollectionViewController
import UIKit
import SwiftyJSON
class PhotosCollectionViewController: UICollectionViewController
{
#IBOutlet var home_collection_View: UICollectionView!
var sensorObjectList = [SensorObject]()
struct Storyboard {
static let photoCell = "PhotoCell"
static let headerView = "HeaderView"
static let showDetailSegue = "ShowDetail"
static let leftAndRightPaddings: CGFloat = 2.0
static let numberOfItemsPerRow: CGFloat = 3.0
}
override func viewDidLoad() {
super.viewDidLoad()
let collectionViewWidth = collectionView?.frame.width
let itemWidth = (collectionViewWidth! - Storyboard.leftAndRightPaddings) / Storyboard.numberOfItemsPerRow
let layout = collectionViewLayout as! UICollectionViewFlowLayout
layout.itemSize = CGSize(width: itemWidth, height: itemWidth+50)
NetworkCall().requestUsingGetMethod(url: "http://122.168.50.5:8181/rest/sitemaps", completion: { response in
print(response)
let jsonResults = JSON(String: response)
print("------------------------------")
print("HomePage Link : \(jsonResults[0]["homepage"]["link"].stringValue)")
print("leaf : \(jsonResults[0]["homepage"]["leaf"].stringValue)")
print("label : \(jsonResults[0]["label"].stringValue)")
print("name : \(jsonResults[0]["name"].stringValue)")
print("link : \(jsonResults[0]["link"].stringValue)")
print("------------------------------")
self.getHomePageData(homeurl: jsonResults[0]["link"].stringValue as String!)
})
}
func getHomePageData(homeurl: String){
NetworkCall().requestUsingGetMethodDictionnary(url: homeurl, completion: { response in
print(response)
let jsonResults = JSON(String: response)
// print(json8 )
print("-------------------------------------------------------------------------------------------------")
print("label : \(jsonResults["label"].stringValue)")
// print("Inside Homepage Link : \(json8["homepage"]["link"].stringValue)")
// print("Inside the Item array : \(json8["homepage"]["widgets"].arrayValue)")
// print("Inside the Item array2 : \(json8["homepage"]["widgets"][0]["widgets"].arrayValue)")
for result in jsonResults["homepage"]["widgets"][0]["widgets"].arrayValue {
print("---------------------------------------------")
print("Label : \(result["label"].stringValue)")
print("widgetId : \(result["widgetId"].stringValue)")
print("icon : \(result["icon"].stringValue)")
print("type : \(result["type"].stringValue)")
print("category : \(result["item"]["category"].stringValue)")
print("link : \(result["item"]["link"].stringValue)")
print("Item label : \(result["item"]["label"].stringValue)")
print("type : \(result["item"]["type"].stringValue)")
print("state : \(result["item"]["state"].stringValue)")
print("name : \(result["item"]["name"].stringValue)")
let sensor = SensorObject()
sensor.Label = result["label"].stringValue
sensor.widgetId = result["widgetId"].stringValue
sensor.icon = result["icon"].stringValue
sensor.category = result["item"]["category"].stringValue
sensor.link = result["item"]["link"].stringValue
sensor.Itemlabel = result["item"]["label"].stringValue
sensor.type = result["type"].stringValue
sensor.state = result["item"]["state"].stringValue
sensor.name = result["item"]["name"].stringValue
self.sensorObjectList.append(sensor)
}
self.home_collection_View.reloadData()
})
}
// MARK: - UICollectionViewDataSource
// override func numberOfSections(in collectionView: UICollectionView) -> Int {
// return photoCategories.count
// }
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
return self.sensorObjectList.count
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: Storyboard.photoCell, for: indexPath) as! PhotoCell
let sensor = self.sensorObjectList[indexPath.row]
cell.imageName = "ic_home_white"
cell.imageText = sensor.name
cell.statusText = sensor.state
cell.titleText = sensor.Itemlabel
return cell
}
// MARK: - UICollectionViewDelegate
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
// let category = self.photoCategories[indexPath.section]
// let image = UIImage(named: category.imageNames[indexPath.item])
//
// self.performSegue(withIdentifier: Storyboard.showDetailSegue, sender: image)
}
}
Can someone help me to put my UICollectionviewcontroller inside the UIView or any suggestion to do this in a simple way.

you can add container view to your mainVC and Embed your collection view to that Container View

Related

Stuck at reassigning TableView Cell property

I'm working on an App where you can track your reading progress for Books.
The HomeViewController contains a TableView that lists the books you have added. It has a progress Bar and shows what page you're on. The AddBookController is for adding Data about a book that gets delegated to the HomeViewController and is then listed as a TableView Row. The BookDetailController is shown when you select a Row and is for updating the Page you're on. I'll provide some screenshots.
I'm stuck at changing the "currentPage" property of the TableView Cell once you update it in the BookDetailViewController. I'm able to send the updatedPage to the HomeViewController (where the TableView is) but I don't know how to align the values of the Cells with the new value. My idea was to use an didSet-observer but I can't figure out how to set it up the right way.
Here is my code:
HomeViewController
class HomeViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, SendingBookDataProtocol {
var updatedPage = String() {
didSet { // probably at the wrong place but everything I've tried didn't work
print(updatedPage)
tableView?.reloadData()
}
}
var items = [BookItem]()
var item: BookItem?
override func viewDidLoad() {
super.viewDidLoad(){
tableView?.delegate = self
tableView?.dataSource = self
let nib = UINib(nibName: "BookCell", bundle: nil)
tableView?.register(nib, forCellReuseIdentifier: "BookCell")
}
func sendDataToHomeController(bookEntry item:BookItem) {
items.append(item)
tableView.reloadData()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
items.count
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let bookDetailVc = self.storyboard?.instantiateViewController(withIdentifier: "BookDetailView") as? BookDetailViewController
let item = items[indexPath.row]
let currentPageInt = Float(item.currentPage)!
let totalPagesInt = Float(item.totalPages)!
let result = Int(totalPagesInt - currentPageInt)
let percentageRead = Int((currentPageInt / totalPagesInt) * 100)
bookDetailVc?.lblName = item.title
bookDetailVc?.lblCurrentPage = Int(Float(item.currentPage)!)
// ...some more Code. Basically just sending the Data to BookDetailViewController
self.navigationController!.pushViewController(bookDetailVc!, animated: true)
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "BookCell", for: indexPath) as! BookCell
item = items[indexPath.row]
cell.title.text = item?.title
//... and so on
cell.pageNumbers.text = "S. " + item!.currentPage + " / " + item!.totalPages //here currentPage needs to be updated
return cell
}
}
BookDetailViewController
class BookDetailViewController: HomeViewController, UIPickerViewDelegate, UIPickerViewDataSource{
#IBOutlet weak var bookTitle: UILabel!
//...
#IBOutlet weak var numberPicker: UIPickerView!
var lblName = String()
//...
var lblCurrentPage = Int()
override func viewDidLoad() {
super.viewDidLoad()
self.numberPicker.delegate = self
self.numberPicker.dataSource = self
//...
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
let valueSelected = pickerData[row] as String
if let homeVc = storyboard?.instantiateViewController(withIdentifier: "getBookData") as? HomeViewController{
homeVc.updatedPage = valueSelected
homeVc.tableView?.reloadData()
}
}
}
AddBookController
protocol SendingBookDataProtocol {
func sendDataToHomeController(bookEntry: BookItem)
}
struct BookItem {
let title,author,currentPage,totalPages:String
let image: UIImage?
}
class AddBookController: UIViewController, UITextFieldDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
var delegate: SendingBookDataProtocol? = nil
#IBAction func buttonSave(_ sender: Any) {
let bookEntry = BookItem(title: textfieldTitle.text!, author: textfieldAuthor.text!, currentPage: fieldCurrentPage.text!, totalPages: fieldTotalPages.text!, image: bookImage)
self.delegate?.sendDataToHomeController(bookEntry: bookEntry)
dismiss(animated: true, completion: nil)
}
}
// rest should be irrelevant
Here are the screenshots:
You have to create a delegate in BookDetailViewController, like this :
protocol BookDetailDelegate: AnyObject {
func updatePage(for bookItem : BookItem)
}
class BookDetailViewController: HomeViewController, UIPickerViewDelegate, UIPickerViewDataSource {
var item: BookItem
var delegate: BookDetailDelegate?
//...
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
let valueSelected = pickerData[row] as String
delegate?.updatePage(valueSelected)
}
}
And then in the HomeViewController:
class HomeViewController {
}
//....
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let bookDetailVc = self.storyboard?.instantiateViewController(withIdentifier: "BookDetailView") as? BookDetailViewController
let item = items[indexPath.row]
bookDetailVc?.item = item
bookDetailVc?.delegate = self
self.navigationController!.pushViewController(bookDetailVc!, animated: true)
}
//.....
extension HomeViewController: BookDetailDelegate {
func updatePage(for bookItem: BookItem) {
let index = item.firstIndex(where: {$0.id = bookItem.id}) //here you should have a UUID or something
item[index] = bookItem
tableView.performBatchUpdates({
self.tableView.reloadRows(at: IndexPath(row: index, section: 0, with: .none)}
}, completion: nil))
}

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()
}

Using multiple UIPickerViews in dynamic UITableView

I am trying to make use of UIPickerViews, whereby the user can select an "amount"(number) between 1 and 20. In my TableviewCell there is a label and the picker.
Before I implemented the PickerViewDelegate and PickerViewDatasource, everything was fine. Since then I cannot even check if my code is right, cause it gives me "Fatal error: Unexpectly found nil..." for the label which has the array soloJobs (Array is not empty). So I guess I am making something fundamentally wrong.
At the end my achievment would be to store the values of the jobAmountPickerin the selAmountArray for given index.
Maybe someone can help.
This is my tableviewcell:
import UIKit
var globalAmount:[String] = []
class ProjectCharacterTableViewCell: UITableViewCell, UIPickerViewDelegate, UIPickerViewDataSource {
var jobAmount: [String] = []
var pickerData = ["1", "2", "3", "4","5","6","7","8","9","10","11","12","13","14","15","16","17","18","19","20"]
var selAmountArray: [String] = []
static let identifier = "ProjectCharacterTableViewCell"
#IBOutlet weak var jobLabel: UILabel!
#IBOutlet weak var jobAmountPicker: UIPickerView!
override func awakeFromNib() {
self.pickerData = Array<String>()
self.jobAmountPicker.delegate = self;
self.jobAmountPicker.delegate = self;
super.awakeFromNib()
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return pickerData.count
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
let selectedAmount = pickerData[row] as String
selAmountArray.append(selectedAmount)
globalAmount = selAmountArray
}
func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return pickerData[row]
}
}
And that's my viewController:
import UIKit
import FirebaseDatabase
import Foundation
import FirebaseFirestoreSwift
import CodableFirebase
class ProjectCharacterViewController: UIViewController, UITextFieldDelegate {
// MARK: - Properties
#IBOutlet weak var specTxt: UITextField!
#IBOutlet weak var difficultyTxt: UITextField!
#IBOutlet weak var budgetTxt: UITextField!
#IBOutlet weak var tableView: UITableView!
var soloJobs: [String] = []
var jobAmount: [String] = []
var rowBeingEditet : Int? = nil
var indexesNeedPicker: [NSIndexPath]?
var i: Int?
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
getJobs(for: User.current) { (memberJob) in
}
}
override func viewDidLoad() {
tableView.register(ProjectCharacterTableViewCell.self, forCellReuseIdentifier: "ProjectCharacterTableViewCell")
super.viewDidLoad()
}
// MARK: - Functions
func getJobs(for user: User, completion: #escaping ([MemberJobsStruct]) -> Void) {
var jobs: [String] = []
let ref = Database.database().reference().child("team").child(user.uid)
ref.observe(DataEventType.value, with: { snapshot in
for case let child as DataSnapshot in snapshot.children {
guard let value = child.value as? [String: Any] else {
return completion ([])
}
let memberJob = value["memberJob"] as! String
jobs.append(memberJob)
self.soloJobs = self.removeDuplicates(array: jobs)
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
})
}
func removeDuplicates(array: [String]) -> [String] {
var encountered = Set<String>()
var result: [String] = []
for value in array {
if encountered.contains(value) {
// Do not add a duplicate element.
}
else {
// Add value to the set.
encountered.insert(value)
// ... Append the value.
result.append(value)
}
}
return result
}
#IBAction func show(_ sender: Any) {
print("SoloJobs: ", soloJobs)
print("Thats the job amount: ", jobAmount)
print("Global amount :", globalAmount)
}
}
// MARK: - UITableViewDataSource
extension ProjectCharacterViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return soloJobs.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ProjectCharacterTableViewCell") as! ProjectCharacterTableViewCell
cell.jobLabel.text = soloJobs[indexPath.row]
i = indexPath.row
cell.jobAmountPicker.reloadAllComponents();
return cell
}
}
// MARK: - UITableViewDelegate
extension ProjectCharacterViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 60
}
}

Cannot convert return expression of type 'NSManagedObject' to return type 'String?'

I have built an app (my first) and it works like I want it to, but then I needed to add CoreData to it to get my events saved/fetched. I can see that my events (add information to tableview/remove information from there) gets saved as I print it, and the app is "Loaded" in "viewDidAppear".
The problem I think is that I am saving the array, not the NSobject. OR I am fetch the array, not the NSobject? I believe what I need to do is to add my array to an NSManagedObject?
Like this:
var List:[MealsMenu] = [].
When I do this I get it to work! Thats great! BUT, I have an VC that is calling this variable in a UIPickerView, and as soon as I Add the list to NSManagedObject (MealsMenu, which is my Entity in coredatamodel) I get this error-message:
Cannot convert return expression of type 'NSManagedObject' to return type 'String?'
I have tried to google this for a few days now but can't find any solution for this in my case. Do any of you have any idea what I can do?
My Entity (MealsMenu) have an attribute called "meals" which is refer to String.
As I said, If I skip the VC where the PickerView is I get it to work! Added and Deleted events are being saved.
Here are my code:
(All places where it says "List[row]" or "List[indexPath.row]" I get this error message).
addViewController:
import UIKit
import CoreData
class addViewController: UIViewController, UITextFieldDelegate {
var context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
#IBOutlet weak var input: UITextField!
#IBAction func addToMenu(_ sender: Any) {
if input != nil{
let newMeal = NSEntityDescription.insertNewObject(forEntityName: "MealsMenu", into: context)
newMeal.setValue(self.input.text, forKey: "meals")
do {
try context.save()
print("SAVED")
}
catch{
print(error)
}
input.text = ""
}else{
print("That's not a meal!")
}
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.view.endEditing(true)
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
input.resignFirstResponder()
return true
}
}
tableViewController:
import UIKit
import CoreData
class tableViewController: UIViewController, UITableViewDelegate, UITableViewDataSource{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return (List.count)
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: .default, reuseIdentifier: "cell")
cell.textLabel?.text = List[indexPath.row]
cell.textLabel?.textColor = UIColor.white
cell.backgroundColor = UIColor.clear
return(cell)
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == UITableViewCell.EditingStyle.delete
{
List.remove(at: indexPath.row)
myTableView.reloadData()
}
}
#IBOutlet weak var myTableView: UITableView!
override func viewDidAppear(_ animated: Bool) {
myTableView.reloadData()
}
override func viewDidLoad() {
super.viewDidLoad()
coredataClass.saveItems()
coredataClass.loadData()
}
}
ViewController:
import UIKit
import CoreData
var List:[MealsMenu] = []
class ViewController: UIViewController {
#IBOutlet weak var monday: UITextField!
#IBOutlet weak var tuesday: UITextField!
#IBOutlet weak var wednesday: UITextField!
#IBOutlet weak var thursday: UITextField!
#IBOutlet weak var friday: UITextField!
#IBOutlet weak var saturday: UITextField!
#IBOutlet weak var sunday: UITextField!
var daysArray = [UITextField]()
let pickerView = ToolbarPickerView()
var selectedMenu : String?
override func viewDidLoad() {
super.viewDidLoad()
setupDelegateForPickerView()
setupDelegatesForTextFields()
coredataClass.loadData()
}
func setupDelegatesForTextFields() {
//appending textfields in an array
daysArray += [monday, tuesday, wednesday, thursday, friday, saturday, sunday]
//using the array to set up the delegates, inputview for pickerview and also the inputAccessoryView for the toolbar
for day in daysArray {
day.delegate = self
day.inputView = pickerView
day.inputAccessoryView = pickerView.toolbar
}
}
func setupDelegateForPickerView() {
pickerView.dataSource = self
pickerView.delegate = self
pickerView.toolbarDelegate = self
}
}
// Create an extension for textfield delegate
extension ViewController : UITextFieldDelegate {
func textFieldDidBeginEditing(_ textField: UITextField) {
self.pickerView.reloadAllComponents()
}
}
// Extension for pickerview and toolbar
extension ViewController : UIPickerViewDelegate, UIPickerViewDataSource {
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return List.count
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return List[row]
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
// Check if the textfield isFirstResponder.
if monday.isFirstResponder {
monday.text = List[row]
} else if tuesday.isFirstResponder {
tuesday.text = List[row]
} else if wednesday.isFirstResponder {
wednesday.text = List[row]
} else if thursday.isFirstResponder {
thursday.text = List[row]
} else if friday.isFirstResponder {
friday.text = List[row]
} else if saturday.isFirstResponder {
saturday.text = List[row]
} else if sunday.isFirstResponder {
sunday.text = List[row]
} else {
//log errors
}
}
}
extension ViewController: ToolbarPickerViewDelegate {
func didTapDone() {
self.view.endEditing(true)
}
func didTapCancel() {
self.view.endEditing(true)
}
}
Specific these functions/lines in "ViewController" are throwing theses errors:
Cannot convert return expression of type 'MealsMenu' to return type 'String?'
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return List[row]
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
// Check if the textfield isFirstResponder.
if monday.isFirstResponder {
monday.text = List[row]
} else if tuesday.isFirstResponder {
tuesday.text = List[row]
} else if wednesday.isFirstResponder {
wednesday.text = List[row]
} else if thursday.isFirstResponder {
thursday.text = List[row]
} else if friday.isFirstResponder {
friday.text = List[row]
} else if saturday.isFirstResponder {
saturday.text = List[row]
} else if sunday.isFirstResponder {
sunday.text = List[row]
} else {
//log errors
}
}
And in "tableViewController" this function is throwing a similar error:
Cannot assign value of type 'MealsMenu' to type 'String?'
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: .default, reuseIdentifier: "cell")
cell.textLabel?.text = List[indexPath.row]
cell.textLabel?.textColor = UIColor.white
cell.backgroundColor = UIColor.clear
Thanks a lot for any guidens and help!
/
Andreas
Please read the error message carefully and then have a look at you design
Your data source is an array of MealsMenu instances which is a subclass of NSManagedObject while the return value is of type String?.
That's what the error message says: You cannot return a MealsMenu instance where a string is expected
return List[row].meals
There are two bad practices in the data source declaration line.
Variable names are supposed to be named lowercased.
The variable name of an array is supposed to be named in plural form.
The latter would indicate clearly that the variable contains multiple items for example
var menus : [MealsMenu] = []
With this change and with splitting the line into two the error becomes more obvious
let menu = menus[row]
return menu.meals
By the way the naming meals is also confusing because it implies to be an array.
In cellForRow change the lines accordingly
let menu = menus[indexPath.row]
cell.textLabel?.text = menu.meals

How to pass data between custom table view cells?

I have two custom table views (not table view controller) with custom
cells. I want to select a second cell from MainViewcontroller
and selected
title and price of cell info pass to the second view as
DetailViewController's first and second index labels.
This is my MainViewController.swift
Edit: Here is the answer
import UIKit
class MainViewController: UIViewController, UITableViewDataSource, UITableViewDelegate,
UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
#IBOutlet weak var searchBar: UISearchBar!
#IBOutlet weak var mainTableView: UITableView!
var imageNames = [ImageNames]()
var searchFoods: [String]!
var priceFood: [Double]!
var searching = false
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.tabBarController?.tabBar.isHidden = false
}
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.navigationBar.isHidden = true
let foodCell = Food(name: ["Hamburger big mac",
"Patates",
"Whopper",
"Steakhouse"], price: [15.0, 20.0, 25.0, 30.0])
searchBar.delegate = self
searchFoods = foodCell.name
priceFood = foodCell.price
imageNames = [
ImageNames(name: "images"),
ImageNames(name: "unnamed"),
ImageNames(name: "unnamed")
]
}
func numberOfSections(in tableView: UITableView) -> Int {
return 2
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return section == 0 ? 1 : searchFoods.count
// return section == 0 ? 1 : foodNames.count
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return indexPath.section == 0 ? 130 : 65
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return indexPath.section == 0 ? 100 : 65
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "MainFoodTableViewCell", for: indexPath) as! MainFoodTableViewCell
cell.mainFoodCollectionView.delegate = self
cell.mainFoodCollectionView.dataSource = self
cell.mainFoodCollectionView.reloadData()
cell.mainFoodCollectionView.tag = indexPath.row
return cell
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: "CellForFood", for: indexPath) as! MainFoodTitleTableViewCell
cell.titleLabel?.text = searchFoods[indexPath.row]
cell.priceLabel?.text = priceFood[indexPath.row].description
return cell
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "cellForFoodSegue" {
if let destinationViewController = segue.destination as? DetailViewController
{
let indexPath = self.mainTableView.indexPathForSelectedRow!
var foodNameArray: [String]
var foodPriceArray: [Double]
foodNameArray = [searchFoods[indexPath.row]]
foodPriceArray = [priceFood[indexPath.row]]
destinationViewController.detailFoodName = foodNameArray
destinationViewController.detailFoodPrice = foodPriceArray
}
}
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return imageNames.count
}
//MARK:- collection view cell size
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let width = UIScreen.main.bounds.width
return CGSize(width: width, height: 130)
}
//MARK:- //collection view cell data
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MainFoodCollectionViewCell", for: indexPath) as! MainFoodCollectionViewCell
let img = imageNames[indexPath.row]
cell.mainFoodImage.image = UIImage(named: img.name)
return cell
}
}
//MARK:- SearchBar data
extension MainViewController : UISearchBarDelegate {
func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) {
self.searchBar.showsCancelButton = true
mainTableView.reloadData()
}
func searchBarCancelButtonClicked(_ searchBar: UISearchBar) {
mainTableView.reloadData()
searchBar.showsCancelButton = false
searchBar.text = ""
searchBar.resignFirstResponder()
}
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
searchFoods = searchText.isEmpty ? searchFoods : searchFoods.filter { (item: String) -> Bool in
return item.range(of: searchText, options: .caseInsensitive, range: nil, locale: nil) != nil
}
mainTableView.reloadData()
}
}
Edit: Here is my DetailViewController
import UIKit
class DetailViewController: UIViewController {
#IBOutlet weak var foodTitle: UILabel!
#IBOutlet weak var foodSubTitle: UILabel!
#IBOutlet weak var foodPiece: UILabel!
#IBOutlet weak var foodPrice: UILabel!
#IBOutlet weak var drinkPicker: UITextField!
#IBOutlet weak var menuPieceStepper: UIStepper!
var drinkPickerView = UIPickerView()
var selectDrinkType: [String] = []
var detailFoodName : [String] = []
var detailFoodPrice : [Double] = [0.0]
let foods = Food(name: ["Hamburger big mac",
"Patates",
"Whopper",
"Steakhouse"], price: [15.0, 20.0, 25.0, 30.0])
#IBAction func foodPieceStepper(_ sender: Any) {
}
#objc func foodPieceChangeStepper() {
let res = menuPieceStepper.value + foods.price.first!
foodPrice.text = "\(res)"
}
#IBAction func addBasket(_ sender: Any) {
let destinationVC = MyCartViewController()
destinationVC.fromDetailFoodNames = foods.name
destinationVC.fromDetailFoodPrices = foods.price
dismiss(animated: true)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if(segue.identifier == "addToCartSegue") {
if let addToCartVC = segue.destination as? MyCartViewController {
addToCartVC.fromDetailFoodNames = [foodTitle.text]
addToCartVC.fromDetailFoodPrices = foods.price
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
menuPieceStepper.value = 0.0
menuPieceStepper.minimumValue = 0.0
menuPieceStepper.maximumValue = 30.0
menuPieceStepper.stepValue = foods.price.first!
menuPieceStepper.addTarget(self, action: #selector(foodPieceChangeStepper), for: .valueChanged)
drinkPickerView.delegate = self
drinkPicker.inputView = drinkPickerView
selectDrinkType = ["Ayran", "Kola", "Su", "Fanta", "Şalgam", "Sprite"]
foodTitle.text = detailFoodName.description
foodPrice.text = detailFoodPrice.description
self.navigationController?.navigationItem.title = "Sipariş Detayı"
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.dismissKeyboard (_:)))
self.view.addGestureRecognizer(tapGesture)
}
#objc func dismissKeyboard (_ sender: UITapGestureRecognizer) {
drinkPicker.resignFirstResponder()
}
override func viewWillAppear(_ animated: Bool) {
self.navigationController?.navigationBar.isHidden = false
}
override func viewWillDisappear(_ animated: Bool) {
self.navigationController?.navigationBar.isHidden = true
}
}
extension DetailViewController: UIPickerViewDelegate, UIPickerViewDataSource {
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return selectDrinkType.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return selectDrinkType[row]
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
let selectedDrink = selectDrinkType[row]
drinkPicker.text = selectedDrink
}
}
Aren't you looking for prepare(for segue: sender:) method? Usually you need to bind a cell prototype to a detail view with a segue, and when the cell is selected the segue is followed just after that method is called to prepare data injection to the detail view.

Resources