Setter/Getter in protocol in swift - ios

branchID is set to be a getter BUT I am able to set the value. What is the use of specifying it to be a setter/ getter?
protocol Bank {
var name: String {get set}
var branchID: Int {get}
}
struct Person: Bank {enter code here
var name: String = "ABC Bank"
var branchID: Int = 123
}
let person = Person()
person.name
person.branchID

First of all the code doesn't use the protocol.
If an object adopts a protocol it must implement the protocol requirements. Your code creates an object Person with all capabilities of Person
var person = Person()
and you can change branchID
person.branchID = 13
However if you cast person to Bank
var bank = person as Bank
bank.branchID = 13
you will get the error
Cannot assign to property: 'branchID' is a get-only property
The same error occurs if you declare a function which tries to update all objects which conform to Bank
func updateID(item : Bank)
{
item.branchID = 12
}

branchID in Person is a new object,You can certainly change its value.
when you write 'Bank. branchID',you can't set its value

Related

Realm list property not saving data

I have two models, lets call them Schools, and Teachers. Models are as under
#objcMembers public class Schools : Object {
dynamic var Id : String = ""
dynamic var UserId : Int64 = 0
dynamic var Name : String? = ""
dynamic var listTeachers : List<Teachers>? = nil
dynamic var teachersList : [Teachers]? = []
}
#objcMembers public class Teachers : Object {
dynamic var Id : String = ""
dynamic var UserId : Int64 = 0
dynamic var Name : String? = ""
}
now before saving data I m putting Teachers objects (list) in School object then I save that School object in realm write closure.
after that I just get the School realm object and when I get the Teachers list, it always gets Nil. What is the case?
Am i missing something or missing something to understand the real LIST property??
please help
Update: This is how I am getting object
let mSavedItems = mDbHelper.realmObj.objects(Schools.self)
if let teachers = mSavedItems[0].teachersList{// here teacher list is nil
}
Your Schools declaration is flawed. You shouldn't declare a List as dynamic or mutable, nor should you make it Optional. As the docs clearly state, let listTeachers = List<Teachers>() is the correct way to declare a many-to-many relationship.
Storing a property of type Array is also not supported by Realm, so you should delete the teachersList : [Teachers]? property.
#objcMembers public class Schools : Object {
dynamic var Id : String = ""
dynamic var UserId : Int64 = 0
dynamic var Name : String? = ""
let listTeachers = List<Teachers>()
}

How can I find the type of a property dynamically in swift (Reflection/Mirror)?

So let's say I have a class like this:
class Employee: NSObject {
var id: String?
var someArray: [Employee]?
}
I use reflection to get the property names:
let employee = Employee()
let mirror = Mirror(reflecting: employee)
propertyNames = mirror.children.flatMap { $0.label }
// ["businessUnitId", "someArray"]
so far so good! Now i need to be able to figure out the type of each of these properties, so if I do the employee.valueForKey("someArray"), it won't work because it only gives me the AnyObject type. What would be the best way to do this? Specially for the array, I need to be able to dynamically tell that the array contains type of Employee.
You don't need to inherit from NSObject (unless you have a good reason to).
class Employee {
var id: String?
var someArray: [Employee]?
}
let employee = Employee()
for property in Mirror(reflecting: employee).children {
print("name: \(property.label) type: \(type(of: property.value))")
}
Output
name: Optional("id") type: Optional<String>
name: Optional("someArray") type: Optional<Array<Employee>>
This also works with Structs
If you are inheriting from NSObject, you can use some of the methods provided by NSCoding and the Objective-C runtime:
let employee = Employee()
employee.someArray = []
employee.valueForKey("someArray")?.classForCoder // NSArray.Type
employee.valueForKey("someArray")?.classForKeyedArchiver // NSArray.Type
employee.valueForKey("someArray")?.superclass // _SwiftNativeNSArrayWithContiguousStorage.Type
employee.valueForKey("someArray")!.dynamicType

How to get method for class in Swift

