Pass Firebase Data to DetailView using CollectionViewCell _Swift - swift

I am using Firebase Database to keep my data there. I can save all of the items successfully and basically can see them in the database console. I can also populate the collectionView cell with the stored data.
The only problem is that I cannot pass the data to detail view successfully.
I have looked at my other iOS app where I segue from tableview to view controller successfully but couldn't make it work with the collectionView in this new app.
This is the view controller that gets the data from firebase database. observeRecipes() function prints out the data in the console.
class RecipesViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
#IBOutlet weak var recipesCollectionView: UICollectionView!
var ref: DatabaseReference!
var recipes = [Recipe]()
override func viewDidLoad() {
super.viewDidLoad()
recipesCollectionView.delegate = self
recipesCollectionView.dataSource = self
observeRecipes()
IHProgressHUD.showImage(UIImage(named:"disabled")!, status: "Loading")
}
func observeRecipes() {
let ref = Database.database().reference(withPath: "recipes")
ref.observe(.value, with: { snapshot in
print(snapshot.value as Any)
var newRecipes: [Recipe] = []
for child in snapshot.children {
if let childSnapshot = child as? DataSnapshot,
let dict = childSnapshot.value as? [String:Any],
let showTitle = dict["RecipeName"] as? String,
let showTime = dict["RecipeTime"] as? String,
let recipeImage = dict["RecipePhoto"] as? String,
let ingridients = dict["Ingridients"] as? String,
let firstImageViewURL = dict["imageOne"] as? String,
let firstIngridients = dict["firstIngridientList"] as? String,
let firstInstructions = dict["firstInstructionList"] as? String,
let secondImageViewURL = dict["imageTwo"] as? String,
let secondIngridients = dict["secondIngridientList"] as? String,
let secondInstructions = dict["secondInstructionList"] as? String,
let thirdImageViewURL = dict["imageThird"] as? String,
let thirdIngridients = dict["thirdIngridientList"] as? String,
let thirdInstructions = dict["thirdInstructionList"] as? String,
let url = URL(string:recipeImage),
let urlFirst = URL(string: firstImageViewURL),
let urlSecond = URL(string: secondImageViewURL),
let urlThird = URL(string: thirdImageViewURL) {
let recipe = Recipe(title: showTitle, time: showTime, recipeImageURL: url, ingridients: ingridients, firstImageViewURL: urlFirst, firstIngridients: firstIngridients, firstInstructions: firstInstructions, secondImageViewURL: urlSecond, secondIngridients: secondIngridients, secondInstructions: secondInstructions, thirdImageViewURL: urlThird, thirdIngridients: thirdIngridients, thirdInstructions: thirdInstructions)
newRecipes.append(recipe)
}
}
self.recipes = newRecipes
self.recipesCollectionView.reloadData()
})
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return recipes.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let recipeCell = collectionView.dequeueReusableCell(withReuseIdentifier: "recipeCell", for: indexPath) as! RecipeCollectionViewCell
recipeCell.set(cell: recipes[indexPath.row])
return recipeCell
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showRecipeDetails" {
let destination = segue.destination as! RecipeDetailViewController
destination.selectedRecipe = sender as! Recipe
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let cell = recipesCollectionView.cellForItem(at: indexPath) as! RecipeCollectionViewCell
performSegue(withIdentifier: "showRecipeDetails", sender: cell)
// performSegue(withIdentifier: "showRecipeDetails", sender: indexPath)
}
}
}
This is the detailViewController
class RecipeDetailViewController: UIViewController, UIScrollViewDelegate {
var recipes = [Recipe]()
var ref: DatabaseReference?
var selectedRecipe: Recipe?
// Recipe Details
#IBOutlet weak var recipeTitleLabel: UILabel!
#IBOutlet weak var recipeTimeLabel: UILabel!
#IBOutlet weak var recipeImageView: UIImageView!
#IBOutlet weak var ingridientsLabel: UILabel!
//General Outlets & Variables
#IBOutlet weak var scrollView: UIScrollView!
#IBOutlet weak var closeButtonView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
scrollView.delegate = self
recipeTitleLabel.text = selectedRecipe?.title
}
Below is the code that I have been using for prepareForSegue in my other app which works fine. I have tried to tweak this to fit into collectionView but somehow I cannot get it work.
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showDetails" {
let destination = segue.destination as! StoryDetailsViewController
if let indexPath = self.tableView.indexPathForSelectedRow {
destination.selectedStory = self.posts[indexPath.row]
print(indexPath.row)
}
}
}

