Swift: inherited objects - ios

I am getting a strange message when I use a derived class for a function with the base class as argument:
class Vehicle: Object, Mappable, Hashable, Equatable {
...
}
class Car: Vehicle {
...
}
class TransportFactory: NSObject{
func doSomethingWithVehicles(vehicles:[Vehicle]){
...
}
}
class CarFactory: TransportFactory{
let myCars = [Car]()
doSomethingWithVehicles(myCars)
}
This results in: "Cannot convert value of type '[Car]' to expected argument type '[Vehicle]'"
Object is a class (Realm), Mappable a protocol (AlamofireMapper), Hashable and Equatable a protocol from Foundation

You're declaring myCars without a type and assigning it an Array containing your Car class, so type inference is literally giving you an Array with your class object inside. Try:
let myCars = [Car]()
self.doSomethingWithVehicles(myCars)
This is why I prefer the Array<Car> syntax rather than the [Car]. I feel the code is clearer/safer, as let myCars = Array<Car> would have just not compiled.

You need to wrap doSomethingWithVehicles in a function, you can't just have it hanging out in the class scope:
class Vehicle: NSObject {
// ...
}
class Car: Vehicle {
// ...
}
class TransportFactory: NSObject {
func doSomethingWithVehicles(vehicles:[Vehicle]){
// ...
}
}
class CarFactory: TransportFactory {
let myCars = [Car]()
func someFunc() {
self.doSomethingWithVehicles(myCars)
}
}
myCars can be at the class scope because it is a class variable.

import Foundation
class Vehicle: NSObject{
}
class Car: Vehicle {
}
class TransportFactory: NSObject{
func doSomethingWithVehicles(vehicles:[Vehicle]){
print("Number of vehicles:", vehicles.count)
}
}
class CarFactory: TransportFactory {
let myCars = [Car]()
}
let carFactory = CarFactory()
carFactory.doSomethingWithVehicles(carFactory.myCars)
/* print out
Number of vehicles: 0
*/

Related

Return Class based on Generic in Swift

