Return Class based on Generic in Swift - ios

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 {
...

Related

Is there any way to create an instance for current class type dynamically?

Assume that I have more than 10 classes, for example: class1, class2, class3, .. etc and each class has own functions.
My question is, since I have to create an instance for each class to use its functions, can I create an instance variable dynamically and assign class type rather than to specific the type manually?
I mean something like this:
class class1 {
static var instance = self
// or
static var instance :type(of:self) {
get {
return type(of:self)
}
}
}
/* instance type will be "class1", through "instance" I can access to class public functions */
Of course I tried these ideas but none of them worked.
Is there any way to do it?
UPDATE :
class Country {
static var instance = Country()
func do_something1 () { // do soething
}
func do_something2 () { // do soething
}
func do_something3 () { // do soething
}
func do_something4 () { // do soething
}
func do_somethingN () { // do soething
}
}
I want make instance got it type dynamically based on class that exist in rather then specific type manually
You can get the class by providing class name and then you can init.
func classFromString(className: String) -> AnyClass! {
let namespace = Bundle.main.infoDictionary!["CFBundleExecutable"] as! String;
let class1: AnyClass = NSClassFromString("\(namespace).\(className)")!;
return class1;
}

How to make different classes conform to the same protocol with different functionality?

I apologize beforehand if title is unclear, but I like to know how this is possible with some code snippets first:
ClassOne:
#objc protocol FetchProtocol
{
var someVar: Bool
{
get set
}
var someUIView: FetchProtocol
{
get set
}
func someFuncOne()
}
class ClassOne: UIViewController, FetchProtocol
{
...
#IBOutlet var someUIView: FetchProtocol!
....
}
ClassTwo:
#objc protocol FetchProtocol
{
var someVar: Bool
{
get set
}
var someTableView: FetchProtocol
{
get set
}
var someUIView: FetchProtocol
{
get set
}
func someFuncOne()
func someFuncTwo()
}
class ClassTwo: UIViewController, FetchProtocol
{
...
#IBOutlet var someTableView: FetchProtocol!
#IBOutlet var someUIView: FetchProtocol!
....
}
Both ClassOne and ClassTwo conform to the same FetchProtocol and both classes use the same someVar as well as someFuncOne, but ClassTwo also uses someTableView and someFuncTwo unique to only ClassTwo.
How can I use the same protocol between both classes, but the other class has "additional" different skeletal implementation?
For example, something like the following:
if let vc = currentVC as? FetchProtocol
{
if vc.someVar == true
{
// Check if vc is of class type ClassOne, call someFuncOne
// Otherwise if vc is of class type ClassTwo, call someFuncOne and someFuncTwo
}
}
Is something like the above possible using protocols and if so, how to properly implement it, or is there another alternative?
Your code doesn't compile and I think you're overcomplicating things and use protocols for the sake of using them.. There is no need to use any protocols at all if all you want to do is this:
if let vc = currentVC as? FetchProtocol
{
if vc.someVar == true
{
// Check if vc is of class type ClassOne, call someFuncOne
// Otherwise if vc is of class type ClassTwo, call someFuncOne and someFuncTwo
}
}
Why not delete all protocols and just do:
if currentVC.someVar {
if let class1 = currentVC as? ClassOne {
class1.someFuncOne()
} else if let class2 = currentVC as? ClassTwo {
class2.someFuncOne()
class2.someFuncTwo()
}
}
You don't really need protocols here because whether protocols exist or not, you still have to check whether currentVC is ClassOne or ClassTwo.
Protocols act like "black boxes". Consider this method:
func foo(fetchObj: FetchProtocol) {
fetchObj.someFuncOne()
}
foo doesn't care about what fetchObj really is. It just says "I don't care what you are, just do someFuncOne!"
What you're trying to do here is completely the opposite: "I do care what you are. If you're ClassOne, do this. If you're ClassTwo, do that."
Your problem is quite abstract, and pretty hard to follow, but this does what you're asking for. That being said, I suspect there's no need for you to be using protocols here at all.
protocol P1 {
var someVar1: String { get }
func func1();
}
protocol P2: P1 {
var someVar2: String { get }
func func2();
}
class C1: P1 {
var someVar1 = "String 1 in C1"
func func1() {
print(someVar1)
}
}
class C2: P2 {
var someVar1 = "String 1 in C2"
var someVar2 = "String 2 in C2"
func func1() {
print(someVar1)
}
func func2() {
print(someVar2)
}
}
func foo(with object: P1) {
object.func1()
if let object = object as? P2 {
object.func2()
}
}
print("Test case 1:")
foo(with: C1())
print("Test case 1:\n")
foo(with: C2())

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()

save and get array of custom object in user default [duplicate]

I try to store Array of objects in NSUserDefaults.
I have following snippets of code:
var accounts = MyAccounts()
var array:Array<MyAccounts.MyCalendar> = accounts.populateFromCalendars()
NSUserDefaults.standardUserDefaults().
setObject(array, forKey: "test_storeAccounts_array") // <- get error here
NSUserDefaults.standardUserDefaults().synchronize()
But I get Exception:
does not implement methodSignatureForSelector: -- trouble ahead
my class structure:
class MyAccounts {
/* ... */
class MyCalendar {
var title:String?
var identifier:String?
var email:String?
var calType:String?
var isActive:Bool?
var isMainAcount:Bool?
init(){}
}
}
Any ideas?
Make sure your class inherits from NSObject
class MyAccounts:NSObject {
/* ... */
class MyCalendar {
var title:String?
var identifier:String?
var email:String?
var calType:String?
var isActive:Bool?
var isMainAcount:Bool?
init(){}
}
}
I was getting this exception in Swift 3.0. In my case, my model class was not inherit from NSObject base class. just inherit my class from NSObject base class and implements NSCoding protocol (if your container array has custom objects)
class Stock: NSObject, NSCoding {
var stockName: String?
override init() {
}
//MARK: NSCoding protocol methods
func encode(with aCoder: NSCoder){
aCoder.encode(self.stockName, forKey: "name")
}
required init(coder decoder: NSCoder) {
if let name = decoder.decodeObject(forKey: "name") as? String{
self.stockName = name
}
}
func getStockDataFromDict(stockDict stockDict:[String:AnyObject]) -> Stock {
if let stockName = stockDict["name"] {
self.stockName = stockName as? String
}
return self
}
}
In Swift 2, I experienced similar error while using the Notification Pattern within a custom class. Note that when the same notification(Observe) is implemented in a ViewController class , it doesn't complain. Its only with the custom class, created from a Swift file without subclassing this error was thrown
class myClass : NSObject {
override init(){
super.init()
NSNotificationCenter.defaultCenter().addObserver(self, selector: Selector("functionCall:"), name: "NotificationName", object: nil)
}
//Implement function
func functionCall(notification: NSNotification) {
//Extract the object and implement the function
}
}
You need to convert the class into NSData first. Something like this:
var data = NSKeyedArchiver.archivedDataWithRootObject(accounts.populateFromCalendars())
var userDefaults = NSUserDefaults.standardUserDefaults();
userDefaults.setObject(data, forKey: "test_storeAccounts_array");

Swift: inherited objects

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
*/

Resources