I have a class:
class myObject: NSObject {
dynamic var objectId : String?
dynamic var name : String?
dynamic var lastName : String?
dynamic var age : String?
}
In my other class I am getting the value of this class's property:
self.myArray.append(myObject.name!)
I can get the value of myObject.name by adding .name but what if there will be hundreds of properties in my myObject class? For that I want to create a method which can return the properties of my class using a variable:
let myVar = "name"
self.myArray.append(myObject.myVar)
It should append the values of property name, but I am getting an error:
value of myObject has no member `myVar`
and I know why I am getting the error.
How can I get access to properties of my class using a variable? Something like :getValue(String) should return that property of my class.
You should also have a look at NSMutableDictionary, here's a quick example which shows how it works
// initialise a dictionary
var dict = NSMutableDictionary(objects: ["first", "second", 42], forKeys: ["String1", "String2", "Int1"])
// add a new attribute
dict.addEntriesFromDictionary(NSDictionary(object: "New thing", forKey: "String3") as [NSObject : AnyObject])
// access the data
let firstString = dict.valueForKey("String1")
let firstInt = dict.valueForKey("Int1")
// update the data
dict.setValue(99, forKey: "Int1")
let newValue = dict.valueForKey("Int1")
I can be wrong, but as I've already said in a comment, it would be better to use Dictionary and store values in it. Also if you want to access some values with a dot-notation, but still be able to get them by string, you can just create a property and override setter and getter
class MyClass {
var properties = [String: AnyObject]()
var someProperty: String? {
get {
return properties["someProperty"] as? String
}
set {
properties["someProperty"] = newValue
}
}
This way you are able to access value of someProperty both by object.someProperty and object.properties["someProperty"]
You can do it making array of object like following
var arrayOfObjects = [myObject]
and then set an objects values
var firstObject:myObject
myObject.name = "Your name"
myObject.age = "Your age"
...
then append first object to arrayOfObjects
arrayOfObject.append(firstObject)
and you can access it
print("First Object's name: \(arrayOfObjects[0].name)")

Classes and calling the properties Dynamically, Swift

I have two swift classes with two fairly similar properties (I have made the ones below the same for the purpose of this question) I want to use. I want to call the properties dynamically in the ViewDidLoad and I have used an array as shown below so I can change the index and choose which class to call. Unfortunately I get the error
Anyobject does not have a member named speciesType
What could I have missed or am I approaching the whole problem in the wrong way?
class Lion {
var age = 45
var speciesType = "Felidae"
}
class Lioness {
var age = 10
var speciesType = "Panthera"
}
var animal1 = Lion()
var animal2 = Lioness()
var animalKingDom = [animal1, animal2]
var colourChanging = animalKingDom[0].speciesType
Why dont you create a protocol that extracts out the common properties from both the classes.
class Lion {
var age = 45
var speciesType = "Felidae"
}
class Lioness {
var age = 10
var speciesType = "Panthera"
}
protocol LionType {
var speciesType: String { get set }
var age: Int { get set }
}
extension Lion: LionType { }
extension Lioness: LionType { }
var animal1 = Lion()
var animal2 = Lioness()
var animalKingDom: [LionType] = [animal1, animal2]
var colourChanging = animalKingDom[0].speciesType
I created a protocol LionType and added extension to both the classes to conform to the protocol. Since both the classes already have age and speciesType, the classes will remain unchanged. And finally, a small modification to your animalKingDom array could make it work easily.
By the way, I added a protocol LionType, I think it makes more sense to name it AnimalType which fits for all animals not just lions :)
I prefer the syntax where you declare the protocol before the classes, and let the classes explicit implement the protocol upon creation.
import Cocoa
protocol Animal {
var age: Int { get set }
var speciesType: String { get set }
}
class Lion: Animal {
var age: Int
var speciesType: String
init(age: Int, speciesType: String) {
self.age = age
self.speciesType = speciesType
}
}
class Lioness: Animal {
var age: Int
var speciesType: String
init(age: Int, speciesType: String) {
self.age = age
self.speciesType = speciesType
}
}
var l1 = Lion(age: 5, speciesType: "Cat")
var l2 = Lioness(age: 6, speciesType: "Doge")
var animalArray: [Animal] = [l1, l2]
for animal in animalArray {
print(animal.age)
print(animal.speciesType)
}
Also I'm not sure I would give a class for both male and female of an animal. But it totally depends on your business domain.
The compiler infer that the generic type of your array is 'AnyObject'.
Try removing one element from your array, and the compiler will find the good type of your array.
The compiler is not able to know that Lion and Lioness has a property in common.
You can either make a superclass or a protocol like GeneratorOne suggests.
I think that what you really want to do is have two instances of a single class (or better yet, if your real example is anything like this one, a struct). Let's keep using your Lion class. Two instances would then be
var lion = Lion()
lion.age = 45
lion.family = "Felidae"
var lioness = Lion()
lioness.age = 10
lioness.family = "Panthera"
(I'm ignoring the fact that your male and female are in different families. :))

In swift, when one property has no default value, the default values held by other properties become useless?

In swift, I have the following code:
struct Person {
var name: String
var nose: Int = 1
}
var mike = Person(name: "mike", nose: 1)
var john = Person(name: "john") //error: missing argument for parameter 'nose' in call
Although nose has a default value, I have to specify a value for it. My question is, does default value of nose become totally useless and I can simply write the declaration as the following?
struct Person {
var name: String
var nose: Int
}
Thanks!
From The Swift Programming Language
Structure types automatically receive a memberwise initializer if they
do not define any of their own custom initializers. This is true even
if the structure’s stored properties do not have default values.
The memberwise initializer is a shorthand way to initialize the member
properties of new structure instances. Initial values for the
properties of the new instance can be passed to the memberwise
initializer by name.
As you haven't declared any initialisers for your struct, the only initialiser that is available is the memberwise initialiser.
You can declare an initialiser that just takes a name in order to use the default value for nose. This then requires you to explicitly declare the memberwise initialiser -
struct Person {
var name: String
var nose: Int = 1
init(_ name:String) {
self.name=name;
}
init (name:String, nose:Int){
self.name=name;
self.nose=nose;
}
}
var mike = Person(name: "mike", nose: 1)
var john = Person("john")
I like this form because it is so flexible:
struct Person {
var name: String
var nose: Int
init(name: String = "Anon", nose: Int = 1) {
self.name=name;
self.nose=nose;
}
}
var sally = Person(nose: 2, name: "Sally")
var anon1 = Person(nose: 1)
var anon2 = Person()
var mike = Person(name: "mike", nose: 1)
var john = Person(name: "john")
Note 5 different initialiser combinations possible. Essentially it allows you to treat Person like a person builder (Builder pattern).

Resources