Swift4 Xcode9 Passing variable between ViewControllers through segue - 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)
}
}

Related

Cannot display title(String) and image from array to CollectionView in swift 4

I have a collection view and array with URLs of different images. I would like to display titles and images in the collection view. But I can't display and there is no error message found.
How can achieve it? In the console, all results can show. I have no idea how to do it.
import UIKit
import Foundation
import SwiftyJSON
class MainPageController: UIViewController, UICollectionViewDelegate,UICollectionViewDataSource{
public var foodImage = [UIImageView]()
public var foodTitle = [String]()
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
collectionView.dataSource = self
collectionView.delegate = self
return foodTitle.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! MainPageCollectionViewCell
cell.FoodTitle.text = self.foodTitle[indexPath.item]
//cell.Food.image = foodImage[indexPath.item] as? UIImage
return cell
}
var fullScreenSize :CGSize!
#IBOutlet weak var CollectionView: UICollectionView!
#IBOutlet weak var DisplayDateAndTime: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
//retrieve screen size
fullScreenSize =
UIScreen.main.bounds.size
// setup backgroud color
self.view.backgroundColor =
UIColor.white
fetchFoodList()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func getCurrentDateTime(){
let formatter = DateFormatter()
formatter.dateStyle = .long
//formatter.timeStyle = .medium
let str = formatter.string(from: Date())
DisplayDateAndTime?.text = str
}
}
extension MainPageController{
public func fetchFoodList(){
let url = URL(string: SomeUrlString)
let task = URLSession.shared.dataTask(with: url!){ (data, response, error) in
if error != nil{
print(error!)
} else {
if let urlContent = data{
do {
let json = try JSON(data:data!)
let recipes = json["hits"]
self.foodTitle = json["hits"].arrayValue.map {$0["recipe"]["label"].stringValue}
print(self.foodTitle)
var foodImage = json["hits"].arrayValue.map {$0["recipe"]["image"].stringValue}
print(foodImage)
print(self.foodImage)
}
catch{
print("JSON Processing Failed")
}
}
}
task.resume()
}
}
Here is the result in the console:
["Chicken Vesuvio", "Chicken Paprikash", "Chicken Gravy", "Catalan Chicken", "Persian Chicken", "Kreplach (Chicken Dumplings)", "Dijon Chicken", "Roast Chicken", "Chicken cacciatore", "Tarragon Chicken"]
["https://www.edamam.com/web-img/e42/e42f9119813e890af34c259785ae1cfb.jpg", "https://www.edamam.com/web-img/e12/e12b8c5581226d7639168f41d126f2ff.jpg", "https://www.edamam.com/web-img/fd1/fd1afed1849c44f5185720394e363b4e.jpg", "https://www.edamam.com/web-img/4d9/4d9084cbc170789caa9e997108b595de.jpg", "https://www.edamam.com/web-img/8f8/8f810dfe198fa3e520d291f3fcf62bbf.jpg"]
You have to set collectionView's datasource and delegate into your viewController's viewDidLoad not in (collectionView:numberOfItemsInSection:)
override func viewDidLoad() {
super.viewDidLoad()
collectionView.dataSource = self
collectionView.delegate = self
//retrieve screen size
fullScreenSize = UIScreen.main.bounds.size
// setup backgroud color
self.view.backgroundColor = UIColor.white
fetchFoodList()
}
You are trying to set your collectionView's delegate and datasource in a dataSource function (collectionView:numberOfItemsInSection:) which can not work.
Instead set the delegate and datasource in your viewController's viewDidLoad or since you are using storyboard directly in the interface builder.
override func viewDidLoad() {
super.viewDidLoad()
collectionView.delegate = self
collectionView.dataSource = self
//retrieve screen size
fullScreenSize = UIScreen.main.bounds.size
// setup backgroud color
self.view.backgroundColor = UIColor.white
fetchFoodList()
}
Make also sure to call collectionView.reloadData() in the completion block of fetchFoodList().
func fetchFoodList() {
let url = URL(string: SomeUrlString)
let task = URLSession.shared.dataTask(with: url!){ (data, response, error) in
if error != nil{
print(error!)
} else {
if let urlContent = data{
do {
let json = try JSON(data:data!)
let recipes = json["hits"]
self.foodTitle = json["hits"].arrayValue.map {$0["recipe"]["label"].stringValue}
print(self.foodTitle)
var foodImage = json["hits"].arrayValue.map {$0["recipe"]["image"].stringValue}
print(foodImage)
print(self.foodImage)
DispatchQueue.main.async {
self.collectionView.reloadData()
}
}
catch{
print("JSON Processing Failed")
}
}
}
task.resume()
}

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

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

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.

Resources