Hi I am doing some Swift coding and I cant figure out how to get rid of this error:
Missing argument for parameter 'makePetMakeNoise' in call.
Could you help me fix this error?
import Foundation
import UIKit
class Human {
static var numCreated:Int = 4
var name:String = ""
var pet:Pet
init(name:String,pet:Pet){
self.name = name
self.pet = pet
Human.numCreated++
}
func makePetMakeNoise(){
var randomNumber = arc4random_uniform(9)
self.pet.makeNoise(randomNumber) //Missing argument for parameter 'makePetMakeNoise' in call
}
func feedPet(){
self.pet.eat
}
static func populationCount(){
println("Total population count is \(Human.numCreated)")
}
}
class Pet {
var name:String = ""
var noise:String = ""
var canMakeNoise:Bool = true
init(name:String,noise:String,canMakeNoise:Bool){
self.name = name
self.noise = noise
self.canMakeNoise = canMakeNoise
}
func makeNoise(canMakeNoise: Int, makePetMakeNoise: Int){
if self.canMakeNoise {
for _ in 1...5{
println("\(self.name) \(self.noise)")
}
}else {
println("\(self.name) *remains silent*")
}
}
func eat(){
println("\(name) is eating")
}
class Dog:Pet{
}
class Cat:Pet{
override func eat {
super.eat()
println("I'm still hungry, meow")
}
}
}
//Pets
var Tobie = Pet(name: "Tobie", noise: "Bark", canMakeNoise: true)
var Bud = Pet(name: "Bud", noise: "Bark", canMakeNoise: false)
var Ginger = Pet(name: "Ginger", noise: "bark", canMakeNoise: false)
var Curry = Pet(name: "Curry", noise: "Bark", canMakeNoise: true)
//Humans
var Sam = Human(name: "Sam", pet: Tobie)
var Mark = Human(name: "Mark", pet: Bud)
var Spencer = Human(name: "Spencer", pet: Ginger)
var Jessie = Human(name: "Jessie", pet: Curry)
let Humans = [Sam, Mark, Spencer, Jessie]
for Human in Humans {
println("\(Humans) \(feedPet) \(makePetMakeNoise)") //Use of unresolved identifier 'feedPet and makePetMakeNoise'\\
}
`
Your makeNoise method defined for Pet takes two parameters. Problem is that when you call it in the line that gives you the error, you pass it just one parameter.
Possible solution is:
Change the Pet's method as follow:
func makeNoise(makePetMakeNoise: Int){
if self.canMakeNoise {
for _ in 1...5{
println("\(self.name) \(self.noise)")
}
}else {
println("\(self.name) *remains silent*")
}
}
Update the code that gives you the error in Human like this:
func makePetMakeNoise(){
var randomNumber = Int(arc4random_uniform(9))
self.pet.makeNoise(randomNumber)
}
Notice I convert random to Int since this is the expected parameter type.
Please consider I'm just guessing a possible modification since I don't know what your classes are intended for ... maybe just a playground.
Other solution is effectively passing two parameters when you call the pet's method from human.
Hope this helps
Your function func makeNoise(canMakeNoise: Int, makePetMakeNoise: Int) expects two arguments, but your are only passing the one randonNumber in your call self.pet.makeNoise(randomNumber). It should look something like this: self.pet.makeNoise(randomNumber, someOtherNumber)
Related
I am very new to Swift so I apologize upfront if this is a "dumb" question. I am just working on a playgrounds script for generating random items, in this case, weapons. When I run my code I get this error: error: Execution was interrupted, reason: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0). What I was trying to do is hold an instance of a structure(which is handle) in my class normalBladeType in variable weaponHandle. I've tried researching about this topic but I've yet to find an answer. Any suggestions would be great. For all I know I may be going about this all wrong.
Thanks,
my code:
//: Playground - noun: a place where people can play
import Cocoa
let handleWoods = ["White Ash", "Oak", "White Oak", "Elm", "Maple","Walnut", "Cherry", "Rosewood", "Ash", "Hickory", "Birch", "Hemlock", "Cedar", "Pine"]
let handleGrips = ["Leather", "Buckskin", "Sharkskin", "Goat Skin", "Deerskin", "Elk Skin", "Rayskin", "Snakeskin", "Silk Cord", "Cotton Cord"]
let gripQualities = ["Simple", "Interwoven", "Ornate", "Smooth", "Thin", "Thick", "Ruff", "Worn"]
func returnRandomItem( _ list: [Any])-> Any {
return list[Int(UInt32(list.count))]
}
struct handle {
var name: String
var value, grip: Int
var weight: Double
var withGrip: Bool
init(withGrip: Bool) {
self.weight = 0.25
self.withGrip = withGrip
let handleNameWithWood = "\(returnRandomItem(handleWoods)) Handle"
if self.withGrip {
let randGrip = "\(returnRandomItem(gripQualities)) \(returnRandomItem(handleGrips)) Grip)"
self.name = "\(randGrip) (\(handleNameWithWood))"
self.grip = 75
self.value = 2
} else {
self.name = handleNameWithWood
self.grip = 50
self.value = 1
}
}
func description() {
print("Handle Description \(self.name)")
}
}
class weapon {
var TypeOfWeapon: String
var weaponHandle: handle
init(weaponType: String, doesHaveGrip: Bool) {
self.TypeOfWeapon = weaponType
self.weaponHandle = handle(withGrip: doesHaveGrip)
}
}
class normalBladeType: weapon {
init() {
super.init(weaponType: "normalBladeType", doesHaveGrip: false)
}
func description() {
print("TypeOfWeapon: \(self.TypeOfWeapon)")
print("TypeDescription: normal hilt (guard - handle - pommel) + straight blade")
}
}
var foo = normalBladeType()
foo.description()
Your returnRandomItem function is wrong. You should change it to
func returnRandomItem( _ list: [Any])-> Any {
let index: UInt32 = arc4random_uniform(UInt32(list.count))
return list[Int(index)]
}
It is working fine for me with this code.
How do you initialize your classes/structs with a lot of properties?
This question could probably be asked without Swift context but Swift brings a flavour to it, so I add Swift tag in headline and tags.
Let's say you have a User class with 20 properties. Most of them should not be nil or empty. Let's assume these properties are not interdependent. Let's assume that 33% of it should be constant (let) by the logic of the class. Let's assume that at least 65% of them do not have meaningful default values. How would you design this class and initialize an instance of it?
So far I have few thoughts but none of it seems to be completely satisfactory to me:
put all of the properties linearly in the class and make huge init method:
class User {
// there is 20 properties like that
let id : String
let username : String
let email : String
...
var lastLoginDate : Date
var lastPlayDate : Date
// then HUUUUGE init
init(id: String,
username: String,
...
lastPlayDate: Date) {
}
}
try to group properties into sub types and deal with smaller inits separately
class User {
struct ID {
let id : String
let username : String
let email : String
}
struct Activity {
var lastLoginDate : Date
var lastPlayDate : Date
}
let id : ID
...
var lastActivity : Activity
// then not so huge init
init(id: ID,
...
lastActivity: Activity) {
}
}
another solution is to break requirements a bit: either declare some of the properties optional and set values after init or declare dummy default values and set normal values after init, which conceptually seems to be the same
class User {
// there is 20 properties like that
let id : String
let username : String
let email : String
...
var lastLoginDate : Date?
var lastPlayDate : Date?
// then not so huge init
init(id: String,
username: String,
email: String) {
}
}
// In other code
var user = User(id: "1", username: "user", email: "user#example.com"
user.lastLoginDate = Date()
Is there a nice paradigm/pattern how to deal with such situations?
You can try the builder pattern.
Example
class DeathStarBuilder {
var x: Double?
var y: Double?
var z: Double?
typealias BuilderClosure = (DeathStarBuilder) -> ()
init(buildClosure: BuilderClosure) {
buildClosure(self)
}
}
struct DeathStar : CustomStringConvertible {
let x: Double
let y: Double
let z: Double
init?(builder: DeathStarBuilder) {
if let x = builder.x, let y = builder.y, let z = builder.z {
self.x = x
self.y = y
self.z = z
} else {
return nil
}
}
var description:String {
return "Death Star at (x:\(x) y:\(y) z:\(z))"
}
}
let empire = DeathStarBuilder { builder in
builder.x = 0.1
builder.y = 0.2
builder.z = 0.3
}
let deathStar = DeathStar(builder:empire)
Example taken from here: https://github.com/ochococo/Design-Patterns-In-Swift
If you are looking for a bit more Java like solution, you can try something like this.
Alternative Example
final class NutritionFacts {
private let servingSize: Int
private let servings: Int
private let calories: Int
private let fat: Int
private let sodium: Int
private let carbs: Int
init(builder: Builder) {
servingSize = builder.servingSize
servings = builder.servings
calories = builder.calories
fat = builder.fat
sodium = builder.sodium
carbs = builder.carbs
}
class Builder {
let servingSize: Int
let servings: Int
private(set) var calories = 0
private(set) var fat = 0
private(set) var carbs = 0
private(set) var sodium = 0
init(servingSize: Int, servings: Int) {
self.servingSize = servingSize
self.servings = servings
}
func calories(value: Int) -> Builder {
calories = value
return self
}
func fat(value: Int) -> Builder {
fat = value
return self
}
func carbs(value: Int) -> Builder {
carbs = value
return self
}
func sodium(value: Int) -> Builder {
sodium = value
return self
}
func build() -> NutritionFacts {
return NutritionFacts(builder: self)
}
}
}
let facts = NutritionFacts.Builder(servingSize: 10, servings: 1)
.calories(value: 20)
.carbs(value: 2)
.fat(value: 5)
.build()
Example taken from: http://ctarda.com/2017/09/elegant-swift-default-parameters-vs-the-builder-pattern
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 })
}
I want to get the value of a variable (passed as a string) in my class and have it casted correctly. This is what I have so far.
// Playground - noun: a place where people can play
import UIKit
class Test: NSObject {
var stringVar = "Some String"
var arrayVar = ["Some", "Array"]
override init() {
super.init()
var dynamicKey = "stringVar"
var valueForKeyResult1: AnyObject! = valueForKey(dynamicKey)
dynamicKey = "arrayVar"
var valueForKeyResult2: AnyObject! = valueForKey(dynamicKey)
var someVarName = valueForKeyResult2
}
}
Test()
Now how do I get the var valueForKeyResult 1 & 2 casted into the types that they were in the first place (without knowing what types they were)?
They are already the correct types:
class Test: NSObject {
var stringVar = "Some String"
var arrayVar = ["Some", "Array"]
override init() {
super.init()
var dynamicKey = "stringVar"
var valueForKeyResult1: AnyObject! = valueForKey(dynamicKey)
println("valueForKeyResult1: \(NSStringFromClass(valueForKeyResult1?.dynamicType)), value: \(valueForKeyResult1!)\n")
dynamicKey = "arrayVar"
var valueForKeyResult2: AnyObject! = valueForKey(dynamicKey)
println("valueForKeyResult2: \(NSStringFromClass(valueForKeyResult2?.dynamicType)), value: \(valueForKeyResult2!)\n")
}
}
Test()
Output:
valueForKeyResult1: Swift._NSContiguousString, value: Some String
valueForKeyResult2: _TtCSs23_ContiguousArrayStorage000000010050D510, value: (
Some,
Array
)
In Objective-C, one can add a description method to their class to aid in debugging:
#implementation MyClass
- (NSString *)description
{
return [NSString stringWithFormat:#"<%#: %p, foo = %#>", [self class], foo _foo];
}
#end
Then in the debugger, you can do:
po fooClass
<MyClass: 0x12938004, foo = "bar">
What is the equivalent in Swift? Swift's REPL output can be helpful:
1> class MyClass { let foo = 42 }
2>
3> let x = MyClass()
x: MyClass = {
foo = 42
}
But I'd like to override this behavior for printing to the console:
4> println("x = \(x)")
x = C11lldb_expr_07MyClass (has 1 child)
Is there a way to clean up this println output? I've seen the Printable protocol:
/// This protocol should be adopted by types that wish to customize their
/// textual representation. This textual representation is used when objects
/// are written to an `OutputStream`.
protocol Printable {
var description: String { get }
}
I figured this would automatically be "seen" by println but it does not appear to be the case:
1> class MyClass: Printable {
2. let foo = 42
3. var description: String { get { return "MyClass, foo = \(foo)" } }
4. }
5>
6> let x = MyClass()
x: MyClass = {
foo = 42
}
7> println("x = \(x)")
x = C11lldb_expr_07MyClass (has 1 child)
And instead I have to explicitly call description:
8> println("x = \(x.description)")
x = MyClass, foo = 42
Is there a better way?
To implement this on a Swift type you must implement the CustomStringConvertible protocol and then also implement a string property called description.
For example:
class MyClass: CustomStringConvertible {
let foo = 42
var description: String {
return "<\(type(of: self)): foo = \(foo)>"
}
}
print(MyClass()) // prints: <MyClass: foo = 42>
Note: type(of: self) gets the type of the current instances instead of explicitly writing ‘MyClass’.
Example of using CustomStringConvertible and CustomDebugStringConvertible protocols in Swift:
PageContentViewController.swift
import UIKit
class PageContentViewController: UIViewController {
var pageIndex : Int = 0
override var description : String {
return "**** PageContentViewController\npageIndex equals \(pageIndex) ****\n"
}
override var debugDescription : String {
return "---- PageContentViewController\npageIndex equals \(pageIndex) ----\n"
}
...
}
ViewController.swift
import UIKit
class ViewController: UIViewController
{
/*
Called after the controller's view is loaded into memory.
*/
override func viewDidLoad() {
super.viewDidLoad()
let myPageContentViewController = self.storyboard!.instantiateViewControllerWithIdentifier("A") as! PageContentViewController
print(myPageContentViewController)
print(myPageContentViewController.description)
print(myPageContentViewController.debugDescription)
}
...
}
Which print out:
**** PageContentViewController
pageIndex equals 0 ****
**** PageContentViewController
pageIndex equals 0 ****
---- PageContentViewController
pageIndex equals 0 ----
Note: if you have a custom class which does not inherit from any class included in UIKit or Foundation libraries, then make it inherit of NSObject class or make it conform to CustomStringConvertible and CustomDebugStringConvertible protocols.
Just use CustomStringConvertible and var description: String { return "Some string" }
works in Xcode 7.0 beta
class MyClass: CustomStringConvertible {
var string: String?
var description: String {
//return "MyClass \(string)"
return "\(self.dynamicType)"
}
}
var myClass = MyClass() // this line outputs MyClass nil
// and of course
print("\(myClass)")
// Use this newer versions of Xcode
var description: String {
//return "MyClass \(string)"
return "\(type(of: self))"
}
The answers relating to CustomStringConvertible are the way to go. Personally, to keep the class (or struct) definition as clean as possible, I would also separate out the description code into a separate extension:
class foo {
// Just the basic foo class stuff.
var bar = "Humbug!"
}
extension foo: CustomStringConvertible {
var description: String {
return bar
}
}
let xmas = foo()
print(xmas) // Prints "Humbug!"
class SomeBaseClass: CustomStringConvertible {
//private var string: String = "SomeBaseClass"
var description: String {
return "\(self.dynamicType)"
}
// Use this in newer versions of Xcode
var description: String {
return "\(type(of: self))"
}
}
class SomeSubClass: SomeBaseClass {
// If needed one can override description here
}
var mySomeBaseClass = SomeBaseClass()
// Outputs SomeBaseClass
var mySomeSubClass = SomeSubClass()
// Outputs SomeSubClass
var myOtherBaseClass = SomeSubClass()
// Outputs SomeSubClass
As described here, you can also use Swift's reflection capabilities to make your classes generate their own description by using this extension:
extension CustomStringConvertible {
var description : String {
var description: String = "\(type(of: self)){ "
let selfMirror = Mirror(reflecting: self)
for child in selfMirror.children {
if let propertyName = child.label {
description += "\(propertyName): \(child.value), "
}
}
description = String(description.dropLast(2))
description += " }"
return description
}
}
struct WorldPeace: CustomStringConvertible {
let yearStart: Int
let yearStop: Int
var description: String {
return "\(yearStart)-\(yearStop)"
}
}
let wp = WorldPeace(yearStart: 2020, yearStop: 2040)
print("world peace: \(wp)")
// outputs:
// world peace: 2020-2040