i was making a family class when it popped up an error it was "expected declaration" i'm not sure what it means and how to debug it
//
// ViewController.swift
// familyClassSecond
//
// Created by Dordor Zheng on 11/13/16.
// Copyright © 2016 Dordor Zheng. All rights reserved.
//
import UIKit
class Person {
var name : String!
var age : String!
var idNum : Int!
init(name:String, age:String, idNum:Int){
self.name = name
self.age = age
self.idNum = idNum
}
func sayPerson() -> String{
let S = "Hi i'm \(name) i am \(age) years old and my id is \(idNum)"
print(S)
return S
}
}
class female : Person {
var sex : String = "female"
override func sayPerson() -> String {
let S = "Hi i'm \(name) and i am \(age) years old"
print(S)
return S
}
}
class male : Person {
var sex : String = "male"
override func sayPerson() -> String {
let S = "Hi i'm \(name) and i am \(age) years old"
print(S)
return S
}
}
class daughter: female {
var mother : female!
var father : male!
var sibbling : Array<Person>! = []
init(me:female,father:male,mother:female,brother:male){
super.init(name: me.name, age: me.age, idNum: me.idNum)
self.father = father
self.mother = mother
}
override func sayPerson() -> String {
let S = "I'm \(name), i am \(age) years old my father is \(father.name) and my mother is \(mother.name)"
print(S)
return S
}
func appendSibbling(brother:Person){
sibbling.append(brother)
}
}
class brother: male {
var mother : female!
var father : male!
var sibbling : Array<Person>! = []
init(me:male,father:male,mother:female,daughter:female){
super.init(name: me.name, age: me.age, idNum: me.idNum)
self.father = father
self.mother = mother
}
override func sayPerson() -> String {
let S = "I'm \(name), i am \(age) years old my father is \(father.name) and my mother is \(mother.name)"
print(S)
return S
}
}
class father: male {
var wife : female!
var children : Array<Person>! = []
init(me:male, wife:female,child:Person,brother:male){
super.init(name: me.name, age: me.age, idNum: me.idNum)
self.wife = wife
self.children.append(child)
self.children.append(brother)
}
if(children.count == 1 || children.count == 0){
var choose = "child"
}else{
choose = "children"
}
override func sayPerson() -> String {
let S = "I'm \(name), i am \(age) years old i have \(children.count) children and my wife is \(wife.name)"
print(S)
return S
}
}
class mother: female {
var husband : male!
var children : Array<Person>! = []
init(me:female, husband:male,child:Person,brother:male){
super.init(name: me.name, age: me.age, idNum: me.idNum)
self.husband = husband
self.children.append(child)
self.children.append(brother)
}
override func sayPerson() -> String {
let S = "I'm \(name), i am \(age) years old i have \(children.count) children and my husband is \(husband.name)"
print(S)
return S
}
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let one = female(name: "Dordor", age: "8", idNum: 388313)
let two = male(name: "Tiger", age: "24", idNum: 773424)
let three = male(name: "Chiwen", age: "48", idNum: 143303)
let four = female(name: "Hongwen", age: "47", idNum: 243332)
let child = daughter(me: one, father: three, mother: four, brother: two)
let mom = mother(me: four, husband: three, child: one,brother:two)
let dad = father(me: three, wife: four, child: one,brother: two)
let bigB = brother(me: two, father: three, mother: four, daughter: one)
child.sayPerson()
mom.sayPerson()
dad.sayPerson()
bigB.sayPerson()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
do you have any ideas and the error is on the if
you can copy paste into your code cause i'm using swift 9.2(it's not beta)
You need to make choose a computed property:
var choose : String {
if children.count == 1 || children.count == 0 {
return "child"
} else {
return "children"
}
}
You can pick between two options that you have
Convert choose to a lazy variable:
lazy var choose: String = {
if(self.children.count == 1 || self.children.count == 0){
return "child"
} else {
return "children"
}
}()
Make choose a function:
func choose() -> String {
if(self.children.count == 1 || self.children.count == 0){
return "child"
}else{
return "children"
}
}
Related
I use xCode 9, swift 4 and "Eureka form library" for my project.
The situation
I have a list of cars with name and unique ID associated this way: 0 - ANY, 1 - VW, 7 - AUDI, 20 - MAZDA
var name_cars: [String] = ["ANY","VW","AUDI","MAZDA"]
var id_cars:[Int] = [0, 1, 7, 20]
I also have a form with "PushRow" and "ButtonRow".
On click to the button I want to print the selected car name and ID.
I was able to print the car's name but not the ID.
import UIKit
import Eureka
class myPage: FormViewController {
var cars: [String] = ["ANY","VW","AUDI","MAZDA"]
var id_cars:[Int] = [0, 1,7,20]
var selected_car: String = "ANY" //default car
var selected_car_id: Int = 0 //default id car
override func viewDidLoad() {
super.viewDidLoad()
create_form()
}
func create_form(){
form
+++ Section("List")
//list
<<< PushRow<String>() {
$0.title = "Cars"
$0.options = cars
$0.value = "ANY"
$0.tag = "list_element"
$0.selectorTitle = "Choose car"
$0.onChange { [unowned self] row in
self.selected_car = row.value!
self.selected_car_id = ??? // **what should it be here in order to get the ID**
}
}
//button
<<< ButtonRow("Button1") {row in
row.title = "Get Value on Console"
row.onCellSelection{[unowned self] ButtonCellOf, row in
print ("Car selected = ",self.selected_car, " and Id_Car_Selected = ",self.selected_car_id)
}
}
}
}
First of all please conform to the naming convention that class names start with a capital letter and variable names are lowerCamelCased rather than snake_cased.
Swift is an object oriented language. Rather than two separate arrays use a custom struct Car.
import UIKit
import Eureka
struct Car : Equatable {
let name : String
let id : Int
}
The push row is declared as PushRow<Car>() and the property displayValueFor is populated with the name
class MyPage: FormViewController {
let cars = [Car(name: "ANY", id: 0), Car(name: "VW", id: 1), Car(name: "AUDI", id: 7), Car(name: "MAZDA", id: 20)]
var selectedCar : Car!
override func viewDidLoad() {
super.viewDidLoad()
selectedCar = cars[0]
createForm()
}
func createForm() {
form
+++ Section("List")
//list
<<< PushRow<Car>() {
$0.title = "Cars"
$0.options = cars
$0.value = selectedCar
$0.displayValueFor = {
guard let car = $0 else { return nil }
return car.name
}
$0.tag = "list_element"
$0.selectorTitle = "Choose car"
$0.onChange { [unowned self] row in
self.selectedCar = row.value!
}
}
//button
<<< ButtonRow("Button1") {row in
row.title = "Get Value on Console"
row.onCellSelection{[unowned self] ButtonCellOf, row in
print ("Car selected = ", self.selectedCar.name, " and Id_Car_Selected = ", self.selectedCar.id)
}
}
}
}
I'm making easy example.
I'm trying to filter movies by year using func: filterByYear.
I have an error in one line on the bottom:
'var filterYear = MovieArchive.filterByYear(1980)' Compiler info is: 'Type 'MovieArchive' has no member filterByYear’
import UIKit
class Movie {
let title: String
let director: String
let releaseYear: Int
init(title: String, director: String, releaseYear: Int){
self.title = title
self.director = director
self.releaseYear = releaseYear
}
}
class MovieArchive{
var movies : [Movie]
init(movies:[Movie]){
self.movies = movies
func filterByYear(year:Int) -> [Movie]{
var filteredArray = [Movie]()
for movie in movies{
if movie.releaseYear == year {
filteredArray.append(movie)
}
}
return filteredArray
}
}
}
var newMovie1 = Movie(title: "IT", director: "S.S", releaseYear: 1980)
var newMovie2 = Movie(title: "PP", director: "O.N", releaseYear: 2003)
var moviesArray = [newMovie1, newMovie2]
var myArchive = MovieArchive(movies: moviesArray)
var filterYear = MovieArchive.filterByYear(1980)
var firstMovie = filterYear[0]
print(firstMovie)
You are calling the method on the class itself, not an instance of it. You would have to create an instance of the class like this:
let myMovieArchive = MovieArchive(movies: [Some Array])
and then call the method on the instance.
print(myMovieArchive.filterByYear)
So in your case, call it on myArchive, not MovieArchive.
Even though the question has been answered, you can simplify your filterByYear method to make it a bit more Swifty:
func filterByYear(year:Int) -> [Movie]
{
return movies.filter({ $0.releaseYear == year })
}
Error is: Cannot convert value of type (String: Int)? to specified type 'String'.
Obviously my dictionary 'roster' is 'String: Int' and the local variables ('lastPlayer' and 'firstPlayer') inside function 'printRoster' is String. But I've tried every variation with no luck. It worked fine before I made roster a dictionary, and it was just a String.
What it should do: function concatenates a string so that it has correct punctuation. First string is "The roster includes", then we add on each player located in the Key of the dictionary 'roster'. But the first key in the roster gets no comma and the last key gets an ', and'.
Also, can I add the dictionary 'roster' to the protocol, didn't see the syntax in any of the Apple manuals
import UIKit
protocol basketballTeams {
var teamName: String? { get }
var numberOfPlayers: Int? { get }
var locatedIn: String? { get }
func printTeamLocation()
}
class BasketballTeam {
var teamName: String?
var numberOfPlayers: Int?
var locatedIn: String?
var roster = [String: Int]()
init(teamName: String) {
self.teamName = teamName
}
func printTeamLocation() -> String {
return "The \(teamName) are located in \(locatedIn)"
}
func printRoster() -> String {
var rosterPrint = "The roster includes"
for player in roster.keys {
rosterPrint += player
var firstPlayer: String = roster.first
var lastPlayer = roster.last
if (player == firstPlayer) {
rosterPrint += " \(player)"
}
else if (player == lastPlayer) {
rosterPrint += ", and \(player)."
}
else {
rosterPrint += ", \(player)"
}
}
return rosterPrint
}
}
enum NumberedPosition: Int {
case PointGuard = 1
case ShootingGuard, SmallForward, PowerForward, Center
func labelOfPosition() -> String {
switch self {
case .PointGuard:
return "Point Guard"
case .ShootingGuard:
return "Shooting Guard"
case .SmallForward:
return "Small Forward"
case .PowerForward:
return "Power Forward"
case .Center:
return "Center"
default:
"Position doesn't exit"
}
}
}
let goldenStateWarriors = BasketballTeam(teamName: "Golden State Warriors")
goldenStateWarriors.numberOfPlayers = 12
goldenStateWarriors.locatedIn = "Oakland, California"
goldenStateWarriors.roster = ["Stephen Curry" : 1, "Andrew Bogut" : 5, "Klay Thompson" : 2]
goldenStateWarriors.roster["Harrison Barnes"] = 3
How about this:
let roster = ["Stephen Curry":1, "Andrew Bogu": 2, "Klay Thompson":3]
let players = roster.keys.joined(separator: ", ")
let all = "Roster contains: \(players)."
If you still want to add the "and" to the last row you can use this function:
func printRoster() -> String {
var rosterPrint = "The roster includes"
let arr = Array(roster.keys)
let firstPlayer: String = arr.first!
let lastPlayer: String = arr.last!
for (player, _ ) in roster {
switch player {
case firstPlayer:
rosterPrint += " \(player)"
case lastPlayer:
rosterPrint += ", and \(player)."
default:
rosterPrint += ", \(player)"
}
}
return rosterPrint
}
and call it like so:
print(goldenStateWarriors.printRoster())
Given this dictionary
let roster = ["Stephen Curry":1, "Andrew Bogu": 2, "Klay Thompson":3]
you can
let elms = roster
.keys
.reduce("") { $0.1 + ", " + $0.0 }
.characters
.dropLast()
.dropLast()
let res = "The roster includes " + String(elms)
Result
"The roster includes Andrew Bogu, Stephen Curry, Klay Thompson"
Update #1: Using the FOR LOOP
Since you want to use the for loop here's the code
let roster = ["Stephen Curry":1, "Andrew Bogu": 2, "Klay Thompson":3]
var result = "The roster includes "
for (index, elm) in roster.keys.enumerate() {
result += elm
if index < roster.keys.count - 1 {
result += ", "
}
}
print(result) // The roster includes Klay Thompson, Stephen Curry, Andrew Bogu
Update #2: Using the FOR LOOP with first and last
let roster = ["Stephen Curry":1, "Andrew Bogu": 2, "Klay Thompson":3]
func printRoster() -> String {
var rosterPrint = "The roster includes"
let players = Array(roster.keys)
guard let
first = players.first,
last = players.last
else { return "" } // this is ugly, it should return nil instead...
for player in players {
switch player {
case first: rosterPrint += " \(player)"
case last: rosterPrint += ", and \(player)."
default: rosterPrint += ", \(player)"
}
}
return rosterPrint
}
printRoster() // "The roster includes Klay Thompson, Stephen Curry, and Andrew Bogu."
This seems to work well, at least until they allow .first and .last with dictionaries (if that's even possible).
class BasketballTeam {
var teamName: String?
var numberOfPlayers: Int?
var locatedIn: String?
var roster = [String: Int]()
init(teamName: String) {
self.teamName = teamName
}
func printTeamLocation() -> String {
return "The \(teamName) are located in \(locatedIn)"
}
func printRoster() -> String {
var rosterPrint = "The roster includes"
let rosterArray = Array(roster.keys)
for player in rosterArray {
let firstPlayer = rosterArray.first
let lastPlayer = rosterArray.last
switch player {
case firstPlayer!:
rosterPrint += " \(player)"
case lastPlayer!:
rosterPrint += ", and \(player)."
default:
rosterPrint += ", \(player)"
}
}
return rosterPrint
}
}
Full code, you can paste into a playground if you're trying to learn swift and familiar with basketball
import UIKit
protocol basketballTeams {
var teamName: String { get }
var numberOfPlayers: Int { get }
var locatedIn: String { get }
var roster: [String: Int] { get }
func printTeamLocation()
}
class BasketballTeam {
var teamName: String?
var numberOfPlayers: Int?
var locatedIn: String?
var roster = [String: Int]()
init(teamName: String) {
self.teamName = teamName
}
func printTeamLocation() -> String {
return "The \(teamName) are located in \(locatedIn)"
}
func printRoster() -> String {
var rosterPrint = "The roster includes"
let rosterArray = Array(roster.keys)
for player in rosterArray {
let firstPlayer = rosterArray.first
let lastPlayer = rosterArray.last
switch player {
case firstPlayer!:
rosterPrint += " \(player)"
case lastPlayer!:
rosterPrint += ", and \(player)."
default:
rosterPrint += ", \(player)"
}
}
return rosterPrint
}
}
enum NumberedPosition: Int {
case PointGuard = 1
case ShootingGuard, SmallForward, PowerForward, Center
func labelOfPosition() -> String {
switch self {
case .PointGuard:
return "Point Guard"
case .ShootingGuard:
return "Shooting Guard"
case .SmallForward:
return "Small Forward"
case .PowerForward:
return "Power Forward"
case .Center:
return "Center"
default:
"Position doesn't exist"
}
}
}
let goldenStateWarriors = BasketballTeam(teamName: "Golden State Warriors")
goldenStateWarriors.numberOfPlayers = 12
goldenStateWarriors.locatedIn = "Oakland, California"
goldenStateWarriors.roster = ["Stephen Curry" : 1, "Andrew Bogut" : 5, "Klay Thompson" : 2]
goldenStateWarriors.roster["Harrison Barnes"] = 3
goldenStateWarriors.printRoster()
goldenStateWarriors.printTeamLocation()
var num = 3
if let numberToPositionConv = NumberedPosition(rawValue: num) {
let description = numberToPositionConv.labelOfPosition()
}
I'm a beginner in Swift and static programming. Going through Big Nerd Ranch Swift book. What I don't understand is why myTown population is changing, but not fredTheZombie.town? The exercise calls for the town population to never go below zero. This could happen when the population is less than 10. How do I change the fredTheZombie.town population variable?
struct Town {
var population = 5422
var numberOfStoplights = 4
func printTownDescription() {
print("Population: \(myTown.population), number of stoplights: \(myTown.numberOfStoplights)")
}
mutating func changePopulation(amount: Int) {
population += amount
}
}
class Monster {
var town: Town?
var name = "Monster"
func terrorizeTown() {
if town != nil {
print("\(name) is terrorizing a town!")
} else {
print("\(name) hasn't found a town to terrorize yet...")
}
}
}
class Zombie: Monster {
var walksWithLimp = true
final override func terrorizeTown() {
guard town?.population > 0 else {
return
}
if town?.population > 10 {
super.town!.changePopulation(-10)
} else {
super.town!.population = 0
}
super.terrorizeTown()
}
func changeName(name: String, walksWithLimp: Bool) {
self.name = name
self.walksWithLimp = walksWithLimp
}
}
var myTown = Town()
myTown.changePopulation(500)
let fredTheZombie = Zombie()
fredTheZombie.town = myTown
fredTheZombie.terrorizeTown()
fredTheZombie.town?.printTownDescription()
fredTheZombie.changeName("Fred the Zombie", walksWithLimp: false)
myTown.changePopulation(-5915)
print(myTown.population)
print(fredTheZombie.town!.population)
fredTheZombie.terrorizeTown()
fredTheZombie.terrorizeTown()
fredTheZombie.town?.printTownDescription()
Output:
Monster is terrorizing a town!
Population: 5922, number of stoplights: 4
7
5912
Fred the Zombie is terrorizing a town!
Fred the Zombie is terrorizing a town!
Population: 7, number of stoplights: 4
Program ended with exit code: 0
Town is a struct, a value type. When assigning a value type to a different variable (e.g. fredTheZombie.town = myTown), that value type is copied (meaning that a new Town is created with the same values as the original Town).
myTown and fredTheZombie.town are not the same town any more. If you want them to be the same instance, make them a class (a reference type).
See more info on Apple Swift Blog and in Swift Language Guide.
The biggest problem we have are optional structs. The result of unwrapping an optional struct (using town!) is again a copy, a new town. To work around that, you have to:
var myTown = super.town!
myTown.changePopulation(-10)
super.town = myTown // assign back
Whole example:
struct Town {
var population = 5422
var numberOfStoplights = 4
func printTownDescription() {
// note you have to print "self" here, not "myTown"
print("Population: \(self.population), number of stoplights: \(self.numberOfStoplights)")
}
mutating func changePopulation(amount: Int) {
population += amount
}
}
class Monster {
var town: Town?
var name = "Monster"
func terrorizeTown() {
if town != nil {
print("\(name) is terrorizing a town!")
} else {
print("\(name) hasn't found a town to terrorize yet...")
}
}
}
class Zombie: Monster {
var walksWithLimp = true
final override func terrorizeTown() {
guard super.town?.population > 0 else {
return
}
var town = super.town!
if town.population > 10 {
town.changePopulation(-10)
} else {
town.population = 0
}
super.town = town
super.terrorizeTown()
}
func changeName(name: String, walksWithLimp: Bool) {
self.name = name
self.walksWithLimp = walksWithLimp
}
}
In your case there is no need for town to be actually optional. You could just pass it to Monster in a constructor.
I am creating a sort of tilling system that will take into account offers on certain products. I need to create a half price offer that will display either true or false depending whether the offer has been applied.
HalfPrice Class:
class HalfPriceOffer :Offer {
init(){
super.init(name: "Half Price on Wine")
applicableProducts = [901,902];
}
override func isApplicableToList(list: [ShoppingItem]) -> Bool {
//should return true if a dicount can be applied based on the supplied list of products (i.e. a product must be matched to an offer)
return false
}
ShoppingItem Class
import Foundation
class ShoppingItem {
var name :String
var priceInPence :Int
var productId :Int
init(name:String, price:Int, productId:Int){
self.name = name
self.priceInPence = price
self.productId = productId
}
}
I know it uses loops; but I am unsure of how to actually write it. Thanks in advance :)
You could use the reduce function to achieve this:
func isApplicableToList(list: [ShoppingItem]) -> Bool {
return list.reduce(false) { (initial: Bool, current: ShoppingItem) -> Bool in
return initial || applicableProducts.contains(current.productId)
}
}
You can even write this shorter (Swift is awesome):
func isApplicableToList(list: [ShoppingItem]) -> Bool {
return list.reduce(false) { $0 || applicableProducts.contains($1.productId) }
}
It's perhaps less complex to think whether the offer items are in the list rather than the list items are in the offer.
override func isApplicableToList(list: [ShoppingItem]) -> Bool {
//should return true if a discount can be applied based on the supplied list of products (i.e. a product must be matched to an offer)
let a = list.map({$0.productId})
for p in applicableProducts
{
if !a.contains(p) {return false}
}
return true
}
And here's a full working code example, which fills in the implied gaps in the sample code:
class ShoppingItem {
var name: String
var priceInPence: Int
var productId: Int
init(name:String, price:Int, productId:Int){
self.name = name
self.priceInPence = price
self.productId = productId
}
}
class Offer {
var applicableProducts = [Int]()
var name:String
init(name: String) {
self.name = name
}
func isApplicableToList(list: [ShoppingItem]) -> Bool {
return false
}
}
class HalfPriceOffer: Offer {
init(){
super.init(name: "Half Price on Wine")
applicableProducts = [901,902]
}
override func isApplicableToList(list: [ShoppingItem]) -> Bool {
//should return true if a discount can be applied based on the supplied list of products (i.e. a product must be matched to an offer)
let a = list.map({$0.productId})
for p in applicableProducts
{
if !a.contains(p) {return false}
}
return true
}
}
let a = [ShoppingItem(name: "one", price: 1000, productId: 901), ShoppingItem(name: "two", price: 1009, productId: 907),ShoppingItem(name: "three", price: 1084, productId: 902)]
HalfPriceOffer().isApplicableToList(a) // true
let b = [ShoppingItem(name: "one", price: 1000, productId: 901), ShoppingItem(name: "two", price: 1009, productId: 907)]
HalfPriceOffer().isApplicableToList(b) // false