ContextMenuConfiguration for User Images? - swift

I want the image of users to popup (without action option) and then be dismissed if touched outside.
Say table view consist of 2 UI elements (a button and a text) and one picture. How would you set the pop up context menu for only the picture - immy?
public override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! ViewControllerTableViewCell
let immy = cell.viewWithTag(1) as! UIImageView
let person: Userx = people[indexPath.row]
let button = cell.viewWithTag(3) as! UIButton
cell.lblName.text = person.Education
cell.postID = self.people[indexPath.row].postID
if let PhotoPosts = person.PhotoPosts {
let url = URL(string: PhotoPosts)
print(PhotoPosts, "sttdb")
immy.sd_setImage(with: url)
}
return cell
}
extension homepage {
func contextMenuInteraction(_ interaction: UIContextMenuInteraction, configurationForMenuAtLocation location: CGPoint) -> UIContextMenuConfiguration? {
let configuration = UIContextMenuConfiguration(identifier: nil, previewProvider: nil)
return configuration
}
}
Below is the ViewControlleTableViewCell, added after the first comment. My reply to the comment also explains how this looks in main.storyboard.
class ViewControllerTableViewCell: UITableViewCell {
#IBOutlet weak var button: UIButton!
#IBOutlet weak var immy: UIImageView!
#IBOutlet weak var lblgenre1: UILabel!
#IBOutlet weak var lblName: UILabel!
#IBOutlet weak var lblName1: UILabel!
#IBOutlet weak var likeLabel: UILabel!
var postID: String!
var caption1: String!
var keyToPost: String!
var latestLocation1: [String: Double]?
let databaseRef = Database.database().reference()
var refArtists: DatabaseReference!
let profileImageView: UIImageView = {
let imageView = UIImageView()
return imageView
} ()
override func awakeFromNib() {
super.awakeFromNib()
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
#IBAction func button1(_ sender: Any) {
}
#IBAction func button2NBTHISISTORPREVENTSEGUE(_ sender: Any) {
}
}
In homepage:
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! ViewControllerTableViewCell

