I have a class:
class WeaponItems {
var name: String
var index: Int
var price: Int
var weaponPower: Int = 0
var attackSpeed: Double = 0
var criticalChance: Double = 0
var criticalDamage: Double = 0
init(name: String, index: Int, price: Int){
self.name = name
self.index = index
self.price = price
}
var weaponBlade = WeaponItems(name: "Weapon Blade", index: 0, price: 300)
weaponBlade.weaponPower = 15
// Error: expected declaration
var swiftShooter = WeaponItems(name: "Swift Shooter", index: 1, price: 300)
swiftShooter.attackSpeed = 0.2
// Error: expected declaration
var minionsFoot = WeaponItems(name: "Minions Foot", index: 3, price: 300)
minionsFoot.criticalChance = 0.1
minionsFoot.criticalDamage = 0.1
// Error: expected declaration
}
I need to set weaponPower attackSpeed ... for each item, I got an error doing it this way.
I found answers saying you have to use a function to modify instances' values, but I feel that makes the code complicated, how do I set the value of it otherwise?
The concern of using a function is it'll separate the instance-creating and value-setting process, making the code harder to maintain.
you should add properties for all the weaponItems in the class
then your class implementation should look like this
class WeaponItems {
var name: String
var index: Int
var price: Int
var weaponPower: Int = 0
var attackSpeed: Double = 0
var criticalChance: Double = 0
var criticalDamage: Double = 0
var weaponBlade:WeaponItems{
get {
let tempWeaponBlade = WeaponItems(name: "Weapon Blade", index: 0, price: 300)
tempWeaponBlade.weaponPower = 15
return tempWeaponBlade
}
}
var swiftShooter:WeaponItems{
get {
let tempSwiftShooter = WeaponItems(name: "Swift Shooter", index: 1, price: 300)
tempSwiftShooter.attackSpeed = 0.2
return tempSwiftShooter
}
}
var minionsFoot:WeaponItems{
get {
let tempMinionsFoot = WeaponItems(name: "Minions Foot", index: 3, price: 300)
tempMinionsFoot.criticalChance = 0.1
tempMinionsFoot.criticalDamage = 0.1
return tempMinionsFoot
}
}
init(name: String, index: Int, price: Int){
self.name = name
self.index = index
self.price = price
}
}
If you wish to have default property values, which you would also like the opportunity to customise when creating an instance, then I would recommend using default parameter values in your initialiser. This will allow you to create a new instance of your WeaponItems class with the actual property values known at initialisation, rather than some default values which you then change immediately after.
I also strongly agree with Luca D'Alberti – there is no need for your 'preset weapons' to be instance properties. As they don't rely on any instance state, or are unique to a given instance – they should be static.
For example:
class Weapon {
static var blade : Weapon {
return Weapon(name: "Blade", index: 0, price: 300, power: 15)
}
static var swiftShooter : Weapon {
return Weapon(name: "Swift Shooter", index: 1, price: 300, attackSpeed: 0.2)
}
static var minionsFoot : Weapon {
return Weapon(name: "Minions Foot", index: 3, price: 300, criticalChance: 0.1, criticalDamage: 0.1)
}
var name: String
var index: Int
var price: Int
var power: Int
var attackSpeed: Double
var criticalChance: Double
var criticalDamage: Double
init(name: String, index: Int, price: Int,
power: Int = 0, attackSpeed: Double = 0,
criticalChance: Double = 0, criticalDamage: Double = 0) {
self.name = name
self.index = index
self.price = price
self.power = power
self.attackSpeed = attackSpeed
self.criticalChance = criticalChance
self.criticalDamage = criticalDamage
}
}
let blade = Weapon.blade
let swiftShooter : Weapon = .swiftShooter
In your case, if the code would compile, to use your pre-created weaponBlade, you have to create two WeaponItems instances as below:
let balde = WeaponItems(name: "", index: 0, price: 0).weaponBlade
That's not the best solution, even because in your case doesn't compile at all (you can read the comment by #gnasher729 to understand why).
What I suggest you is to create static instances of them
extension WeaponItems {
static var Blade: WeaponItems {
get {
let blade = WeaponItems(name: "The name", index: 1, price: 300)
blade.weaponPower = 15
return blade
}
}
}
And you can now use the blade by typing WeaponItems.Blade, or if it the type is easily inferred as below:
let blade: WeaponItems = .Blade
You can try using like below code.
lazy var weaponBlade:WeaponItems = {
let _weaponBlade = WeaponItems(name: "Weapon Blade", index: 0, price: 300)
_weaponBlade.weaponPower = 15
return _weaponBlade
}()
Please refer this link to know more about lazy variable.
Related
Cast from 'A' to unrelated type 'B' always fails
protocol P {
var name: String { get set }
var age: Int { get set }
}
class A: P {
var name: String
var age: Int
var address: String
init(na: String, ag: Int, a: String) {
self.name = na
self.age = ag
self.address = a
}
}
class B: P {
var name: String
var age: Int
var number: String
init(na: String, ag: Int, nu: String) {
self.name = na
self.age = ag
self.number = nu
}
}
var a = A(na: "Aa", ag: 20, a: "not")
var b = B(na: "Ra", ag: 22, nu: "23232")
if let n = a as? B {
print(n)
}
How can I cast the object to access the common property?
You don't need to cast anything. Simply treat A and B as P. Assuming you're using a playground you can do something like this.
var a = A(na: "Aa", ag: 20, a: "not")
var b = B(na: "Ra", ag: 22, nu: "23232")
func show(_ p: P) {
print("Name: \(p.name)")
print("Age: \(p.age)")
}
show(a)
show(b)
you can get your object as 'P' type, like this
let n: P = a
Why am I getting the error: Type 'MenuItem' does not conform to protocol 'Decodable'? It was working before. One of the things I changed was modifiers from [String]? to [Modifier]? Is that producing the error? If so, why? Stackoverflow wants me to keep saying things because it's too little description relative to the amount of code that I displayed below. Still needing to add text.
struct MenuItem: Codable {
let itemId: String
let name: String
var modifiers: [Modifier]?
var photoUrl: String?
var quantity: Int
var unitPrice: Int
var sizeAddOnPrice: Int
var toppingsAddOnPrice: Int
var totalPrice: Int
var totalModifiersPrice: Int
let description: String
var size: String
var toppings: [String]?
let category: String
init(itemId: String, name: String, modifiers: [Modifier]?, photoUrl: String?, quantity: Int, unitPrice: Int, sizeAddOnPrice: Int, toppingsAddOnPrice: Int, totalPrice: Int, totalModifiersPrice: Int, description: String, size: String, toppings: [String]?, category: String) {
self.itemId = itemId
self.name = name
self.modifiers = modifiers
self.photoUrl = photoUrl
self.quantity = quantity
self.unitPrice = unitPrice
self.sizeAddOnPrice = sizeAddOnPrice
self.toppingsAddOnPrice = toppingsAddOnPrice
self.totalPrice = totalPrice
self.totalModifiersPrice = totalModifiersPrice
self.description = description
self.size = size
self.toppings = toppings
self.category = category
}
init?(itemId: String, payload: JSON) {
guard
let name = payload[ParamKey.name].string,
let photoUrl = payload[ParamKey.photoUrl].string,
let description = payload[ParamKey.description].string,
let category = payload[ParamKey.categoryName].string,
let unitPrice = payload[ParamKey.basePrice].int,
let size = payload[ParamKey.size].string
else { return nil }
self.itemId = itemId
self.name = name
self.photoUrl = photoUrl
self.description = description
self.category = category
self.unitPrice = unitPrice
self.size = size
self.sizeAddOnPrice = 0
self.toppings = nil
self.toppingsAddOnPrice = 0
self.totalPrice = (unitPrice + sizeAddOnPrice + toppingsAddOnPrice) * quantity
self.totalModifiersPrice = (sizeAddOnPrice + toppingsAddOnPrice) * 2
self.quantity = 1
self.modifiers = payload[ParamKey.modifiers].arrayObject as? [Modifier]
}
}
You need to make the inner structs conform to Decodable/Codable also and remove struct init it'll be automatically generated
struct Modifier: Codable {
// add properties
}
struct MenuItem: Codable {
let itemId: String
let name: String
var modifiers: [Modifier]?
var photoUrl: String?
var quantity: Int
var unitPrice: Int
var sizeAddOnPrice: Int
var toppingsAddOnPrice: Int
var totalPrice: Int
var totalModifiersPrice: Int
let description: String
var size: String
var toppings: [String]?
let category: String
init?(itemId: String, payload: JSON) {
guard
let name = payload[ParamKey.name].string,
let photoUrl = payload[ParamKey.photoUrl].string,
let description = payload[ParamKey.description].string,
let category = payload[ParamKey.categoryName].string,
let unitPrice = payload[ParamKey.basePrice].int,
let size = payload[ParamKey.size].string
else { return nil }
self.itemId = itemId
self.name = name
self.photoUrl = photoUrl
self.description = description
self.category = category
self.unitPrice = unitPrice
self.size = size
self.sizeAddOnPrice = 0
self.toppings = nil
self.toppingsAddOnPrice = 0
self.totalPrice = (unitPrice + sizeAddOnPrice + toppingsAddOnPrice) * quantity
self.totalModifiersPrice = (sizeAddOnPrice + toppingsAddOnPrice) * 2
self.quantity = 1
self.modifiers = payload[ParamKey.modifiers].arrayObject as? [Modifier]
}
}
You can also use
try content.rawData() // for payload: JSON) {
to JSON to data and then supply it to the Decodable class
I developed an iOS app which have two objects, each of one inside another, as below:
first one:
class OfferItem
{
var _id : Int? = 0
var _OfferId : Int? = 0
var _ItemId : Int? = 0
var _Discount : Int? = 0
var _item = Item()
..
functions()
}
and 2nd one:
class Item
{
var _id : Int! = 0
var _RateCount : Int? = 0
var _Offer = OfferItem()
..
functions()
}
How to resolve that in such away where I can call each object in another?
You must read about references in Swift. Automatic Reference Counting link
Here is your example:
class OfferItem {
var id: Int?
var discount: Int?
var item: Item!
init(id: Int? = nil, discount: Int? = nil, itemId: Int, itemRateCount: Int) {
self.id = id
self.discount = discount
self.item = Item(id: itemId, rateCount: itemRateCount, offer: self)
}
}
class Item {
var id = 0
var rateCount = 0
unowned var offer: OfferItem
init(id: Int, rateCount: Int, offer: OfferItem) {
self.id = id
self.rateCount = rateCount
self.offer = offer
}
}
var offerItem = OfferItem(id: 10, discount: 2, itemId: 1, itemRateCount: 20)
print(offerItem.item.id, offerItem.item.offer.id)
Result: 1 Optional(10)
I hope to help you with my answer above!
I am having trouble with a design of a Vertex struct. I want to be able to create "Array" or "Set" so my "Vertex" doesnt all have to be the same type. Both situations are giving different errors. Check code below.
Thank you in advance
import Foundation
public struct Vertex<T: Equatable> where T: Equatable, T: Hashable {
public var data: T
public let index: Int?
init(data: T , index: Int ) {
self.data = data
self.index = index
}
}
extension Vertex: CustomStringConvertible {
public var description: String {
return "\(index): \(data)"
}
}
struct Coordinate {
var x : Int
var y : Int
init(x : Int, y: Int) {
self.x = x
self.y = y
}
}
extension Coordinate: Equatable {}
func ==(lhs: Coordinate, rhs: Coordinate) -> Bool {
guard lhs.x == rhs.x else {
return false
}
guard lhs.y == rhs.y else {
return false
}
return true
}
extension Coordinate: Hashable {
var hashValue: Int {
return "\(x)\(y)".hashValue
}
}
let coord1 = Coordinate(x : 5, y: 5)
let stringVertex1 = Vertex(data: "Hello World", index: 3)
let stringVertex2 = Vertex(data: "Foo ", index: 3)
let intVertex1 = Vertex(data: 2, index: 1)
let coordVertex1 = Vertex(data: coord1, index: 1)
//Error: Cannot convert value of type 'Vertex<String>' to expected element type 'Vertex'.
//Even if I make myArr1 equal to [stringVertex1, stringVertex1], I still get the same error.
let myArr1 : Array<Vertex> = [stringVertex1, intVertex1]
//This works since the data inside "Vertex" is the same type.
let myArr2 : Array<Vertex<String>> = [stringVertex1, stringVertex2]
//Error: Type "Vertex" does not conform to protocol "Hashable".
let mySet1 : Set<Vertex> = [stringVertex1, stringVertex2]
I got my answer. This is the final vertex code. THE POWER OF POP!
public enum TypeOfVertex : String {
case Int = "Mirror for Int"
case Float = "Mirror for Float"
case Double = "Mirror for Double"
case Coordinates = "Mirror for Coordinate"
case String = "Mirror for String"
}
protocol AnyVertexable {
var type: TypeOfVertex { get set }
var index: Int { get set }
}
struct Vertex<Element : Hashable> : AnyVertexable where Element: Equatable & Hashable {
var type : TypeOfVertex
var index: Int
var data : Element?
init(index: Int, data: Element) {
self.data = data
self.index = index
if let type = TypeOfVertex(rawValue: data.hashValue.customMirror.description) {
self.type = type
} else {
fatalError()
}
}
}
let sample1 = Vertex(index: 0, data: 1.0)
let sample2 = Vertex(index: 2, data: 1)
let sample3 = Vertex(index: 3, data: Coordinate(x: 5, y: 5))
let myArr : [AnyVertexable] = [sample1, sample2, sample3]
I am stuck in a problem. Let's assume I have this Realm Model:
class Table: Object {
dynamic var id = 0
dynamic var x: Int = 0
dynamic var y: Int = 0
dynamic var width:Int = 0
dynamic var height: Int = 0
dynamic var text: String = ""
dynamic var color: String = ""
dynamic var type: String = ""
let food = List<Food>()
override static func primaryKey() -> String {
return "id"
}
}
class Food : Object {
dynamic var id: Int = 0
dynamic var name = ""
dynamic var ingredients: String = "" // bigger text field
dynamic var size: Int = 0 // none, small, medium, big size
dynamic var price: Float = 0.0
dynamic var category: Category?
let additionalIngredients = List<Ingredient>()
override static func primaryKey() -> String {
return "id"
}
}
Let's say I have one table and added 2 times the same food on that table like so :
try! realm.write(){
table.food.append(food) // A
table.food.append(food) // B
realm.add(table, update: true)
}
If I change the additionalIngredients for food A , also at the same food B changes its values. I am doing that changes with this transaction :
try! realm.write(){
table.food.first!.additionalIngredients.removeAll()
for ingredient in ingredientsToAdd{
table.food.first!.additionalIngredients.append(ingredient)
}
realm.add(table, update: true)
}
I guess I am doing something wrong regarding the reference/instance, can someone give me a hint?
Thanks in advance!
List.append() adds the object itself to the list and not a copy of the object, so you only have one Food object.