How to access a property of one class from another class? - ios

I have one class:
class FoodListTable: UITableViewController
At the end of this class, I have a variable of the sum of numbers in an array:
var calorieTotal: Int {
return calorieNumberArray.reduce(0) { $0 + $1 }
}
I also have another class:
class Menu: Calculator { // Calculator is a class I had created earlier
In this class, I want to have a property that is the var calorieTotal: Int from class FoodListTable: UITableViewController. I have started this property:
let dividend =
How can I access the 'calorieTotal' property from the first class? I am very new to programming so please provide all the code possible. If you were wondering, I have looked for this question, but I still can't seem to figure it out?

Related

Copy fields between similar classes swift

I have two classes that are same but are present in different places. One inside framework and one in Normal App classes. I want to copy all the fields between them.
class Account {
var prodCode;
var subProdCode;
}
Same class inside the framework.
class Account {
var prodCode;
var subProdCode;
}
I need all fields to be copied from Object of 1st class to Object second class.
What is the best and easy way to do in Swift?
Add a method to MyAccout to update values of properties in your class, which accepts FrameworkAccount as parameter.
class MyAccout {
//...
func updateValues(account: FrameworkAccount) {
prodCode = account.prodCode
subProdCode = account.subProdCode
}
}

Array Data Through Different View Controllers Swift

Hey guys I'm working on my first ever app and need some help. My workout tracker app has two classes which you can find below. I have two view controllers hooked up to their own swift files.
Heres my first view controller
Basically what it does is takes the data in the text fields and steppers and turns it into a "Workout" object then appends it to the "WorkoutList" class array.
I've got a print statement setup that prints the Array.count. It shows the correct number in the debug but when I switch views it gets reset to zero.
#IBAction func addToWorkoutList(_ sender: UIButton) {
let workout = Workout(name: workoutName.text!, description: workoutDescription.text!, sets: Int(setStepper.text!)!, reps: Int(repStepper.text!)!)
workoutArrayList.append(workout)
print(workoutArrayList.count)
}
The second view inherits the first views class so that is how I access the "WorkoutArrayList"
class OverViewViewController: NewWorkoutViewController, UITableViewDelegate, UITableViewDataSource {
My app basically allows you to add a workout then produces a graph based on the data you provided. This can make it easy to visualize your gains in the gym. I'm doing this as a learning project so any help on what I should do to build this app would also be greatly appreciated.
Workout Object Class
import Foundation
class Workout {
let workoutName : String
let workoutDescription : String
let numberOfSets : Int
let numberOfReps : Int
init(name : String, description : String, sets : Int, reps : Int) {
workoutName = name
workoutDescription = description
numberOfSets = sets
numberOfReps = reps
}
}
WorkoutList Class
import Foundation
class WorkoutList {
let workoutArray : [Workout] = []
}
Inheriting the class is not what you want to do here. An easy fix for you would be to make workoutArray a static variable so any class can access it at any given time.
static var workoutArray : [Workout] = []
Here is why just inheriting the class doesn't work. When the OverViewViewController loads in to the app, it creates a new instance of the class OverViewViewController and since it inherits NewWorkoutViewController, it also creates a new instance of the NewWorkoutViewController class. You have 2 different instances of NewWorkoutViewController, changing a variable in one of those instances won't change it for any other instances of the class. A static variable, however, is what you are looking for. The array can be changed and accessed any time from any class, you don't even need to inherit. It would work whether you made workoutArray static or workoutArrayList static.
If you have any other questions, feel free to leave a comment.

Hiding access to a parent's property in the subclass

I feel like this should be relatively simple but I can't find a way to accomplish it.
Let say I have
class Parent {
public var file: PFFile?
}
and a subclass
class Child : Parent {
// some functionality that hides access to super.file
}
Problem is I can't mess with the Parent class, but I don't want anyone using the Child class to have access to 'file'. How can I accomplish this in Swift?
Perhaps this one fix it:
class Parent {
public var file: PFFile?
}
class RestrictedParent : Parent {
private override var file: PFFile?
}
class Child : RestrictedParent {
// some functionality that hides access to super.file
}
Here in RestrictedParent, we can hide any functionality that should not be visible to any of the child class inheriting to it.
EDIT:
A part from doc:
class Car: Vehicle {
var gear = 1
override var description: String {
return super.description + " in gear \(gear)"
}
}
As per Swift documentation
You can prevent a method, property, or subscript from being overridden
by marking it as final. Do this by writing the final modifier before
the method, property, or subscript’s introducer keyword (such as final
var, final func, final class func, and final subscript).
so you can declare parent class as
class Parent {
final var file: PFFile?
}
Or if you cannot modify parent class then maybe this would work
class Child : Parent {
override private final var file: PFFile?
}
I don't think this is directly possible in Swift 3. Here is the best workaround I could come up with:
class Child : Parent {
override public var file: PFFile? {
get { return nil }
set { }
}
func exampleFunction() {
print(super.PFFile?.description) // Use like this
print(PFFile?.description) // Don't do this
//This ^^^ will ALWAYS return nil for PFFile
}
}
This is sort of a hack, but it does almost exactly what you want. It doesn't completely hide the variable from the outside world, but it makes it impotent. When you try and access file you always get nil, and when you try and assign a value to file it just does nothing. So the outside world still knows that Child has a property file of type PFFile?, but it just can't do anything about it.
Essentially, file is like an attractive movie star. You can send them letters, post on their facebook wall, comment on their instagram feed, but they will never reply to you. You know who they are, and what they look like, but you just can't do anything about it.
Then, inside Child you MUST use super.file EVERYWHERE you access Parent's file property. If you use file or self.file you will be trying to interact with the impotent version, and you will do nothing and get nothing every time! I have included exampleFunction() as an example of this usage. (I made up the description property on PFFile, just assume it is a String)
You can use final modifier,like this :
class Perent {
final var file: PFFile?
}
class Child: Perent {
// code here ...
}

Methods in Swift

I have 2 classes in Swift in different Swift files, and I'm trying to call a method from the other class, and pass an integer as an argument. I have the following:
Class 1:
Inschatting.wentBack(Punten)
Class 2:
class Inschatting : UIViewController {
var Punten:Int = 0;
#IBOutlet var inschattingAdvies: UILabel!
func wentBack(Punten:Int) {
self.inschattingAdvies.text = Punten
}
}
Given error: Cannot convert value of type "Int" to expected argument type 'Inschatting'
Bonus question: Class 2 also complaints about the fact I want to put down a String, but it's clearly an Int
When you want to call your wentBack()-Func like above you should declare it as a class function... otherwise you should create an instance of Inschatting.
the problem is that Inschatting should declare the function the following way:
static func wentBack(Punten:Int) {
self.inschattingAdvies.text = Punten
}
But the problem is that, that you have an instance value the wentBack function.
self.inschattingAdvies
Now what you need to do is to make a decision:
1. you should call the wentback function on a Inschatting instance.
In Class A:
let instance = Inschatting()
instance.wentBack(5)
2. You should remove the self.inschattingAdvies from wentBack.
Answer to your bonus question:
"Punten" does not seem to be an integer, or an enum value at all to me.
Since your Inschatting class is a UIViewController, I suspect you want to display the data from your 1st class in your UIViewController. If this is indeed true your mistake is that you are using a Class instead of an instance of the class.
If you indeed want to display the data from your 1st class in your 2nd class (The VC), you will need to create a class instance of your second class.
let inschattingVC = Inschatting()
this way you can use inschattingVC.wentBack(someRandInt) to call your function and set the text accordingly.
Secondly your Punten in Inschatting.wentBack(Punten) is also probably not a variable but again an instance (or you should rename it. Variables should start with lowercase letters!!!).
So if you are creating a class instance using Inschatting() you should be able to use .wentBack(12345) to set the text in your class instance.
First you say :
#IBOutlet var inschattingAdvies: UILabel!
so inschattingAdvies is a UILabel
Then you have a function :
func wentBack(Punten:Int) {
self.inschattingAdvies.text = Punten
}
where you have Punten which is an integer. And then you try to set the text property of your label to punten.
Your code should be :
func wentBack(Punten:Int) {
self.inschattingAdvies.text = String(Punten)
}
note the cast to a string.
Not sure if that's the error you were getting, but it's definitely also an error.

In swift, how to refer to topmost class when my class has subclass of same name

In Swift:
How can I assign a topmost myObject to the innerObj variable?
Does swift have some sort of namespace operator that lets me create an myObject from global namespace?
Consider the code below.
//my object that can init with a message=string
class MyObject {
init(message: String) {
println(message)
}
}
//here I define a global works fine
let global = myObject(message: "this works")
//other class
class ViewController: UIViewController {
//defines an inner class with same name
class MyObject {
func failsFunction(){
//cannot invoke initializer for type "ViewController.myObject" with an argument of type (String)
let innerObj = myObject("how can I refer to the topmost myObject here?")
}
}
}
My first answer would be "don't do that." It's technically legal because the two classes have unique scope, but it's confusing as all hell, and will come back to bite you 6 months from now when you are coming back to this code and don't remember that you have a global class and a child class of ViewController with the same name.
If you are going to ignore that advice, Lou provided your solution: Create a typeAlias at the top level and use that inside your ViewController class so that you can reference the global class inside ViewController.
Secondly, class names should start with an upper-case letter. So class myObject should be class MyObject. This is a documented convention of the language.
Thirdly, myObject is a dreadful name for a class. It doesn't give you any idea what the class is for. Even if this is a learning exercise, you should still follow good coding practices. It trains good habits, and test code has a way of finding itself in real projects, or posted as demo code somewhere, or whatever.
You need to alias it before you hide it with:
typealias GlobalMyObject = MyObject
One usual way is to bind your outer class into struct. This pattern is quite similar to creating a namespace. You could do it like this
struct MyNameSpace {
class myObject {
init(message: String) {
print(message)
}
}
}
//here I define a global works fine
let global = MyNameSpace.myObject(message: "this works")
//other class
class ViewController: UIViewController {
//defines a subclass with same name
class myObject {
func failsFunction(){
//cannot invoke initializer for type "ViewController.myObject" with an argument of type (String)
let innerObj = MyNameSpace.myObject(message: "how can I refer to the topmost myObject here?")
}
}
}
Then, you could use both the classes and the compiler determines the use cases differently for both.

Resources