You can try
performSegue(withIdentifier: "showRecipeDetails", sender: recipes[indexPath.item])
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showRecipeDetails" {
let destination = segue.destination as! RecipeDetailViewController
destination.selectedRecipe = sender as! Recipe
}
}

Related

How do I allow a user to only fetch their own data? Swift

I've already implemented Firebase in my app. I'm able to press a button and send the desired data to Firebase. I also set up a table view, so that the desired data is then added to the table view. However, when any user presses the butting to send data and update the table, all of the data is pulled, even from other users. It seems the entire database is being pulled, rather than the one specific to the user. I want a user to be able to get the hand drying options that they entered/saved based on their uid, not those of other users. I think it has something to do with this part of the code: let handDryLocations = ["id":key
I'm very new to all of this so any help would be very much appreciated. Here is the code:
import UIKit
import Firebase
import FirebaseDatabase
class HandDrySaveViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var refHandrylocations: DatabaseReference!
#IBOutlet weak var BestOption: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self, selector: #selector(didGetNotification4(_:)), name: Notification.Name("text4"), object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(didGetNotification5(_:)), name: Notification.Name("text5"), object: nil)
if FirebaseApp.app() == nil {
FirebaseApp.configure()
}
refHandrylocations = Database.database().reference().child("users");
refHandrylocations.observe(DataEventType.value, with:{(snapshot) in
if snapshot.childrenCount>0{
self.handDryList.removeAll()
for handDryOptions in snapshot.children.allObjects as![DataSnapshot]{
let handDryObject = handDryOptions.value as? [String: AnyObject]
let handDryLocation = handDryObject?["handrylocation"]
let handDryBest = handDryObject?["handdrybest"]
let handDryString = handDryObject?["handdryoption"]
let handDryId = handDryObject?["id"]
let handDry = HandDryModel(id: handDryId as! String?, location: handDryLocation as! String?, best: handDryBest as! String?, options: handDryString as! String?)
self.handDryList.append(handDry)
}
self.handDryTable.reloadData()
}
})
// Do any additional setup after loading the view.
}
#IBAction func BacktoHDCalcButton(_ sender: UIButton) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(identifier: "TowelVDryer")
vc.modalPresentationStyle = .overFullScreen
present(vc, animated: true)
}
func addHandDryLocation(){
let key = refHandrylocations.childByAutoId().key
let handDryLocations = ["id":key,
"handrylocation": HandDryLocation.text! as String,
"handdrybest" : BestOption.text! as String,
"handdryoption" : HandDryOptionsString.text! as String
]
refHandrylocations.child(key!).setValue(handDryLocations)
OptionSavedMessage.text = "Location Saved"
}
#IBOutlet weak var HandDryOptionsString: UILabel!
#IBOutlet weak var HandDryLocation: UITextField!
#IBOutlet weak var OptionSavedMessage: UILabel!
#IBAction func BackButton(_ sender: UIButton) {
}
#objc func didGetNotification4(_ notification: Notification){
let text = notification.object as! String?
HandDryOptionsString.text = text
}
#objc func didGetNotification5(_ notification: Notification){
let text = notification.object as! String?
BestOption.text = text
}
#IBAction func SaveHandDryButton(_ sender: UIButton) {
addHandDryLocation()
}
#IBOutlet weak var handDryTable: UITableView!
var handDryList = [HandDryModel]()
public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return handDryList.count
}
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! HandDrySavedTableViewCell
let handDry: HandDryModel
handDry = handDryList[indexPath.row]
cell.locationOfOption.text = handDry.location
cell.bestOption.text = handDry.best
cell.optionString.text = handDry.options
return cell
}
}
You're reading the data for all users here:
refHandrylocations = Database.database().reference().child("users");
refHandrylocations.observe(DataEventType.value, with:{(snapshot) in
If you want to read the data for only specific users, you will have to change this code to specify what users to read the data for.
For example, if you've stored the information for each user using their UID as the key, you can read only that key with:
refHandrylocations = Database.database().reference().child("users");
var uid = Auth.auth().currentUser!.uid; // See https://firebase.google.com/docs/auth/ios/manage-users#get_the_currently_signed-in_user
refHandrylocations.child(uid ).observe(DataEventType.value, with:{(snapshot) in
let handDryObject = snapshot.value as? [String: AnyObject]
let handDryLocation = snapshot?["handrylocation"]
let handDryBest = snapshot?["handdrybest"]
let handDryString = snapshot?["handdryoption"]
let handDryId = snapshot?["id"]
...
Here's what I ended up doing. I'm sure its not perfect to a pro, but it gets the job done for me.
guard let user = Auth.auth().currentUser?.uid else { return }
ref!.child("users").child(Auth.auth().currentUser!.uid).child("Quotes").childByAutoId().setValue(quotesLabel.text!)

Passing access from tableViewController to another view controller

I have spent a fair bit of time on this and still can't seem to figure out what I'm doing wrong.
I would like to run the reloadData() function in my own function on another view controller than the tableViewController but I get the error Type 'HomeViewController' has no member 'reloadData'.
HomeViewController:
import UIKit
import CoreData
class HomeViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var index = ""
var item : [ListItem] = [] //listName
var listName = [""]
override func viewDidLoad() {
super.viewDidLoad()
self.homeListsTableView.delegate = self
self.homeListsTableView.dataSource = self
homeListsTableView.reloadData()
//List Names
//List Items - Within a list Name
let listItem1 = ListItem()
listItem1.name = "" //Update so names are updated via append the ListItem Array
listItem1.location = ""
item.append(listItem1)
let listItem2 = ListItem()
listItem2.name = ""
listItem2.location = ""
item.append(listItem2)
}
#IBOutlet weak var homeListsTableView: UITableView!
#IBAction func templatesButton(_ sender: Any) {
tabBarController?.selectedIndex = 2
}
override func viewWillAppear(_ animated: Bool) {
if let context = (UIApplication.shared.delegate as? AppDelegate)?.persistentContainer.viewContext {
if let coreDataListItems = try? context.fetch(ListName.fetchRequest()) as? [ListName] {
print(coreDataListItems)
}
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return listName.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = listName[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
// performSegue(withIdentifier: "goToItems", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let vc = segue.destination as! ListNameViewController
vc.homeListsTableViewVC = homeListsTableView
}
}
ListName View Controller:
import UIKit
import CoreData
class ListNameViewController: UIViewController, UITableViewDelegate {
// var listName = [""]
let context = (UIApplication.shared.delegate as? AppDelegate)?.persistentContainer.viewContext
var homeListsTableViewVC = HomeViewController.self
override func viewDidLoad() {
super.viewDidLoad()
}
#IBOutlet weak var listNameValue: UITextField!
#IBOutlet weak var locationOption: UITextField!
#IBOutlet weak var createButtonChange: UIButton!
#IBAction func createButton(_ sender: Any) {
let newList = ListName(context: context!)
newList.listName = listNameValue.text
// let location = locationOption.text!
//tabBarController?.selectedIndex = 0
//performSegue(withIdentifier: "home", sender: nil)
}
func saveList() {
do {
try context!.save()
} catch {
print("Error saving context \(error)")
}
homeListsTableViewVC.reloadData()
}
}
I'm trying to use the prepare for segue function to pass the homeListsTableView data to then use the reloadData() function. Could someone tell me what I'm doing wrong?
Thanks!
You can use delegate or closure to update your tableview.. here is pointers of how you can use closure in your classes to update view
class ListNameViewController: UIViewController, UITableViewDelegate {
var callback: (()->())?
//....
func saveList() {
do {
try context!.save()
} catch {
print("Error saving context \(error)")
}
callback?()
}
}
And while creating ListNameViewController
class HomeViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let vc = segue.destination as! ListNameViewController
vc.callback = { [weak self] in
self?.homeListsTableView.reloadData()
}
}
}

Blank labels after data passing in Swift 4?

I am currently trying to pass data from my table view controller to a second view controller but my labels and image are appearing as blank in the second view controller.
This is my main event view controller:
class EventsTableViewController: PFQueryTableViewController {
override func queryForTable() -> PFQuery<PFObject> {
let query = PFQuery(className: "Events")
//query.order(byAscending: "location")
query.order(byAscending: "date")
return query
}
override func viewDidLoad() {
super.viewDidLoad()
self.title = "Upcoming Events"
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "MasterToDetail" {
let detailVC = segue.destination as! DetailViewController
detailVC.myEventCell = sender as? EventCell
}
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath, object: PFObject?) -> PFTableViewCell? {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! EventCell
cell.dateLabel.text = object?.object(forKey: "date") as? String
cell.locationLabel.text = object?.object(forKey: "location") as? String
cell.nameLabel.text = object?.object(forKey: "name") as? String
let imageFile = object?.object(forKey: "image") as? PFFile
cell.eventImage.image = UIImage(named: "download")
cell.eventImage.file = imageFile
cell.eventImage.loadInBackground()
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "MasterToDetail", sender: EventCell())
}
#IBAction func reloadTable(_ sender: Any) {
self.loadObjects()
}
#IBAction func onSignOutTapped(_ sender: Any) {
let firebaseAuth = Auth.auth()
do {
try firebaseAuth.signOut()
performSegue(withIdentifier: "signOutSegue", sender: nil)
} catch {
print (error)
}
}
}
and my second view controller:
class DetailViewController: UIViewController {
#IBOutlet weak var detailImageView: UIImageView!
#IBOutlet weak var detailNameLabel: UILabel!
#IBOutlet weak var detailDescriptionLabel: UILabel!
#IBOutlet weak var detailLocationLabel: UILabel!
var myEventCell: EventCell?
override func viewDidLoad() {
super.viewDidLoad()
setUI()
}
func setUI () {
detailNameLabel.text = myEventCell?.nameLabel.text
detailImageView.image = myEventCell?.eventImage.image
detailLocationLabel.text = myEventCell?.locationLabel.text
}
}
As you send an empty cell here
performSegue(withIdentifier: "MasterToDetail", sender: EventCell())
You need
let cell = tableView.cellForRow(at:indexPath)
performSegue(withIdentifier: "MasterToDetail", sender:cell)