I have two custom class objects. I have to show a view which reads the data from both the objects depending on what class object we passed.
How can I achieve this?
Thank you,
You can set your myObject as AnyObject and after you can check object is from class A or class B.
class viewc : UIViewController {
var myObject: AnyObject?
override func viewDidLoad() {
super.viewDidLoad()
if let object = myObject as? ClassA {
print("Object is of class- ClassA")
}else if let object = myObject as? ClassB {
print("Object is of class- ClassB")
}
}
}
You cannot do it like var object = <T>() as its not the correct format or var object = T() as Non-nominal type 'T' does not support explicit initialization.
You can use it like this:-
class ABC<T>: UIViewController{
var object: T? = nil
}
Hope it helps :)
You can use a generic type.
class ControllerTimeline<T>: UIViewController {
var myObject :T?
...
}
If you need T to have some constraint (example: could be only NSObject)
class ControllerTimeline<T: NSObject>: UIViewController {
var myObject :T?
...
}
If you want to use only A or B, you can create a common parent for A and B+
class ControllerTimeline<T: C>: UIViewController {
...
Or let A and B implement a common protocol and type something like this
class ControllerTimeline<T: MyProtocol>: UIViewController {
...

How to access same propety from different class without type casting in swift

I have 2 class which have same number of properties with same name. I want to access property without type casting.
class A : NSObject {
var amount : Int = 10
}
class B : NSObject {
var amount : Int = 20
}
Now I want to double the value of amount property like this
main() {
let classA : A()
print(doubleValue(classA))
let classB : B()
print(doubleValue(classB))
}
func doubleValue(myClass:AnyObject) -> Int {
return myClass.amount * 2
}
Please suggest how can I achieve this.
This is exactly what protocol are used for. Let us call this new protocol Amountable and add the amount property.
protocol Amountable {
var amount: Int { get set }
}
If you want to provide a default implementation for doubleValue() you can event use protocol extension as follows:
extension Amountable {
mutating func doubleValue() {
self.amount *= 2
}
}
Finally, let your classes conform to the protocol:
class ClassA: Amountable {
// Implementation of classA here
}
class ClassB: Amountable {
// Implementation of classB here
}
objectA = ClassA()
objectA.doubleValue()

How to export method of inner class using JSExport

I have one class whose methods and properties are exported using JSExport. In normal cases, it works well. But if the property is the type of some inner class, then it can not be accessed from javascript.
Following are the classes i am using:
Person.swift
import Foundation
import JavaScriptCore
#objc
protocol PersonJavaScritMethod : JSExport {
var testProperty : OuterClassPersonal.Personal? { get set }
func sayHello(name1:String)
}
class Person : NSObject, PersonJavaScritMethod {
var name : String!
var testProperty:OuterClassPersonal.Personal?
init(name:String) {
testProperty = OuterClassPersonal.Personal()
super.init()
self.name = name
}
class func create(name : String) -> Person {
return Person(name: name)
}
func sayHello(name1:String) {
println("Hello \(name) \(name1)")
}
}
Personal.swift
import Foundation
import JavaScriptCore
#objc
protocol PersonalJavaScritMethod : JSExport {
func getNNN()
}
class OuterClassPersonal:NSObject,JSExport{
class Personal:NSObject,PersonalJavaScritMethod {
func getNNN(){
println("Hip Hip Hurray")
}
}
}
JavaScript.swift
import Foundation
import JavaScriptCore
class Javascript {
let context = JSContext()
func evaluateScript() {
context.exceptionHandler = { context, exception in
println("❌ Error in Javascript: \(exception) ");
}
var p1:Person = Person(name: "Luitel")
context.globalObject.setObject(p1, forKeyedSubscript: "Person1")
context.evaluateScript("Person1.sayHello('sdf') \n ")
var result = context.evaluateScript("Person1.testProperty.getNNN() \n")
println("\(result.toString())")
}
}
When i run the evaluateScript() method, i get the output as the following in console,
Hello Luitel sdf ❌ Error in Javascript: TypeError: undefined is not a
function (evaluating 'Person1.testProperty.getNNN()')
undefined
i want to access the method getNNN() of Personal Class. Here, if getNNN() is the method of OuterClassPersonal class and OuterClassPersonal implements PersonalJavaScriptMethod, it works properly.
The Question is, How can i access method of internal class "Personal" from Javascript?
Seems there is no way exporting inner class functions to javascript. I moved the inner class (Personal) out and created independent class and it worked.

Referencing the class in it self in Class method

I would like to access the class methods inside the class it self. I know you could use self keyword in a class instance like so:
class InstanceClass {
var testProperty = "testing"
func testMathod() {
print(self.testProperty)
}
}
// initiate like so
let newInstance = InstanceClass()
newInstance.testMathod() // result testing
What's the keyword for accessing class in static property in below example:
class BaseClass {
static let testProperty = "test"
class func printProperty () {
// here I want to access testProperty
}
}
I aware that I could do BaseClass.testProperty in above example but I want to keep it abstract.
I have Swift 2.11 running.
My bad.. self keyword works with Class Methods also.
Example:
class BaseClass {
class var testProperty: String {
return "Original Word"
}
static func printTestPropery() {
print(self.testProperty)
}
}
class ChildClass: BaseClass {
override class var testProperty: String {
return "Modified Word"
}
}
ChildClass.printTestPropery() // prints "Modified Word"
I find Swift to be a little inconsistent for this but here is how you access static class properties from various scopes:
class BaseClass
{
static let testProperty = "test2"
// access class property from class function
class func printProperty()
{
print( testProperty )
}
// access class property from instance function
func printClassProperty()
{
print(BaseClass.testProperty)
print(self.dynamicType.testProperty)
}
}
protocol PrintMe:class
{
static var testProperty:String { get }
}
extension BaseClass:PrintMe {}
extension PrintMe
{
// access from a class protocol can use Self for the class
func printFromProtocol()
{
print(Self.testProperty)
}
}

Swift generics: EXC_BAD_ACCESS when trying to access class property

It seems a class, which uses generics in swift, sometimes cannot properly determine object type.
Consider the following model structure:
class BaseModel: NSObject, Equatable, Printable {
var id: String = ""
override var description: String {
return "id: \(id)"
}
override func isEqual(object: AnyObject?) -> Bool {
if let object = object as? BaseModel {
return object.id == id
}
else {
return super.isEqual(object)
}
}
}
class Image: BaseModel {
var image: UIImage!
}
I also have parsers, which should parse/serialize objects:
class AbstractParser<T: BaseModel where T: Equatable>: NSObject {
func convertFromParseObject(object: NSObject) -> T {
var entity = T()
......
return updateEntityWithParseObject(object, entity: entity)
}
func updateEntityWithParseObject(object: NSObject, entity: T) -> T {
fatalError("This method must be overridden")
}
}
class ImageParser<T: Image>: AbstractParser<Image> {
override func updateEntityWithParseObject(object: NSObject, entity: Image) -> Image {
println("\(entity)")
println("\(entity.id)")
// The line below outputs BaseModel, shouldn't it be Image instead?
println("\(NSStringFromClass(entity.classForCoder))")
// EXC_BAD_ACCESS here:
println("\(entity.image)")
return entity
}
}
The app crashes when I try to access entity.image.
For some reasons Swift thinks that entity object is BaseModel, not Image.
Playground file: https://drive.google.com/file/d/0B6agzpK_lR6JQUlhMFoxaGw1akU/view?usp=sharing

Resources