What you need is to enable user interaction in your UIImageView, make your ViewControllerTableViewCell conform to UIContextMenuInteractionDelegate, create an UIContextMenuInteraction and set your cell as the delegate. Then add the iteraction to your image view. Don't forget to remove the contextMenuInteraction method from your HomePage extension.
Your ViewControllerTableViewCell contextMenuInteraction interaction implementation should look like this:
import UIKit
class ViewControllerTableViewCell: UITableViewCell, UIContextMenuInteractionDelegate {
#IBOutlet weak var immy: UIImageView!
override func awakeFromNib() {
super.awakeFromNib()
immy.isUserInteractionEnabled = true
immy.addInteraction(UIContextMenuInteraction(delegate: self))
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
func contextMenuInteraction(_ interaction: UIContextMenuInteraction, configurationForMenuAtLocation location: CGPoint) -> UIContextMenuConfiguration? {
UIContextMenuConfiguration(identifier: nil, previewProvider: nil) { _ in
let share = UIAction(title: "Share", image: UIImage(systemName: "square.and.arrow.up")) { _ in
// share code
}
return UIMenu(title: "Profile Picture Menu", children: [share])
}
}
}

Related

Updating Realm through a custom button on the UITableViewCell

I have a tableview of "Books" that are stored in Realm. I want to set the "CurrentBook" property to "True" when hitting a button on a custom UITableViewCell.
I believe my error has something to do with getting the correct book value in "func selectCurrentBook", when I use an optional like below nothing happens.
#objc func selectCurrentBook(sender: UIButton) {
try! realm.write {
book?.currentlyReading = true
}
}
When I don't use an optional for book and use book.currentlyReading = true I get the error "Unexpectedly found nil while implicitly unwrapping an Optional value:"
Am I incorrectly passing the book value somewhere? I can't seem to find out how. Maybe I'm delegating wrong?
My TableViewCell is:
import UIKit
import RealmSwift
protocol MyBooksDelegate {
func currentlyReadingButton()
}
class MyBooksTableViewCell: UITableViewCell {
let realm = try! Realm()
#IBOutlet weak var titleLabel: UILabel!
#IBOutlet weak var authorLabel: UILabel!
#IBOutlet weak var smallThumbnailImageView: UIImageView!
#IBOutlet weak var currentlyReadingButton: UIButton!
#IBAction func currentlyReadingButton(_ sender: Any) {
}
private var book: Book!
func loadImage(smallThumbnailURL: String) {
let imageURL = URL(string: smallThumbnailURL ?? "")
smallThumbnailImageView.sd_setImage(with: imageURL)
}
func configureCell(book: Book, delegate: MyBooksDelegate?) {
titleLabel.text = book.bookTitle
authorLabel.text = book.bookAuthor
loadImage(smallThumbnailURL: book.bookSmallThumbnailImageURL)
currentlyReadingButton.addTarget(self, action: #selector(selectCurrentBook(sender:)), for: .touchUpInside)
}
#objc func selectCurrentBook(sender: UIButton) {
try! realm.write {
book?.currentlyReading = true
}
}
}
My View Controller with TableView is :
import SwiftyJSON
import RealmSwift
class BooksViewController: UIViewController, UITextFieldDelegate, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var myBooksTableView: UITableView!
let realm = try! Realm()
var books: Results<Book>?
// Search Bar Properties
var searchParameter = "intitle"
var booksArray: [Book] = []
override func viewDidLoad() {
super.viewDidLoad()
loadBooks()
// Setting up the TableView
self.myBooksTableView.delegate = self
self.myBooksTableView.dataSource = self
self.myBooksTableView.rowHeight = 120.0
// Setup Title
title = "My Books"
// navigationController?.navigationBar.prefersLargeTitles = true
}
override func viewWillAppear(_ animated: Bool) {
navigationController?.navigationBar.barStyle = .black
loadBooks()
}
func loadBooks() {
books = realm.objects(Book.self).sorted(byKeyPath: "DateCreated", ascending: false)
myBooksTableView.reloadData()
}
// TABLEVIEW
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return books?.count ?? 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCell(withIdentifier: "MyBooksTableViewCell", for: indexPath) as? MyBooksTableViewCell {
cell.configureCell(book: (books?[indexPath.row])!, delegate: self as? MyBooksDelegate)
// cell.selectionStyle = UITableViewCell.SelectionStyle.none
return cell
} else {
return UITableViewCell()
}
}
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
return true
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.performSegue(withIdentifier: "myBooksTOMyBooksDetail", sender: self)
myBooksTableView.deselectRow(at: indexPath, animated: true)
}
And my Book Model is:
class Book: Object {
#objc dynamic var bookTitle: String!
#objc dynamic var bookAuthor: String!
#objc dynamic var bookSmallThumbnailImageURL: String!
#objc dynamic var bookThumbnailImageURL: String!
#objc dynamic var bookDescription: String!
#objc dynamic var bookISBN_13: String!
#objc dynamic var currentlyReading = false
#objc dynamic var DateCreated = Date()
#objc dynamic var WordID = UUID().uuidString
// words
let words = List<Word>()
override static func primaryKey() -> String? {
return "WordID"
}
}
The most compatible syntax is
currentlyReadingButton.addTarget(self, action: #selector(selectCurrentBook), for: .touchUpInside)
and
#objc func selectCurrentBook(_ sender: UIButton) {
However as the cell is custom anyway I'd prefer an IBAction over target/action
And the protocol MyBooksDelegate seems to be unused.
Side note:
Force unwrap the cell
let cell = tableView.dequeueReusableCell(withIdentifier: "MyBooksTableViewCell", for: indexPath) as! MyBooksTableViewCell
A crash – with report – reveals a design mistake which can be fixed instantly. With the if let you'll see nothing and have no clue why.
Update:
The crash occurs because you don't set book in the cell, add the first line after the {
func configureCell(book: Book, delegate: MyBooksDelegate?) {
self.book = book
titleLabel.text = book.bookTitle
...

How pass data from button in TableViewCell to View Controller?

I have 2 ViewControllers, one of is called ProductListVC the other is MoreInfoVC. I have a tableView on ProductListViewController that shows cells multiple labels and buttons.
MoreInfoVC is a Modal pop-up VC with a few labels for the brand, Name, and description. I have all my data stored in Firestore and already have created class(ProductList) to help retrieve the data which presents the data in the tableview from the Cloud Firestore.
what I need to do is use the MoreInfo button in the individual TBV cell to pass the data into MoreInfoVC so that it can present the information of selected product
Now i can easily do this with either didSelectRowAt method or using indexPathForSelectedRow in prepare segue method. But both cases requires me to tap on the cell itself but not the button.
how would I be able to pass data from an individual tableview cell through the MoreInfo button onto the MoreInfoVC. I think I'm on the right path since it seems my MoreInfoVC is passing data but showing this at the moment
import UIKit
import Firebase
import FirebaseFirestore
class ProductListVC: UIViewController {
#IBOutlet weak var productListTableView: UITableView!
var productInventory: [ProductList] = []
var productSetup: [ProductList] = []
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
}
override func viewDidLoad() {
super.viewDidLoad()
productListTableView.dataSource = self
productListTableView.delegate = self
searchBar.delegate = self
fetchProducts { (products) in
self.productSetup = products
self.productListTableView.reloadData()
}
}
func fetchProducts(_ completion: #escaping ([ProductList]) -> Void) {
let ref = Firestore.firestore().collection("products")
ref.addSnapshotListener { (snapshot, error) in
guard error == nil, let snapshot = snapshot, !snapshot.isEmpty else {
return
}
completion(snapshot.documents.compactMap( {ProductList(dictionary: $0.data())} ))
}
}
}
extension ProductListVC: UITableViewDelegate, UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return productSetup.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "ProductListCell") as?
ProductListCell else { return UITableViewCell() }
cell.configure(withProduct: productSetup[indexPath.row])
cell.delegate = self
return cell
}
}
extension ProductListVC: ProductListCellDelegate {
func onTouchInfoButton(from cell: ProductListCell) {
self.selectedProduct = cell.product
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
self.performSegue(withIdentifier: "MoreInfo", sender: self)
}
}
import UIKit
import Firebase
class MoreInfoVC: UIViewController {
var products: ProductList?
#IBOutlet weak var productName: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
productName.text = "\(String(describing: products?.brand)): \(String(describing: products?.name))"
}
#IBAction func closeBtn(_ sender: Any) {
dismiss(animated: true, completion: nil)
print("Close More Information")
}
}
import UIKit
import SDWebImage
import Firebase
protocol ProductListCellDelegate: class {
func onTouchInfoButton(from cell: ProductListCell)
}
class ProductListCell: UITableViewCell {
weak var product: ProductList!
weak var delegate: ProductListCellDelegate?
#IBOutlet weak var productImage: UIImageView!
#IBOutlet weak var productName: UILabel!
#IBOutlet weak var categoryLabel: UILabel!
#IBOutlet weak var strain: UILabel!
#IBOutlet weak var moreInfo: RoundButton!
func configure(withProduct product: ProductList) {
productName.text = "\(String(describing: product.brand)): \(String(describing: product.name))"
categoryLabel.text = product.category
productImage.sd_setImage(with: URL(string: product.imageUrl))
strain.text = product.strain
self.product = product
}
#IBAction func infoButtonAction(_ sender: Any) {
self.delegate?.onTouchInfoButton(from: self)
}
}
Function #IBAction func infoButtonAction(_ sender: Any) {} should be in the ProductListCell
When that button is tapped, connect with the ProductListVC by delegate or closure to get the selected product.
Update
Using delegate:
Update your ProductListCell
import UIKit
import SDWebImage
import Firebase
protocol ProductListCellDelegate: class {
func onTouchInfoButton(from cell: ProductListCell)
}
class ProductListCell: UITableViewCell {
#IBOutlet weak var productImage: UIImageView!
#IBOutlet weak var dispensaryName: UILabel!
#IBOutlet weak var productName: UILabel!
#IBOutlet weak var thcPercent: UILabel!
#IBOutlet weak var cbdPercent: UILabel!
#IBOutlet weak var categoryLabel: UILabel!
#IBOutlet weak var categoryStrain: UILabel!
#IBOutlet weak var moreInfo: RoundButton!
weak var product: Product!
weak var delegate: ProductListCellDelegate?
func configure(withProduct product: ProductList) {
self.product = product
productName.text = "\(String(describing: product.brand)): \(String(describing: product.name))"
dispensaryName.text = product.dispensaryName
categoryLabel.text = product.category
productImage.sd_setImage(with: URL(string: product.imageUrl))
cbdPercent.text = product.cbd
thcPercent.text = product.thc
categoryStrain.text = product.strain
}
#IBAction func infoButtonAction(_ sender: Any) {
self.delegate?.onTouchInfoButton(from: self)
}
}
In your ProductListVC:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "ProductListCell") as?
ProductListCell else { return UITableViewCell() }
cell.configure(withProduct: productSetup[indexPath.row])
cell.delegate = self
return cell
}
extension ProductListVC: ProductListCellDelegate {
func onTouchInfoButton(from cell: ProductListCell) {
let selectedProduct = cell.product
// Do your stuff here
}
}
UPDATE
Because you use segue for navigation so let's create a variable to store your selected product in your ProductListVC
import UIKit
import Firebase
import FirebaseFirestore
class ProductListVC: UIViewController {
#IBOutlet weak var productListTableView: UITableView!
var productInventory: [ProductList] = []
var productSetup: [ProductList] = []
var selectedProduct: Product?
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
}
override func viewDidLoad() {
super.viewDidLoad()
productListTableView.dataSource = self
productListTableView.delegate = self
searchBar.delegate = self
fetchProducts { (products) in
self.productSetup = products
self.productListTableView.reloadData()
}
}
func fetchProducts(_ completion: #escaping ([ProductList]) -> Void) {
let ref = Firestore.firestore().collection("products")
ref.addSnapshotListener { (snapshot, error) in
guard error == nil, let snapshot = snapshot, !snapshot.isEmpty else {
return
}
completion(snapshot.documents.compactMap( {ProductList(dictionary: $0.data())} ))
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let vc = segue.destination as? MoreInforVC {
vc.product = self.selectedProduct
}
}
}
extension ProductListVC: UITableViewDelegate, UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return productSetup.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "ProductListCell") as?
ProductListCell else { return UITableViewCell() }
cell.configure(withProduct: productSetup[indexPath.row])
cell.delegate = self
return cell
}
}
extension ProductListController: ProductListCellDelegate {
func onTouchInfoButton(from cell: ProductListCell) {
self.selectedProduct = cell.product
self.performSegue(withIdentifier: "YourSegueIdentifier", sender: self)
}
}