Can't convert value of type 'String' to expected argument type 'UIImage'. UIImagePicker puts into collectionView - want to view in a detailed VC?

I'm trying to create a photo album via UIImagePicker into a CollectionView and cannot get it to segue to that same photo again in a detailed UIViewController. Pulling my hair out and this is just a tutorial as I have just started coding!
Can anyone tell me what I'm doing wrong?
Here is my ViewController:
import UIKit
class ViewController: UIViewController, UINavigationControllerDelegate {
#IBOutlet private weak var addButton: UIBarButtonItem!
#IBOutlet private weak var collectionView:UICollectionView!
#IBOutlet private weak var trashButton:UIBarButtonItem!
var testItems = [Person]()
var stormTrooperCollectionArray: [UIImage] = [#imageLiteral(resourceName: "StormTrooper-3052-423a-8c57-7220081e1585_800x"), #imageLiteral(resourceName: "ST3"), #imageLiteral(resourceName: "ST2"), #imageLiteral(resourceName: "ST4")]
#IBAction func addItem() {
addNewPerson()
}
#IBAction func trashItem(_ sender: Any) {
if let selectedItems = collectionView.indexPathsForSelectedItems {
let itemsForDeletion = selectedItems.map{$0.item}.sorted().reversed()
for item in itemsForDeletion {
testItems.remove(at: item)
}
collectionView.deleteItems(at: selectedItems)
}
}
#objc func refresh() {
addItem()
collectionView.refreshControl?.endRefreshing()
}
override func viewDidLoad() {
super.viewDidLoad()
// Set up a 3-column Collection View
let width = (view.frame.size.width - 20) / 3
let layout = collectionView.collectionViewLayout as! UICollectionViewFlowLayout
layout.itemSize = CGSize(width:width, height:width)
// Refresh Control
let refresh = UIRefreshControl()
refresh.addTarget(self, action: #selector(self.refresh), for: UIControlEvents.valueChanged)
collectionView.refreshControl = refresh
// Edit
navigationItem.leftBarButtonItem = editButtonItem
navigationController?.isToolbarHidden = true
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "DetailSegue" {
if let dest = segue.destination as? DetailsViewController,
let index = sender as? IndexPath {
dest.detailedImageHi = stormTrooperCollectionArray [index.row]
}
}
}
override func setEditing(_ editing: Bool, animated: Bool) {
super.setEditing(editing, animated: animated)
navigationController?.isToolbarHidden = !editing
addButton.isEnabled = !editing
trashButton.isEnabled = editing
collectionView.allowsMultipleSelection = editing
let indexes = collectionView.indexPathsForVisibleItems
for index in indexes {
let cell = collectionView.cellForItem(at: index) as! CollectionViewCell
cell.isEditing = editing
}
}
}
extension ViewController: UICollectionViewDelegate, UICollectionViewDataSource, UIImagePickerControllerDelegate {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return stormTrooperCollectionArray.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell", for: indexPath) as! CollectionViewCell
//cell.titleLabel.text = stormTrooperCollectionArray[indexPath.row]
cell.selectionImage.image = stormTrooperCollectionArray[indexPath.row]
cell.isEditing = isEditing
return cell
}
#objc func addNewPerson() {
let picker = UIImagePickerController()
picker.allowsEditing = true
picker.delegate = self
present(picker, animated: true)
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
guard let image = info[UIImagePickerControllerEditedImage] as? UIImage else { return }
let imageName = UUID().uuidString
let imagePicture = getDocumentsDirectory()
if let jpegData = UIImageJPEGRepresentation(image, 80) {
try? jpegData.write(to: imagePicture)
}
//let detailedItem = Person(imageHi: imageName)
//testItems.append(detailedItem)
let detailedItem = Person(imageHi: imageName)
//KEEPS THROWING AN ERROR HERE WHICH SAYS: Cannot convert value of type 'String' to expected argument type 'UIImage'
stormTrooperCollectionArray.append(detailedItem)
collectionView?.reloadData()
dismiss(animated: true)
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if !isEditing {
performSegue(withIdentifier: "DetailSegue", sender: indexPath)
}
}
func getDocumentsDirectory() -> URL {
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
let documentsDirectory = paths[0]
return documentsDirectory
}
}
Here is my VC for the Cell in the CollectionView:
import UIKit
class CollectionViewCell: UICollectionViewCell {
#IBOutlet weak var titleLabel: UILabel!
#IBOutlet weak var selectionImage: UIImageView!
}
Here is my VC for the Detailed View Controller:
import UIKit
class DetailsViewController: UIViewController {
var selection: String!
var detailedImageHi: UIImage!
#IBOutlet private weak var detailsLabel: UILabel!
#IBOutlet private weak var detailedImage: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
detailsLabel.text = selection
detailedImage.image = detailedImageHi
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Here is my VC for the NSObject Swift File:
import UIKit
class Person: NSObject {
var imageHi: UIImage
init(imageHi: UIImage){
self.imageHi = imageHi
}
}
In your code the UIImage is image and not imageName:
guard let image = info[UIImagePickerControllerEditedImage] as? UIImage else { return }
So all you have to do is pass the right argument to the constructor of Person:
let detailedItem = Person(imageHi: image)
imageName is a random string generated via UUID().uuidString, and used in this code to save the image to the documents directory with a random and unique name.

How to pass data via segue from one View Controller to another with optionals

I am trying to get my data to pass from one view to the next when I click on an NSCollectionViewItem. When an item is clicked I simply want to pass some data to a new view for a more "detailed" view of each item.
I keep getting "fatal error: unexpectedly found nil while unwrapping an Optional value". I feel like I am missing a key step in the ProductDetail.swift file. The error occurs at the bottom of ViewController.swift in my prepare() method. The process on how to do this for OS X is completely different than iOS so any help would be greatly appreciated.
ViewController.swift
import Cocoa
class ViewController: NSViewController {
#IBOutlet weak var colView: NSCollectionView!
var productCategories: [ProductCategory]?
var productsArray: [ProductModel]?
var detailLabel: test1?
override func viewWillAppear() {
super.viewWillAppear()
preferredContentSize = NSSize(width: 1025, height: 1200)
}
override func viewDidLoad() {
super.viewDidLoad()
getJSON()
}
func getJSON() {
let requestURL: NSURL = NSURL(string: "http://myurl.php")!
let urlRequest: NSMutableURLRequest = NSMutableURLRequest(url: requestURL as URL)
let session = URLSession.shared
let task = session.dataTask(with: urlRequest as URLRequest) {
(data, response, error) -> Void in
let httpResponse = response as! HTTPURLResponse
let statusCode = httpResponse.statusCode
if (statusCode == 200) {
do{
let json = try JSONSerialization.jsonObject(with: data!, options:.mutableContainers)
self.productsArray = [ProductModel]()
if let products = json as? [[String: Any]] {
for product in products {
let testproduct = ProductModel()
testproduct.product_name = product["product_name"] as? String
testproduct.product_price = product["product_price"] as? String
testproduct.product_image = product["product_image"] as? String
self.productsArray?.append(testproduct)
}
DispatchQueue.main.async(){
self.colView.reloadData()
}
}
}catch {
print("Error parsing the JSON: \(error)")
}
}
}
task.resume()
}
override var representedObject: Any? {
didSet {
// Update the view, if already loaded.
}
}
}
extension ViewController: NSCollectionViewDataSource, NSCollectionViewDelegate{
func collectionView(_ collectionView: NSCollectionView, numberOfItemsInSection section: Int) -> Int {
return productsArray?.count ?? 0
}
func collectionView(_ collectionView: NSCollectionView, itemForRepresentedObjectAt indexPath: IndexPath) -> NSCollectionViewItem {
let item = collectionView.makeItem(withIdentifier: "test1", for: indexPath) as! test1
item.buildProduct = productsArray?[indexPath.item]
return item
}
func collectionView(_ collectionView: NSCollectionView, didSelectItemsAt indexPaths: Set<IndexPath>) {
print("selected")
self.performSegue(withIdentifier: "showProductDetail", sender: self)
}
override func prepare(for segue: NSStoryboardSegue, sender: Any?) {
if (segue.identifier == "showProductDetail") {
if let detailVC = segue.destinationController as? ProductDetail {
detailVC.testLabel.stringValue = (detailLabel?.label.stringValue)!
}else{
detailLabel?.label.stringValue = "failed"
}
}
}
}
test1.swift
import Cocoa
class test1: NSCollectionViewItem {
#IBOutlet weak var label: NSTextField!
#IBOutlet weak var label2: NSTextField!
#IBOutlet weak var productImageView: NSImageView!
var productItem: ProductModel?
var buildProduct: ProductModel? {
didSet{
label.stringValue = (buildProduct?.product_name)!
label2.stringValue = (buildProduct?.product_price)!
setupAppIconImage()
}
}
override func viewDidLoad() {
super.viewDidLoad()
}
func setupAppIconImage() {
if let appIconImageURL = buildProduct?.product_image {
let url = NSURL(string: appIconImageURL)
URLSession.shared.dataTask(with: url! as URL,completionHandler:{(data, response, error) in
if error != nil {
print(error)
return
}
self.productImageView.image = NSImage(data: data!)
}).resume()
}
}
}
ProductDetail.swift
import Cocoa
class ProductDetail: NSViewController {
#IBOutlet weak var testLabel: NSTextField!
override func viewDidLoad() {
super.viewDidLoad()
}
}
I ended up figuring it out. It was much simpler than I thought. I needed to create a variable to hold the new data being passed in. Thank you to Santosh for his help and guidance.
ProductDetail.swift
class ProductDetail: NSViewController {
#IBOutlet weak var testLabel: NSTextField!
var theBigPass = String()
override func viewDidLoad() {
super.viewDidLoad()
testLabel.stringValue = theBigPass
}
}
ViewController.swift Segue Methods
func collectionView(_ collectionView: NSCollectionView, didSelectItemsAt indexPaths: Set<IndexPath>) {
print("selected")
let selectedIndexPath = collectionView.selectionIndexPaths.first
let item = collectionView.item(at: selectedIndexPath!)
detailLabel = item as! test1?
self.performSegue(withIdentifier: "showProductDetail", sender: self)
}
override func prepare(for segue: NSStoryboardSegue, sender: Any?) {
if (segue.identifier == "showProductDetail") {
if let detailVC = segue.destinationController as? ProductDetail {
let passed = (detailLabel?.label.stringValue)!
detailVC.theBigPass = passed
}
}
}