I'm pretty new to Swift. I'm creating an application that allows a user to create registration forms. I have two files/scenes, FirstViewController, and SecondViewController. The SecondViewController allows the user to create a question. The FirstViewController will display all the created questions in a UITableView. In my SecondViewController I have a class called Question which basically helps me create a question, it is shown below for context.
class Question {
var Label: String
var required: Int
// create question
init (Label: String, required: Int) {
self.Label = Label
self.required = required
}
}
class textInput: Question {
var placeHolder: String
init (placeHolder: String, Label: String, required: Int) {
self.placeHolder = placeHolder
super.init(Label: Label, required: required)
}
}
class multiChoice: Question {
var answers: [String]
init(answers: [String], Label: String, required: Int) {
self.answers = answers
super.init(Label: Label, required: required)
}
}
In the FirstViewController I need to create an array of that type to keep a running list of all the questions in the UITableView...
var formQuestions: [Question]
Obviously the FirstViewController does not have access to this custom object type. My question is how do I make it so that it does? I could copy and paste the entire class over to my FirstViewController but that would be terrible programming...
Thanks for the help.
Your FirstViewController doesn't have access to the Question class and its subclasses because they are all declared in SecondViewController. This means they are local to SecondViewController and nowhere else can access it. What you need to do is to make the question class global.
So at the moment your classes are like: (contents omitted)
class SecondViewController: UIViewController {
class Question {
}
class TextInputQuestion: Question {
}
class MultiChoiceQuestion: Question {
}
}
You should move them out of the SecondViewController:
class SecondViewController {
}
class Question {
}
class TextInputQuestion: Question {
}
class MultiChoiceQuestion: Question {
}
Oh by the way, I renamed your class names! You should always use PascalCase for classes and I think adding the word Question would be more descriptive of what they are.
Related
VC = ViewController
VM = ViewModel
P = Protocol
I have ViewModel protocols & classes in the format
protocol BaseVMP {
}
protocol VM1P: BaseVMP {
}
protocol VM2P: BaseVMP {
}
class BaseVM: BaseVMP {
}
class VM1: BaseVM, VM1P {
}
class VM2: BaseVM, VM2P {
}
ViewController classes
class BaseVC {
var baseVM: BaseVMP
}
class VC1: BaseVC {
var vm: VM1P
}
class VC2: BaseVC {
var vm: VM2P
}
As of now, I am keeping 2 variables for viewModel, one as vm and another one as baseVM in VC & baseVC respectively. What I want to achieve is that I keep just one variable vm in BaseVC which gets typecasted (if this is the correct term, I hope you got the meaning) to VM1P/VM2P when I want to access it in VC1/VC2. Is it possible with the help of generics?
With your class hierarchy you can have your BaseVC, VC1, VC2, structure something like,
class BaseVC<T:BaseVMP> {
var vm: T
init(vm: T) {
self.vm = vm
}
}
class VC1<T: VM1P>: BaseVC<T> {
}
class VC2<T: VM2P>: BaseVC<T> {
}
let vc1 = VC1(vm: VM1())
let vc2 = VC2(vm: VM2())
Note, vm property is inherited in all the subclasses and for VC1 and VC2, they are of specific types VM1 and VM2. I hope this is what you were looking for.
By the way, you should either have initializer or make property implicitly unwrapped just so that there is no error.
You already have that, BaseVMP can both hold an instance of VM1P and VM2P since they both comply to BaseVMP protocol.
class BaseVC
{
var baseVM: BaseVMP! // Be sure that's initialized before use.
}
class VC1: BaseVC
{
func setVM(vm: BaseVMP)
{
baseVM = vm as! VM1P // VM1P implements BaseVMP
}
}
In Swift 3.2 this (let id = row.tableViewCellClass?.reuseIdentifier) worked:
class DrillDownTableViewCell {
class var reuseIdentifier: String
{
return String(describing: self)
}
}
class RowViewModel: NSObject
{
var tableViewCellClass: AnyClass?
}
class Foo {
var row : RowViewModel?
func setup() {
row = RowViewModel()
row?.Class = DrillDownTableViewCell.self
}
func doThings() {
let id = row?.tableViewCellClass?.reuseIdentifier
}
}
After my Swift 4 update, it's showing "Instance member 'reuseIdentifier' cannot be used on type 'AnyObject'.
How would I access a class variable on a class who's metaType information is stored in an AnyClass variable?
(I assume you mean to have a ? after row in doThings(). I assume that's a typo and not part of the question. There are several other ? missing here and some other typos that I won't dive into.)
If you expect tableViewCellClass to have a reuseIdentifier class property, then it isn't of type AnyClass. There are many classes that don't have that property. You want classes that conform to a protocol:
protocol Identifiying {
static var reuseIdentifier: String { get }
}
So your model requires an Identifying class:
class RowViewModel: NSObject {
var tableViewCellClass: Identifiying.Type?
}
Then you can use this as you're expecting.
I am wondering how to reference a class type within another class for instance (a rough Sketch not a true example) I have two classes:
class Class1: UIViewController {
var a = self
}
class Class2: SKScene {
//How do I get a to equal the same thing as it equals in class 1?
var a = //??????????
}
How can I get the same a value in Class2 as in class 1. essentially references class2's self value in another class. Thanks in advance.
As much detail you have provided in question, based on that i can give you this solution:
class Class1: UIViewController {
static let sharedInstance : Class1= {
let instance = Class1()
return instance
}()
}
class Class2: SKScene {
var a = Class1.sharedInstance
}
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")
This is a weird one. I have several classes so far in a test app and everything has been going swimmingly. However, I'm getting the error EpisodePlayerController.Type does not have a member named episodeData when I declare otherThing below.
import UIKit
class EpisodePlayerController: UIViewController {
var episodeData = "Hi"
var otherThing = episodeData
}
Tried restarting Xcode, restarting Mac, recreating the class, renaming the class, etc. At a loss. Might be a bug in my Xcode install, but I'd love to be wrong and not have wait for another release. ;)
This seems to solve the problem:
class EpisodePlayerController: UIViewController {
var episodeData = "Hi"
var otherThing = ""
init(){
otherThing = episodeData
}
}
Take a look at the property reference.
The problem is that as far as Swift is concerned, none of your properties have values until the class is fully initialized. Before that point, you can't interact with 'self' implicitly. (this includes its properties and functions.) I think your class is a good candidate for the #lazy attribute:
import UIKit
class EpisodePlayerController: UIViewController {
var episodeData: String = "Hi"
#lazy var otherData: String = self.episodeData
}
You could also include more complex stuff if you need to:
import UIKit
class ClassTwo {
var episodeData = "Hi"
#lazy var otherData: String = {
// Additional parameters
return self.episodeData
}()
}
This way, you can access self because the property 'otherData' won't be called until 'episodeData' is fully initialized.
Because this view was being called via a segue, I wound up making the variable optional and then calling a function from the segue to set the optional variable and then trigger any function dependent on that variable:
import UIKit
class YourController: UIViewController {
var yourData:NSString?
func setYourData(value:NSString) {
self.yourData = value
dependentFunction()
}
A similar effect can be achieved using the didSet and/or willSet methods:
import UIKit
class YourController: UIViewController {
var yourData:NSString? {
didSet {
// Dependent functionality
}
}
func setYourData(value:NSString) {
self.yourData = value
}
Also, for reference, the segue looks like this:
func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
if segue.identifier == "yourSegue" {
var destination:YourController = segue.destinationViewController as YourController
destination.setYourData(someData)
}
}
i think this code will help.
class Square: NamedShape {
var sideLength: Double
init(sideLength: Double, name: String) {
self.sideLength = sideLength
super.init(name: name)
numberOfSides = 4
}
func area() -> Double {
return sideLength * sideLength
}
override func simpleDescription() -> String {
return "A square with sides of length \(sideLength)."
}
}
let test = Square(sideLength: 5.2, name: "my test square")
test.area()
test.simpleDescription()”