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

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.

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

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

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!
}

Fatal error: unexpected found nil while unwrapping an Optional value

I have a problem with an array of data, in this data array I send the name of 6 images so that later they are loaded in a CollectionView, the 6 images load well, without any problem, but when I add a String value to send it gives me a error that is empty:
This is my class where is my data array:
import UIKit
class HBook{
var imagenB: UIImage!
var estatus: String!
init(estatus: String, imagenB: UIImage) {
self.estatus = estatus
self.imagenB = imagenB
}
class func getData() -> [HBook]{
let rawData = [
["imagenB":"book1"],
["imagenB":"book2"],
["imagenB":"book3"],
["imagenB":"book4"],
["imagenB":"book5"],
["imagenB":"book6"],
["estatus":"No reservado"]
]
var hbook:[HBook] = []
for item in rawData{
hbook.append(HBook(estatus: item["estatus"]!, imagenB: UIImage(named: item["imagenB"]!)!))
}
return hbook
}
}
I print my data array to see which variable is empty, but apparently all have an assigned value:
I do not know why I'm sending an empty value.
This information was retrieved in another class that has a CollectionView and a Label, the method where I passed the information is in the cellForItemAt method:
class DetailViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
#IBOutlet weak var contenedorCollection: UIView!
#IBOutlet weak var myCollection: UICollectionView!
#IBOutlet weak var pages: UIPageControl!
#IBOutlet weak var estatus: UILabel!
var hbook = HBook.getData()
var nombreH = ""
override func viewDidLoad() {
super.viewDidLoad()
pages.numberOfPages = hbook.count
self.title = nombreH
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return hbook.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CellCollectionViewCell
cell.imageview.image = hbook[indexPath.row].imagenB
estatus.text = hbook[indexPath.row].estatus
return cell
}
I think the problem is in data class. Please replace your HBook class with following code and it will work without any further change :
class HBook{
var imagenB: UIImage?
var estatus: String?
init(estatus: String? = nil, imagenB: UIImage? = nil) {
self.estatus = estatus
self.imagenB = imagenB
}
class func getData() -> [HBook]{
let rawData = [
["imagenB":"book1","estatus":"No reservado"],
["imagenB":"book2","estatus":"No reservado"],
["imagenB":"book3","estatus":"No reservado"],
["imagenB":"book4","estatus":"No reservado"],
["imagenB":"book5","estatus":"No reservado"],
["imagenB":"book6","estatus":"No reservado"]
]
var hbook:[HBook] = []
for item in rawData{
if let image = item["itemnB"]{
hbook.append(HBook(estatus: item["estatus"], imagenB:UIImage(named:image)))
}else{
hbook.append(HBook(estatus: item["estatus"]))
}
}
return hbook
}
}

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

Passing data between TabBarController, not updating label

I´m trying to pass data between TabBarController using this example
Problem is, that the label in ViewController2 won´t update.
Here is the code I´m using:
TabBarController:
import UIKit
class CustomTabBarController: UITabBarController {
var myInformation: [String ] = []
override func viewDidLoad() {
super.viewDidLoad()
}
ViewController1:
class ViewController1: UIViewController {
var items = [String]()
#IBOutlet weak var label: UILabel!
#IBAction func item1(_ sender: UIButton) {
items += ["Audi"]
print(items)
}
override func viewDidLoad() {
super.viewDidLoad()
if let tbc = self.tabBarController as? CustomTabBarController {
tbc.myInformation = items
}
}
ViewController2
class ViewController2: UIViewController {
#IBOutlet weak var label: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
if let tbc = self.tabBarController as? CustomTabBarController {
for item in tbc.myInformation {
label.text = item
}
}
}
I guess, since
if let tbc = self.tabBarController as? CustomTabBarController {
tbc.myInformation = items
}
is in viewDidLoad, it won't update when the item1 button is pushed?
But X-code won't allow me to put it elsewhere.
How should I go about to get the button to update the array?
I think issue is there in Controller 1:
if let tbc = self.tabBarController as? CustomTabBarController {
tbc.myInformation = items
}
Because you are calling this in ViewDidLoad, and ViewDidLoad is only call when your view is load in memory. You need to update values when you are appending values in your controller 1's arrays.
you have to update myInformation array in:
#IBAction func item1(_ sender: UIButton) {
items += ["Audi"]
if let tbc = self.tabBarController as? CustomTabBarController {
tbc.myInformation = items //OR// tbc.myInformation.append("Audi")
}
print(items)
}

Resources