can't change property on parent class - ios

I have a view controller class:
class PostImageController: UIViewController {
var textToChange:String = "original"
//Action run to change the text:
#IBAction func temp(sender: AnyObject) {
className().changeText()
println(textToChange)
}
}
The goal here, is to change "original" by "new Text" from an other file containing a class.
I tried this in the class file that is called in the view controller:
class className: PostImageController {
func changeText() {
super.textToChange = "New text"
}
}
Which does strictly nothing.
and this instead of previous exemple still in the class file:
override var textToChange: String {
return "Modified !!"
}
which I cannot even build with because of error message: "Cannot override mutable property with read-only property 'textToChange'".
The goal here, is to be able to change a property from a subclass file. If you have a clue why, please advise.

use self instead of super here
func changeText() {
self.textToChange = "New text"
}
Another solution will be to initialise textTochange in the init method of your subclass like this :
init() {
super.init()
self.textToChange = "Modified !!"
}
But the real problem here is that you print textToChange in the super class. Try this :
#IBAction func temp(sender: AnyObject) {
var subclassObject = className().changeText()
println(subclassObject.textToChange)
}

Related

Access data / functions from several view controllers

I am trying to build an app with several screens. Every screen should have different buttons which all call one function.
My problem is that I do not understand how to call one function from different view controllers with input parameters.
Also I want to have another variable defined accessible and changeable from every view controller.
This is what I kind of want my code to be:
import UIKit
var address = "address"
public func makeRequest(Command: String){
let url = URL(address + Command)
print(url)
}
class MainViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let command = "command"
makeRequest(Command: command)
}
}
class SecondViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
print("address")
address = "address2"
}
}
If all classes are view controllers put the method in an extension of UIViewController and the address constant in a struct
struct Constant {
static let address = "address"
}
extension UIViewController {
public func makeRequest(command: String) -> URL? {
guard let url = URL(string: Constant.address + command) else { return nil }
print(url)
return url
}
}
extension UIViewController{
func getName(name: String)-> String{
print("hai \(name)")
return name
}
}
you can write a extension for Viewcontroller and try to call the method like this. if you write the extension for viewcontroller you can directly call them with its reference
self.getName(name:"Raghav")

passing data between view controllers without changing views

