Let's say I have
struct cat {
var paws: int
var name: string
var breed: string
}
How would i go about segueing an instance to a new destination controller? Particularly, this instance from an array to a new DC?
prepare for segue
{
if segue.identifier == "segue"
var nextVC = segue.desitnationviewcontroller as ...
nextvc.instance = ?
}
You can just assign it like this:
let someCat = cat(paws: 4, name: "Kitty", breed: "Unknown")
let arrayCat = [cat(paws: 5, name: "Mutant", breed: "Unknown"),
cat(paws: 4, name: "John", breed: "Doe")]
var nextVC = segue.desitnationviewcontroller as SomeViewController
nextVC.somePropertyName = someCat // or arrayCat if you're using an array
In your SomeViewController, you'll have to have a property with type cat and you can just assign it. For example:
class SomeViewController: UIViewController {
var somePropertyName: cat? // [cat]() if it's an array of type cat
}
Also, for your convenience I added a link to Apple's documentation of Swift. The link is here.
Related
I'm trying to learn how to use NSTableViewDiffableDataSource to load data with NSTableView. I am able to use UITableViewDiffableDataSource and UICollectionViewDiffableDataSource to load data in iOS because I have found some examples online. But I am not able to use NSTableViewDiffableDataSource in Cocoa.
In the following case, I have a subclass of NSTableCellView named TestTableCellView, which shows three fields: First name, Last name, and his or her date of birth in String.
import Cocoa
class ViewController: NSViewController {
// MARK: - Variables
var dataSource: NSTableViewDiffableDataSource<Int, Contact>?
// MARK: - IBOutlet
#IBOutlet weak var tableView: NSTableView!
// MARK: - Life cycle
override func viewWillAppear() {
super.viewWillAppear()
let model1 = Contact(id: 1, firstName: "Christopher", lastName: "Wilson", dateOfBirth: "06-02-2001")
let model2 = Contact(id: 2, firstName: "Jen", lastName: "Psaki", dateOfBirth: "08-25-1995")
let model3 = Contact(id: 3, firstName: "Pete", lastName: "Marovich", dateOfBirth: "12-12-2012")
let model4 = Contact(id: 4, firstName: "Deborah", lastName: "Mynatt", dateOfBirth: "11-08-1999")
let model5 = Contact(id: 5, firstName: "Christof", lastName: "Kreb", dateOfBirth: "01-01-2001")
let models = [model1, model2, model3, model4, model5]
dataSource = NSTableViewDiffableDataSource(tableView: tableView, cellProvider: { tableView, tableColumn, row, identifier in
let cell = tableView.makeView(withIdentifier: NSUserInterfaceItemIdentifier(rawValue: "cell"), owner: self) as! TestTableCellView
let model = models[row]
cell.firstField.stringValue = model.firstName
cell.lastField.stringValue = model.lastName
cell.dobField.stringValue = model.dateOfBirth
return cell
})
tableView.dataSource = dataSource
guard let dataSource = self.dataSource else {
return
}
var snapshot = dataSource.snapshot()
snapshot.appendSections([0])
snapshot.appendItems(models, toSection: 0)
dataSource.apply(snapshot, animatingDifferences: true, completion: nil) // <--- crashing...
}
}
struct Contact: Hashable {
var id: Int
var firstName: String
var lastName: String
var dateOfBirth: String
}
Hmm... The application crashes with an error "Invalid parameter not satisfying: snapshot." A couple of days ago, I tested another example, which also crashed at the same line (dataSource.apply). I don't find many examples involving NSTableViewDiffableDataSource online. The only example I have found is this topic, which doesn't help. Anyway, what am I doing wrong? My Xcode version is 13.1. Thanks.
Create a snapshot like this and it should work:
guard let dataSource = self.dataSource else {
return
}
var snapshot = NSDiffableDataSourceSnapshot<Int, Contact>()
snapshot.appendSections([0])
snapshot.appendItems(models, toSection: 0)
dataSource.apply(snapshot, animatingDifferences: false)
I get the following error when trying to pass data from one viewcontroller to another: "Cannot assign value of type 'activityTableViewController.request' to type 'activityDetailTableViewController.request?'"
What am I doing wrong?
First view controller:
class activityTableViewController: UITableViewController {
struct request {
var fromDateAndTime: String
var toDateAndTime: String
var createdBy: String
init(fromDateAndTime: String, toDateAndTime: String, createdBy: String) {
self.fromDateAndTime = fromDateAndTime
self.toDateAndTime = toDateAndTime
self.createdBy = createdBy
}
}
var requestList: [request] = []
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "activityToDetail" {
if let nextViewController = segue.destination as? activityDetailTableViewController {
let indexPath = tableView.indexPathForSelectedRow
nextViewController.requestDetail = requestList[indexPath!.row]
}
}
}
}
Second view controller:
class activityDetailTableViewController: UITableViewController {
struct request {
var fromDateAndTime: String
var toDateAndTime: String
var createdBy: String
init(fromDateAndTime: String, toDateAndTime: String, createdBy: String) {
self.fromDateAndTime = fromDateAndTime
self.toDateAndTime = toDateAndTime
self.createdBy = createdBy
}
}
var requestList: request!
}
First of all please conform to the naming convention that class and struct names start with a capital letter.
Both structs seem to be the same but they are different objects because they are declared in different name spaces.
Create one struct outside of any class and delete the initializer because you get it for free.
struct Request {
var fromDateAndTime: String
var toDateAndTime: String
var createdBy: String
}
You need to only have 1 struct as it will be visible inside all the app , and get it out of any class
struct Request {
var fromDateAndTime,toDateAndTime,createdBy: String
}
plus there is no need to write init inside a struct type , and start it with capital letter
There is no availability to declare a struct with the same name as another it's a language logical constraint
I am trying to get my ingredients name (FoodName) which is in the class SpecificFood. The meal class has a property mealIngredients which contains ingredients objects.
Now in the table view I am trying to refer to the foodName in the mealingredients such, however, it doesn't find the foodName because that is referring to the SpecificFood rather than the meal class. I input the names for everything and the ingredients into different foods in a separate model class.
If there is better way of doing this then please do let me know as I'm new to swift and programming.
Any help would be much appreciated.
let meal = self.selectedMeal
let ingredientTitle = meal?.mealIngredients[indexPath.row].FoodName
cell.textLabel?.text = String(ingredientTitle)
return cell
I have made reference to all the different classes in the top such;
var myMeals:Array = [Meal]()
var meals:[Meal] = [Meal]()
var ingredients:[SpecificFood] = [SpecificFood]()
My meal class is such;
class Meal: NSObject {
var mealTitle:String = ""
var mealID:String = ""
// var mealIngredients:NSArray = [NSObject]()
var mealIngredients:NSArray = [SpecificFood]()
}
My SpecificFood class is such;
class SpecificFood: NSObject {
var foodName = ""
var foodGroup = ""
}
Then my model is like such; (I've taken some of the other foods and ingredients but this gives the jist.
class MealModel: NSObject {
var ingredients:[SpecificFood] = [SpecificFood]()
func getMeals() -> [Meal] {
var allFoods = [SpecificFood]()
let meat = String()
let chicken = SpecificFood()
let rice = SpecificFood()
// Assign properties of the SpecificFoods
chicken.foodName = "Chicken"
chicken.foodGroup = meat
// Add foods to my food array
allFoods.append(chicken)
// Create a meal objects
var meal1 = Meal()
// Assign properties
meal1.mealIngredients = [chicken, rice, tomatoeSauce]
The top two pieces of code refer to the class with the tableView in. It has no other code in apart from var selectedMeal:Meal?
Without seeing your class variables it is a bit hard... I'll post this generic example:
class firstViewController: UIViewController {
var someVariable: SomeType = someValue
var someVariable2: SomeType = someValue
init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
}
}
Then instantiate the view:
var myCustomViewController: firstViewController = firstViewController(nibName: nil, bundle: nil)
var variable = myCustomViewController.someVariable
var variable2 = myCustomViewController.someVariable2
If you have
meal1.mealIngredients = [chicken, rice, tomatoeSauce]
then you access chicken's name and food group with:
meal1.mealIngredients[0].foodName // Chicken
meal1.mealIngredients[0].foodGroup // meat
You may want to consider using structs instead of classes (unless you're already using inheritance).
struct SpecificFood {
var foodName = ""
var foodGroup = ""
}
struct Meal {
var mealTitle:String = ""
var mealID:String = ""
var mealIngredients: [SpecificFood]
}
Your code becomes:
let chicken = SpecificFood(foodName: "Chicken", foodGroup: "meat")
var meal1 = Meal(mealTitle: "Chicken and Rice", mealID: "45634", mealIngredients: [])
and you access the properties with the dot (.) syntax.
I am looking to have a data model that is created by the user in the main View Controller and then passed into other view controllers via prepareForSegue.
However in my View Controller I am unable to use the model and I get errors for unwrapped optional values.
I have :
Class Collection: NSObject {
var id: String!
var image: String!
var apples: Int?
var oranges: Int?
var lemons: Int?
}
init(id: String, image: String, apples: Int, oranges: Int, lemons: Int) {
super.init()
self.id = id
self.photo = photo
self.apples = apples
self.oranges = oranges
self.lemons = lemons
}
View Controller:
var collection: Collection!
...
// if user selects a number ..
self.collection.oranges = usersSelection
self.collection.apples = usersSelection
etc
Can anyone tell me what I'm doing wrong please?
Thank you!
Define your model class like this:
class Collection: NSObject {
var id: String!
var image: String!
var apples: Int?
var oranges: Int?
var lemons: Int?
init(id: String, image: String, apples: Int?, oranges: Int?, lemons: Int?) {
super.init()
self.id = id
self.image = image
if let _ = apples{
self.apples = apples
}
if let _ = oranges{
self.oranges = oranges
}
if let _ = lemons{
self.lemons = lemons
}
}
}
Then implement in your ViewController like this:
class ViewController: UIViewController {
var collection: Collection!
override func viewDidLoad() {
collection = Collection(id: "user selection", image: "useselection", apples: nil, oranges: nil, lemons: nil)
// collection.image =
// colection.oranges =
// ........
}
}
This question already has an answer here:
Swift Access Controll Example
(1 answer)
Closed 8 years ago.
i have this Class in my ViewController.swift for example ...
class Person {
internal let name: String
init(name: String) {
self.name = name
}
}
class ViewController: UIViewController {
}
and in my SecondViewController i have
override func viewDidLoad() {
super.viewDidLoad()
let person = Person(name: "")
println(person.name)
}
How can I assign a value a name from the internal of the view controller class ?
Just create an instance of it:
var person = Person(name: "Person Name")
I don't know what you are going to do with it - it can be either a local variable in a view controller method, or a view controller property.
You can use this to create an instance and it's name property
var personsName = Person(name: "persons name")