[英]Not correctly referencing random number in Swift object
我有一個對象數組,其中每個對象都有一個“練習名稱”和隨機次數的代表。
然后,我有一個功能可以生成隨機鍛煉(其中包含3至6個鍛煉)
但是,當我打印它時,盡管加載了30次左右,但代表幾乎總是1、2或偶爾是14。
我在這里做錯什么了嗎?
這是我的對象和結構:
struct exerciseInWorkout {
let name : String
let reps : Int
}
let exerciseBankArray = [
exerciseInWorkout(name: "Squat", reps: (Int(arc4random_uniform(10)))),
exerciseInWorkout(name: "Push Ups", reps: (Int(arc4random_uniform(5)))),
exerciseInWorkout(name: "Viking Press", reps: (Int(arc4random_uniform(20)))),
]
這是我的功能:
func generateWorkout(){
let possibleExercises = exerciseBankArray
let numberOfExercisesKey = Int(arc4random_uniform(4) + 3)
let workoutSet : [exerciseInWorkout] = (1...numberOfExercisesKey).map { _ in
let randomKey = Int(arc4random_uniform(UInt32(possibleExercises.count)))
return exerciseInWorkout(name: exerciseBankArray[randomKey].name, reps: exerciseBankArray[randomKey].reps)}
print (workoutSet)
}
}
另外,有沒有辦法創建一組這樣的方法來避免同一練習出現兩次? 我嘗試使用Set,但似乎根本不起作用。
最后,當我打印它時,每個對象前面都帶有“ project.exerciseInWorkout ...”,有什么方法可以只打印/返回干凈的數組,即[[“名稱:” press ups“,reps:12],[name: xyz,代表:30]]?
原因是我想將其傳遞給新的VC,然后放在表格視圖中,並假定我需要一個干凈的陣列來做到這一點。
看來您的數組exerciseBankArray
是全局存儲的,這意味着對整個應用程序初始化一次exerciseInWorkout
組件。 話雖如此,然后代表的次數總是相同是正常的,所以arc4random_uniform
僅在第一次訪問時執行。
如果要保持相同的結構,我建議您這樣做
從exerciseBankArray
刪除arc4random_uniform
,然后寫下所需的最大次數
let exerciseBankArray = [ exerciseInWorkout(name: "Squat", maxReps: 10), exerciseInWorkout(name: "Push Ups", maxReps: 5), exerciseInWorkout(name: "Viking Press", maxReps: 20) ]
像這樣在generateWorkout()
內部調用隨機函數
func generateWorkout(){ let possibleExercises = exerciseBankArray let numberOfExercisesKey = Int(arc4random_uniform(4) + 3) let workoutSet : [exerciseInWorkout] = (1...numberOfExercisesKey).map { _ in let randomKey = Int(arc4random_uniform(UInt32(possibleExercises.count))) return exerciseInWorkout( name: exerciseBankArray[randomKey].name, reps: Int(arc4random_uniform(exerciseBankArray[randomKey].maxReps)) ) } }
如果您願意為代碼創建更好的體系結構,請參考以下建議
將練習模型分為兩個類/結構:
代表實際的練習
struct WorkoutExercise { let name: String let reps: Int }
代表鍛煉的人
struct WorkoutExerciseGenerator { let name: String let maxReps: Int // Add any other parameter you need to generate a good exercise func generate() -> WorkoutExercise { return WorkoutExercise( name: name, reps: Int(arc4random_uniform(maxReps)) ) } }
當您說刪除全局變量時,是指將練習數組存儲在需要它們的每個VC中嗎? 我只是認為那將是“重復自己”(根據DRY原則等?)
我完全同意DRY准則,但是有很多方法可以避免重復。 全局變量(一個不在任何類內的變量,只是自由浮動)的問題很多:
另外,如果我更改為上面的第二個示例,那么該如何稱呼這些數量呢? 只需用新功能替換“ return ExerciseInWorkout”? 還是因為func包含在結構中而不會改變?
因此,我理解正確,您真正想要創建的是一組具有名稱和最大次數的練習的默認生成器,並且這些應在整個項目中可用(因此,為什么要使用全局變量)。
改進此代碼的一個好方法是定義靜態生成器,例如,您可以將WorkoutExerciseGenerator
更新為
struct WorkoutExerciseGenerator {
let name: String
let maxReps: Int
// Add any other parameter you need to generate a good exercise
func generate() -> WorkoutExercise {
return WorkoutExercise(
name: name,
reps: Int(arc4random_uniform(maxReps))
)
}
// Generates a "Squat" workout
static var squat {
return WorkoutExerciseGenerator(name: "Squat", maxReps: 10)
}
// Generates a "Push Up" workout
static var pushUp {
return WorkoutExerciseGenerator(name: "Push Ups", maxReps: 5)
}
// Generates a "Viking Press" workout
static var vikingPress {
return WorkoutExerciseGenerator(name: "Viking Press", maxReps: 20)
}
}
現在,您已經擁有了這些特定的生成器,您似乎還希望有一種生成整體鍛煉的方法。 如果是這樣,那么除了我寫過的內容之外,您還可以簡單地創建一些對象來代表鍛煉和鍛煉生成器。
/// This represents a whole workout that contains
/// multiple exercises
struct Workout {
let exercises: [WorkoutExercise]
}
/// This allows to dynamically creates a Workout
struct WorkoutGenerator {
// This is the "pool" of exercises from
// which it generates a workout (similar to your
// `exerciseBankArray`)
let exercisePool: [ExerciseGenerators]
// Min and max amount of workouts
let minCount: Int
let maxCount: Int
// Generates a workout from the generator
func generate() -> WorkoutGenerator {
let amount = Int(arc4random_uniform(maxCount - minCount)) + minCount
let exercises = (0..<amount).map { _ in
// Selects an exercise generator at random
let index = Int(arc4random_uniform(exercisePool.count))
// Generates a random workout exercise from this generator
return exercisePool[index].generate()
}
return Workout(exercises: exercises)
}
// Same thing here, you can use a static variable to create
// a "default" workout generator that contains the exercises
// you had inside your `exerciseBankArray`
static var default: WorkoutGenerator {
return WorkoutGenerator(
exercisePool: [.squat, .pushUp, .vikingPress],
minCount: 3,
maxCount: 6
)
}
}
既然已經擁有了所有這些,那么根據您的需求創建完全隨機的鍛煉所需要做的唯一一件事就是
let myWorkout = WorkoutGenerator.default.generate()
如果您想添加更多的運動類型,只需創建更多的靜態ExerciseGenerator
,如果您想創建不同類型的運動(也許使用不同的運動池,有些很難或很容易),只需創建其他靜態WorkoutGenerator
。 (請注意,您不需要靜態的,也可以直接在VC中創建對象)。
希望有幫助!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.