Cannot assign value of type 'NSObject' file to type 'UIImage' - Apple Swift - arrays

I'm trying to create a photo album via UIImagePicker into a CollectionView and cannot get it to segue to said 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?
var testItems = [Person]()
#IBAction func addItem() {
addNewPerson()
}
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 = testItems[index.row]
}
}
}
THE NS OBJECT FILE IS AS FOLLOWS:
class Person: NSObject {
var imageHi: String
init(imageHi: String){
self.imageHi = imageHi
}
}
DetailsViewController:
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.
}
}
import UIKit
class CollectionViewCell: UICollectionViewCell {
#IBOutlet weak var titleLabel: UILabel!
#IBOutlet weak var selectionImage: UIImageView!
}

Related

Send array from custom cell to another view controller

i'm running a query to Firebase and the results are displaying in a custom cell. The cell has a UIButton that when tapped it goes to another view controller where the user can enter info. The question i have is, how do i send the array in the custom cell to the next view controller? i need to send the array so i can reference the subcollection of info i'm going to add for each array. Segue is working properly, when i print to the console, the array is empty "nil". Any help is greatly appreciated.
Custom Cell
import UIKit
import Firebase
protocol PatCellCommentsDelegate {
func patCommentBtnTapped (ptcomments: [Comment])
}
class PatdataCell: UITableViewCell {
#IBOutlet weak var ptnameLbl: UILabel!
#IBOutlet weak var dobLbl: UILabel!
#IBOutlet weak var finLbl: UILabel!
#IBOutlet weak var officemdLbl: UILabel!
#IBOutlet weak var assignedmdLbl: UILabel?
#IBOutlet weak var appnameLbl: UILabel!
#IBOutlet weak var assigneddateLbl: UILabel!
#IBOutlet weak var roomnumberLbl: UILabel?
#IBOutlet weak var diagnosesLbl: UILabel!
#IBOutlet weak var reasonforadmitorconsultLbl: UILabel!
#IBOutlet weak var goalofhospitalizationLbl: UILabel!
#IBOutlet weak var seenoseeLbl: UILabel?
#IBOutlet weak var notestocboLbl: UILabel!
#IBOutlet weak var numCommentsLbl: UILabel!
#IBOutlet weak var hospitalLbl: UILabel!
#IBOutlet weak var teamLbl: UILabel!
#IBOutlet weak var addCommentBtn: UIButton!
var ptdata: PTData!
var ptcomments = [Comment]()
var delegate: PatCellCommentsDelegate?
override func awakeFromNib() {
super.awakeFromNib()
}
func configurePatDataCell(ptdata: PTData, delegate:
PatCellCommentsDelegate) {
self.ptdata = ptdata
self.delegate = delegate
ptnameLbl.text = ptdata.ptname
dobLbl.text = ptdata.dob
finLbl.text = ptdata.fin
officemdLbl.text = ptdata.officemd
assignedmdLbl?.text = ptdata.assignedmd
appnameLbl.text = ptdata.app
assigneddateLbl.text = ptdata.assigneddate
roomnumberLbl?.text = ptdata.room
diagnosesLbl.text = ptdata.diagnoses
reasonforadmitorconsultLbl.text = ptdata.reasonforadmitorconsult
goalofhospitalizationLbl.text = ptdata.goalofhospitalization
seenoseeLbl?.text = ptdata.seenosee
notestocboLbl.text = ptdata.notestocbo
numCommentsLbl.text = ptdata.comments
hospitalLbl.text = ptdata.hosp
teamLbl.text = ptdata.team
}
#IBAction func addCommentBtnTapped(_ sender: Any) {
//trying to send data to commentsVC from this cell
delegate?.patCommentBtnTapped(ptcomments: self.ptcomments)
}
}
View Controller
import UIKit
import Firebase
import SVProgressHUD
class PatdataVC: UIViewController, UITableViewDelegate,
UITableViewDataSource, PatCellCommentsDelegate {
#IBOutlet weak var patDataTableView: UITableView!
var ptdatas = [PTData]()
var ptComments = [Comment]()
override func viewDidLoad() {
super.viewDidLoad()
patDataTableView.delegate = self
patDataTableView.dataSource = self
patDataTableView.rowHeight = 1150
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "goToComments" {
let commtsVC = segue.destination as! CommentsVC
commtsVC.ptComments = ptComments
SVProgressHUD.dismiss()
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection
section: Int) -> Int {
return ptdatas.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath:
IndexPath) -> UITableViewCell {
if tableView == patDataTableView {
let cell = tableView.dequeueReusableCell(withIdentifier:
"PatdataCell", for: indexPath) as? PatdataCell
cell!.configurePatDataCell(ptdata: ptdatas[indexPath.row],
delegate: self)
return cell!
}
return UITableViewCell()
}
func patCommentBtnTapped (ptcomments: [Comment]) {
self.ptComments = ptcomments
performSegue(withIdentifier: "goToComments", sender: self)
}
}
CommentsVC
import UIKit
import Firebase
import FirebaseFirestore
class CommentsVC: UIViewController, UITableViewDelegate,
UITableViewDataSource, CommentsDelegate {
#IBOutlet weak var commentTableView: UITableView!
#IBOutlet weak var addCommentTxt: UITextField!
#IBOutlet weak var keyboardView: UIView!
var ptComments = [Comment]()
var commentsPtData: Comment!
var commentRef: DocumentReference!
var username: String!
var commentListener : ListenerRegistration!
let firestore = Firestore.firestore()
override func viewDidLoad() {
super.viewDidLoad()
commentTableView.dataSource = self
commentTableView.delegate = self
commentTableView.rowHeight = 110
//commentRef =
firestore.collection(PTLIST_REF).document(commentsPtData.documentId)
// if let name = Auth.auth().currentUser?.displayName{
// username = name
// }
self.view.bindToKeyboard()
}
override func viewDidAppear(_ animated: Bool) {
commentListener =
firestore.collection(PTLIST_REF).document(self.commentsPtData
.documentId)
.collection(COMMENTS_REF)
.order(by: TIMESTAMP, descending: false)
.addSnapshotListener({ (snapshot, error) in
guard let snapshot = snapshot else {
debugPrint("Error Fetching comments: \(Error.self)")
return
}
self.ptComments.removeAll()
self.ptComments = Comment.parseData(snapshot: snapshot)
self.commentTableView.reloadData()
})
}
override func viewDidDisappear(_ animated: Bool) {
commentListener.remove()
}
func commentOptionsTapped(commentsCellPtData: Comment) {
let alert = UIAlertController(title: "Edit Comment", message: "You
can delete or edit", preferredStyle: .actionSheet)
let deleteAction = UIAlertAction(title: "Delete Comment", style:
.default) { (action) in
self.firestore.runTransaction({ (transaction, errorPointer) ->
Any? in
let ptListDocument: DocumentSnapshot
do {
try ptListDocument =
transaction.getDocument(Firestore.firestore()
.collection(PTLIST_REF).document(self.commentsPtData.documentId))
} catch let error as NSError {
debugPrint("Fetch Error: \ .
(error.localizedDescription)")
return nil
}
guard let oldNumComments = ptListDocument.data()!
[NUM_COMMENTS] as? Int else { return nil }
transaction.updateData([NUM_COMMENTS : oldNumComments -
1], forDocument: self.commentRef!)
let commentRef =
self.firestore.collection(PTLIST_REF).document(self
.commentsPtData.documentId).collection(COMMENTS_REF)
.document(commentsCellPtData.documentId!)
transaction.deleteDocument(commentRef)
return nil
}) { (object, error) in
if let error = error {
debugPrint("transaction failed: \(error)")
} else {
alert.dismiss(animated: true, completion: nil)
}
}
}
let editAction = UIAlertAction(title: "Edit Comment", style:
.default) { (action) in
self.performSegue(withIdentifier: "toEditComment", sender:
(commentsCellPtData, self.commentsPtData))
alert.dismiss(animated: true, completion: nil)
}
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel,
handler: nil)
alert.addAction(deleteAction)
alert.addAction(editAction)
alert.addAction(cancelAction)
present(alert, animated: true, completion: nil)
}
#IBAction func addCommentTapped(_ sender: Any) {
guard let commentTxt = addCommentTxt.text else { return }
firestore.runTransaction({ (transaction, errorPointer) -> Any? in
let ptListDocument: DocumentSnapshot
do {
try ptListDocument =
transaction.getDocument(Firestore.firestore()
.collection(PTLIST_REF).document(self.commentsPtData.documentId))
} catch let error as NSError {
debugPrint("Fetch Error: \(error.localizedDescription)")
return nil
}
guard let oldNumComments = ptListDocument.data()!
[NUM_COMMENTS] as? Int else { return nil }
transaction.updateData([NUM_COMMENTS : oldNumComments + 1],
forDocument: self.commentRef!)
let newCommentRef =
self.firestore.collection(PTLIST_REF).document((self
.commentsPtData.documentId)).collection(COMMENTS_REF).document()
transaction.setData([
COMMENT_TXT : commentTxt,
TIMESTAMP : FieldValue.serverTimestamp(),
USERNAME : self.username!,
USER_ID : Auth.auth().currentUser?.uid ?? ""
], forDocument: newCommentRef)
return nil
}) { (object, error) in
if let error = error {
debugPrint("transaction failed: \(error)")
} else {
self.addCommentTxt.text = ""
self.addCommentTxt.resignFirstResponder()
}
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection
section: Int) -> Int {
return ptComments.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath:
IndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCell(withIdentifier:
"CommentCell", for: indexPath) as? CommentCell {
cell.configureCell(comment: ptComments[indexPath.row],
delegate: self)
return cell
}
return UITableViewCell()
}
}
In your source code ptcomments property in Custom Cell not set anywhere, it is empty in cell.
Please set correct value for ptcomments
UPDATE:
You try add line like self.comments = ptdata.commentsList to function configurePatDataCell

How to access UILabel in custom cell with indexPath and implement user data from array/ dictionary into the label

I have been trying to fix this for 4 days and still no luck so any help would be appreciated. I am trying to create a table view where workers can upload their profiles and users can scroll through to see which ones they like (see simulator photo). However, when I use indexPath.row it fills out the whole cell when I only want it to fill out one label so I can configure the different labels with the data I want.
Here is my Table view controller code:
import UIKit
import FirebaseDatabase
import FirebaseStorage
struct Worker {
var name: String!
var price: String!
}
class SelectATaskerTableViewController: UITableViewController {
var ref: DatabaseReference!
var myList:[String] = []
#IBOutlet var myTableView: UITableView!
var handle: DatabaseHandle!
var storageHandle: StorageHandle!
var storageRef: StorageReference!
override func viewDidLoad() {
super.viewDidLoad()
tableView.rowHeight = 111
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem
}
override func viewWillAppear(_ animated: Bool) {
myTableView.delegate = self
myTableView.dataSource = self
ref = Database.database().reference()
storageRef = Storage.storage().reference()
handle = ref.child("WorkerProfile").child("Name").observe(.childAdded, with: { (snapshot) in
if let item = snapshot.value as? String {
self.myList.append(item)
self.myTableView.reloadData()
}
})
}
#IBAction func reset(_ sender: Any) {
Database.database().reference().child("WorkerProfile").removeValue()
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return myList.count
}
var nameText: String!
var pricePerHourText: String!
var extraDetailsText: String!
var profilePicImage: UIImage!
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell:MyCellTableViewCell = self.tableView.dequeueReusableCell(withIdentifier: "cell") as! MyCellTableViewCell
cell.firstName.text = myList[indexPath.row]
cell.pricePerHour.text = myList[indexPath.row]
// cell.extraDetails.text = extraDetailsText
// cell.profilePic.image = profilePicImage
// Configure the cell...
return cell
}
And my custom table view cell code
import UIKit
class MyCellTableViewCell: UITableViewCell {
#IBOutlet weak var firstName: UILabel!
#IBOutlet weak var pricePerHour: UILabel!
#IBOutlet weak var extraDetails: UILabel!
#IBOutlet var profilePic: UIImageView!
}

Swift4 Xcode9 Passing variable between ViewControllers through segue

class InstanceViewController: NSViewController{
#IBOutlet weak var InstanceAddr:NSTextField!
var input: String = ""
override func viewDidLoad(){
super.viewDidLoad()
}
override func prepare(for segue: NSStoryboardSegue, sender: Any?) {
InstanceViewController().input = "https://google.com"
if (segue.identifier?.rawValue == "moveToLoginWindow"){
let destinationVC = segue.destinationController as! loginWebViewController
destinationVC.address = input
}
}
}
class loginWebViewController: NSViewController{
#IBOutlet weak var instanceview: WKWebView!
var address: String?
override func viewDidLoad(){
var instanceaddress: String? = address
super.viewDidLoad()
var url = URL(string: instanceaddress!)
var request = URLRequest(url: url!)
instanceview.load(request)
}
}
I'm trying to pass variable input: String from InstanceViewController to address: String? in loginWebViewController and load webview with this address. I succeeded loading webview but I can't seem to pass variable through segue moveToLoginWindow. I did everything I could possibly think but nothing worked. Can anyone tell me what I'm doing wrong?
To create a new instance of InstanceViewController inside another instance of the same type makes no sense and causes the issue.
You have to use input of the current instance:
override func prepare(for segue: NSStoryboardSegue, sender: Any?) {
input = "https://google.com"
if segue.identifier?.rawValue == "moveToLoginWindow" {
let destinationVC = segue.destinationController as! loginWebViewController
destinationVC.address = input
}
}
And as the passed type is non-optional declare address also as non-optional
var address = ""
class InstanceViewController: NSViewController{
#IBOutlet weak var InstanceAddr:NSTextField!
var input: String = ""
override func viewDidLoad(){
super.viewDidLoad()
}
override func prepare(for segue: NSStoryboardSegue, sender: Any?) {
InstanceViewController().input = "https://google.com" // Well actually in this line you are creating a new instance for your controller , that will not affect the input value of this controller So correction will be :-
self.input = "https://google.com"
if (segue.identifier?.rawValue == "moveToLoginWindow"){
let destinationVC = segue.destinationController as! loginWebViewController
destinationVC.address = input
}
}
}
class loginWebViewController: NSViewController{
#IBOutlet weak var instanceview: WKWebView!
var address: String?
override func viewDidLoad(){
var instanceaddress: String? = address // there is no need of create extra object as both are optional Prefer guard let instanceaddress = address else { return }
super.viewDidLoad()
var url = URL(string: instanceaddress!)
var request = URLRequest(url: url!)
instanceview.load(request)
}
}
This might help you :-
class InstanceViewController: NSViewController{
#IBOutlet weak var InstanceAddr:NSTextField!
var input: String = ""
override func viewDidLoad(){
super.viewDidLoad()
}
override func prepare(for segue: NSStoryboardSegue, sender: Any?) {
self.input = "https://google.com"
if (segue.identifier?.rawValue == "moveToLoginWindow"){
let destinationVC = segue.destinationController as! loginWebViewController
destinationVC.address = input
}
}
}
class loginWebViewController: NSViewController{
#IBOutlet weak var instanceview: WKWebView!
var address: String?
override func viewDidLoad(){
super.viewDidLoad()
guard let instanceAddress = address, let url = URL(string: instanceAddress) else { return}
var request = URLRequest(url: url)
instanceview.load(request)
}
}

On a button press to scroll through an array, my app crashes

When I press nextImage1 in the simulator, I get an error saying:
[Project_BodySwapp.ViewController nextImage:]: unrecognized selector sent to instance 0x7ffe4660a1e0'
import UIKit
class ViewController: UIViewController {
var imageNames1 = ["doghead","uk"]
var imageNames2 = ["macawLower","us"]
var pickedImage = String()
var currentImage = 0
#IBOutlet weak var displayImage: UIImageView!
//212x138
#IBOutlet weak var displayImage2: UIImageView!
//212x334
//BUTTON FUNCTIONALITY
//UPPER
#IBAction func randomizeImage(_ sender: Any) {
displayImage.image = UIImage(named: (produceRandomValue(imageNames1)))
}
#IBAction func nextImage1(_ sender: Any) {
currentImage += 1
displayImage.image = UIImage(named: imageNames1[currentImage])
}
#IBAction func previousImage1(_ sender: Any) {
}
//LOWER
#IBAction func randomizeImage2(_ sender: Any) {
displayImage2.image = UIImage(named: (produceRandomValue(imageNames2)))
}
func randomFromZero(to number: Int) -> Int {
return Int(arc4random_uniform(UInt32(number)))
}
func produceRandomValue(_ array: [String]) -> String {
let randomIndex = randomFromZero(to: array.count)
let pickedImage = imageNames1[randomIndex]
return pickedImage
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Any help would be greatly appreciated
Your button's action touchUpInside has been set as nextImage but in your code you don't have that. You have nextImage1 instead. Recheck the Connections Inspector.

Im getting the error = Cannot assign value of type 'String?' to type '[String]' Ive looked everywhere and i can't seem to find the answer

import UIKit
class FirstViewController: UIViewController
{
#IBOutlet var Dishname: UILabel!
#IBOutlet var TEXT: UITextField!
#IBOutlet var recipy: UIView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let secondVC: SecondViewController = segue.destinationViewController as! SecondViewController
secondVC.items = TEXT.text! as? String //Error
// Cannot assign value of type 'String?' to type '[String]'
}
The items variable in SecondViewController is Array of String, [String] type and you try to assign a String to it rather than insert or append into it.

Resources