"Fatal error: Index out of range 2019-08-30 11:01:35.001667-0400 fmcBeta[58563:3478851] Fatal error: Index out of range"

I am creating an events feed, using a table view and Firebase as my database. I am using dateformatter with a style type of full for date and short for time and writing it to my database as a string which is perfect, it writes exactly how i want it to.
However, when i try to read the data from firebase and display it on my textlabel in the tableview cell i get the following error.
Error:
"Fatal error: Index out of range
2019-08-30 11:01:35.001667-0400 fmcBeta[58563:3478851] Fatal error: Index out of range"
Any help would be greatly appreciated i am self learning and fairly new to swift.
This is my table view cell:
class EventsTableViewCell: UITableViewCell {
#IBOutlet weak var eventLocation: UILabel!
#IBOutlet weak var eventDate: UILabel!
#IBOutlet weak var eventTitle: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
This is my viewcontoller with tableview protocols:
class EventsViewController: UIViewController,UITableViewDelegate,UITableViewDataSource {
#IBOutlet weak var tableView: UITableView!
var eventsRef: DatabaseReference?
var eventsDatabaseHandle:DatabaseHandle?
var eventsTitles = [String]()
var eventTimestamps:[String] = []
var eventsLocations = [String]()
eventsRef = Database.database().reference()
tableView.reloadData()
tableView.transform = CGAffineTransform(rotationAngle: -CGFloat.pi)
tableView.delegate = self
tableView.dataSource = self
eventsDatabaseHandle = eventsRef?.child("Church Events").observe(.childAdded, with: { (snaphot) in
let eventPost = snaphot.value as! [String: Any]
self.eventTimestamps.append(eventPost["eventdate"] as! String)
self.eventsTitles.append(eventPost["eventtitle"] as! String)
self.eventsLocations.append(eventPost["eventlocation"] as! String)
self.tableView.reloadData()
})
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return eventsTitles.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "events") as! EventsTableViewCell
cell.eventTitle.text! = eventsTitles[indexPath.row]
cell.eventDate.text! = eventTimestamps[indexPath.row]
cell.eventLocation.text! = eventsLocations[indexPath.row]
cell.transform = CGAffineTransform(rotationAngle: CGFloat.pi)
return cell
}
}
This is how i'm writing the data to Firebase
#IBAction func saveEventsButton(_ sender: Any) {
let eventsDates = DateFormatter.localizedString(from: eventDateSelector.date, dateStyle: DateFormatter.Style.full, timeStyle: DateFormatter.Style.short) as String
print(eventsDates.description)
let eventSaved:[String: Any] = ["eventdate": eventsDates,"eventtitle":eventsTitleTextField.text!,"eventlocation":eventsLocation.text!]
eventsRef.child("Church Events").childByAutoId().setValue(eventSaved)
self.dismiss(animated: true, completion: nil)
}
}

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.