I want to pass data between two view controllers, but don't want the view to change when the users presses my save data button.
The users needs to fill in multiple data fields, and when finish can press another button to go to the second view controller.
I found many tutorials how to pass data using segue, but they all change view as soon as the 'save button is pressed'.
Any one can explain to me how to alter the code?
#Phillip Mills: here is how I used your code. (what am I doing wrong?)
code:
//////// declaring classes on FirstViewController (trying it first on only one ViewController)
class FakeVC1 {
func userInput() {
DataModel.shared.username = outbj14u.text
}
class FakeVC2 {
func viewAppears() {
if let name = DataModel.shared.username {
outbj14p.text = name
print("I have nothing to say")
}
}
}
class DataModel {
static let shared = DataModel()
var username: String?
}
////till here
//// here is where i call the functions
override func viewDidAppear(_ animated: Bool) {
FakeVC1().userInput()
FakeVC2().viewAppears()
if let xbj14p = UserDefaults.standard.object(forKey: "outbj14p") as? String
{
outbj14p.text = xbj14p
}
if let xbj14u = UserDefaults.standard.object(forKey: "outbj14u") as? String
{
outbj14u.text = xbj14u
}
////
#Phillip Mills: Below is what I have know. I think I got the code on the FirstViewController right, but the code on the Second View controller must be wrong. I don't get any errors, but the text field on the SecondViewController remains unchanged after putting input on in the FirstViewController
//// Code on the FirstViewController
class DataModel {
static let shared = DataModel()
var username: String?
}
#IBAction func savebj14p(_ sender: Any) {
outbj14p.text = inbj14p.text
DataModel.shared.username = outbj14p.text
UserDefaults.standard.set(inbj14p.text, forKey: "namebj14p")
}
//and on the SecondViewController
#IBOutlet weak var bj14u: UILabel! // connected to a label
//and
class DataModel {
static let shared = DataModel()
var username: String?
}
override func viewDidAppear(_ animated: Bool) {
if let name = DataModel.shared.username {
bj14u.text = name
}
}
In your case, don't pass data.
Create a shared object to act as your data model. When users fill in the fields, update the data model.
When the user moves to the second controller/view, that controller uses the data model object to show what it needs to.
class FakeVC1 {
func userInput() {
DataModel.shared.username = "Me"
}
}
class FakeVC2 {
func viewAppears() {
if let name = DataModel.shared.username {
print(name)
} else {
print("I have nothing to say")
}
}
}
class DataModel {
static let shared = DataModel()
var username: String?
}
FakeVC1().userInput()
FakeVC2().viewAppears()
If you need to pass value to another viewcontroller without changing the view , you can user NSNotificationCenter class
Refer this link for more details
NSNotificationCenter addObserver in Swift
what i will recommend is to use a global variable or array, you will have the info in all view controllers and you will be able to call it in your new view controller.

Access variable in a function which is called from another class

I have a class1 which is having many variable and also having one function within a class1.I am calling the function from another class class2.function triggered but i cannot access variable of class1.
here is the sample code
class ViewController: UIViewController {
var Flat:String?
var Flong:String?
var Tlat:String?
var Tlong:String?
override func viewDidLoad() {
super.viewDidLoad()
Flat = "flat value";
Flong="flong value";
Tlat="Tlat value";
Tlong="tlong value";
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func calculation()
{
print("origin_lat new\(Flat)")
print("origin_lng new\(Flong)")
print("dest_lat new\(Tlat)")
print("dest_lng new\(Tlong)")
}
}
I am calling calculation method from another class Collectionviewcell click function
var mycontroller : ViewController = ViewController()
mycontroller.calculation()
Why i could not access the values anyone help me?
You can also reach other controller's variables with defining global variables like this way:
class Class1ViewController: UIViewController {
struct GlobalVariables{
static var Flat:String?
static var Flong:String?
static var Tlat:String?
static var Tlong:String?
}
override func viewDidLoad() {
super.viewDidLoad()
Flat = "flat value";
Flong="flong value";
Tlat="Tlat value";
Tlong="tlong value";
}
...
}
And you can use these variables in another view controller:
class Class2ViewController: UIViewController
{
...
print(Class1ViewController.GlobalVariables.Flat)
print(Class1ViewController.GlobalVariables.Flong)
print(Class1ViewController.GlobalVariables.Tlat)
print(Class1ViewController.GlobalVariables.Tlong)
...
}
Actually, the "viewDidLoad()" function is not called. It's will be called when you display the viewController, for example, a UINavigationController push it. In your case, you just created the viewController, not displayed it. If you want to init these variables without displaying the viewController, you need to do this:
class ViewController: UIViewController {
var Flat:String?
var Flong:String?
var Tlat:String?
var Tlong:String?
required init?(coder:NSCoder) {
super.init(coder:coder)
self.customInit()
}
override init(nibName: String?, bundle: Bundle?) {
super.init(nibName: nibName, bundle: bundle)
self.customInit()
}
func customInit() {
Flat = "flat value";
Flong="flong value";
Tlat="Tlat value";
Tlong="tlong value";
}
//.......
}
What your trying to achieve is a kind of model class. I would suggest you create a simple model class which is not subclass of UIViewcontroller like so.
class Model: NSObject {
var fLat: String?
var fLong: String?
var tLat: String?
var tLong: String?
override init() {
super.init()
fLat = "flat value"
fLong = "flong value"
tLat = "tlat value"
tLong = "tlong value";
}
// for print I have forced unwrapped so remember to check before force unwrapping smi)e
func calculation() {
print("orgin_lat new\(fLat!)")
print("origin_lng new\(fLong!)")
print("origin_lat new\(tLat!)")
print("origin_lng new \(tLong!)")
}
}
Now inside your main View controller you can initialize and call the function like so
let model = Model()
model.calculation()

Get child class from parent

I have a big issue in Swift programming. I am trying to get the name of child class from the parent. This is a sample example, what i want to do:
class Parent {
class func sayHello() {
let nameChildClass = //
println("hi \(nameChildClass)")
}
}
class Mother: Parent {
}
class Father: Parent {
}
Mother.sayHello()
Father.sayHello()
I know there is some other way do to that, but i really need to it like that.
You can use a function like this:
func getRawClassName(object: AnyClass) -> String {
let name = NSStringFromClass(object)
let components = name.componentsSeparatedByString(".")
return components.last ?? "Unknown"
}
which takes an instance of a class and obtain the type name using NSStringFromClass.
But the type name includes the namespace, so to get rid of that it's split into an array, using the dot as separator - the actual class name is the last item of the returned array.
You can use it as follows:
class Parent {
class func sayHello() {
println("hi \(getRawClassName(self))")
}
}
and that will print the name of the actual inherited class
From Swift 5.2
String(describing: Self.self)
You have to override the sayHello function in your child classes:
class Parent {
class func sayHello() {
println("base class")
}
}
class Mother: Parent {
override func sayHello() {
println("mother")
}
}
class Father: Parent {
override func sayHello() {
println("father")
}
}
mother = Mother()
father = Father()
mother.sayHello()
father.sayHello()

Swift declare class in class

Let me explain my question with an Example.
class Mother: NSObject {
var momVar:Int =5
var subClass : child(mylevel:5) // <-- ******** Error //
init(){
momVar=1000
level=1
}
func print(){
NSLog("%d",momVar);
}
func subMethod(){
subClass =child(myVar: 5) // <== Doesnt Work either
yazdir()
}
}
below child class:
class child:Mother{
var someVar:Int=1
init(myVar:Int) {
super.init()
someVar = myVar
}
}
I want to use "child" class in "Mother" class. But i got " not initialized at super.init call" error. Other view controller calls "Mother" class with "print" method such as:
#IBAction func buttonTest(sender : AnyObject) {
var mom=Mother()
mom.yazdir()
}
The question is How i can use "child" class in "Mother" class?
Thank you
this line of code is not correct syntactically as is:
var subClass : child(mylevel:5)
you need to define the type after the : (before the = if there is any) or you can use it without explicit type, like:
var subClass = child(mylevel:5)

Resources