Delegating a string to a UILabel and an image to a UIImageView - Swift

So, this is what's happening: I have two controllers; MainViewController and DetailsTableViewController. On DetailsTableViewController I want to write a name for random recipe, then I pick an image from photo library. After that, I want to send those data to a cell in MainViewController. The code this:
import UIKit
import CoreData
class MainViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, sendDetailsToMVCDelegate {
#IBOutlet weak var mainImage: UIImageView!
#IBOutlet weak var tableView: UITableView!
var namesListArray: [String] = []
var imagesListArray: [UIImage] = []
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
}
func sendDetailsToMVC (name: String, image: UIImage) {
namesListArray.append(name)
imagesListArray.append(image)
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return namesListArray.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var row = indexPath.row
var name: String = namesListArray[row] as String
var image: UIImage = imagesListArray[row] as UIImage
var cell = self.tableView.dequeueReusableCellWithIdentifier("customCell") as! CustomCellTableViewCell
cell.customLabel!.text = (name as String)
cell.customImage.image = (image as UIImage)
return cell
}
}
and
import UIKit
import CoreData
protocol sendDetailsToMVCDelegate {
func sendDetailsToMVC(name: String, image: UIImage)
}
class DetailsViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate, UITableViewDataSource, UITableViewDelegate, sendNameToDetailsViewControllerDelegate {
#IBOutlet weak var nameTextField: UITextField!
#IBOutlet weak var recipeImage: UIImageView!
#IBOutlet weak var tableView: UITableView!
var ingredientsList = [""]
var delegateDetails: sendDetailsToMVCDelegate?
override func viewDidLoad() {
super.viewDidLoad()
let howToDoButton = UIBarButtonItem(title:"How To Do", style: UIBarButtonItemStyle.Plain, target: self, action: Selector("showHowToDoScreen"))
navigationItem.rightBarButtonItem = howToDoButton
let newIngredientButton = UIBarButtonItem(title:"New Ingredient", style: UIBarButtonItemStyle.Plain, target:self, action: Selector("showNewIngredientScreen"))
navigationItem.leftBarButtonItem = newIngredientButton
//Picker imagem pelo toque
let tapGestureRecognizer: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: "chooseImage:")
tapGestureRecognizer.numberOfTapsRequired = 1
recipeImage.addGestureRecognizer(tapGestureRecognizer)
recipeImage.userInteractionEnabled = true
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return ingredientsList.count
}
func addNameToDetailsViewController(nameToDetail: NSString) {
ingredientsList.append(nameToDetail as String)
if tableView == nil {
return
}
tableView!.reloadData()
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let row = indexPath.row
let ingredientName = ingredientsList[row]
var cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: nil)
cell.textLabel!.text = ingredientName
return cell
}
//Picka a imagem pelo toque, acessando a PhotoLibrary
func chooseImage(recognizer: UITapGestureRecognizer) {
let imagePicker: UIImagePickerController = UIImagePickerController()
imagePicker.delegate = self
imagePicker.sourceType = UIImagePickerControllerSourceType.PhotoLibrary
self.presentViewController(imagePicker, animated: true, completion: nil)
}
//Ao selecionar a imagem, coloca-a na tela tocada
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [NSObject:AnyObject]) {
let pickedImage: UIImage = (info as NSDictionary).objectForKey(UIImagePickerControllerOriginalImage) as! UIImage
// small picture
let smallPicture = scaleImageWith(pickedImage, newSize: CGSizeMake(75,75))
var sizeOfImageView:CGRect = recipeImage.frame
sizeOfImageView.size = smallPicture.size
recipeImage.frame = sizeOfImageView
recipeImage.image = smallPicture
picker.dismissViewControllerAnimated(true, completion: nil)
}
func imagePickerControllerDidCancel(picker: UIImagePickerController) {
picker.dismissViewControllerAnimated(true, completion: nil)
}
func scaleImageWith(image:UIImage, newSize: CGSize) -> UIImage {
UIGraphicsBeginImageContextWithOptions(newSize, false, 0.0)
image.drawInRect(CGRectMake(0,0, newSize.width, newSize.height))
let newImage: UIImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return newImage
}
#IBAction func showNewIngredientScreen() {
let newIngredient = AddIngredientViewController(delegate: self)
if let navigation = navigationController {
navigation.pushViewController(newIngredient, animated: true)
}
}
#IBAction func showHowToDoScreen() {
let howToDo = HowToDoViewController(nibName: "HowToDoViewController", bundle: nil)
if let navigation = navigationController {
navigation.pushViewController(howToDo, animated: true)
}
}
#IBAction func addButton(sender: AnyObject) {
if nameTextField == nil || recipeImage == nil { return }
if recipeImage == nil { return }
let nameLabel = nameTextField.text
let imageView = recipeImage.image
if delegateDetails == nil { return }
delegateDetails?.sendDetailsToMVC(nameLabel, image: imageView!)
println("button pressed, name \(nameLabel) and image \(imageView) added.")
if let navigation = self.navigationController {
navigation.popViewControllerAnimated(true)
}
}
My question is: am I passing the information correctly? Is the correct way for storing images creating images arrays like I did? When I press the addButton, nothing happens, but it has no crashes. I'm in this issue for quite some time already and I would be very thankful if someone pointed to me what's wrong.
By the way, I'm new to Swift, so forgive me for any n00b mistakes.
Thanks!
Should be the same as in your other question. In the addButton function you are only setting the delegate if not niland not if you should. So delete if delegateDetails == nil { return } from the DetailViewControler - addButton and it should work.