Swift iOS固定题库实现及API题目解析技术问询
Hey there! Let's work through your Swift iOS addition app requirements one by one. I'll show you how to build a non-repeating question bank (fixed or dynamic from API) and assign values to your labels properly.
First, let's fix the core issue of non-repeating questions. Instead of using two separate arrays for numbers, we'll use a structured approach to track full questions (both a and b values) so we can manage which ones we've already used.
Step 1: Define a Question Structure
Create a simple struct to hold each addition question's two numbers:
struct Question { let a: Int let b: Int }
Step 2: Manage Question Banks in Your View Controller
We'll maintain two arrays: one for your original fixed questions, and one for currently available (unused) questions. When the available array is empty, we'll reset it to the original bank to start over.
class MathGameViewController: UIViewController { @IBOutlet weak var lbNum1: UILabel! @IBOutlet weak var lbNum2: UILabel! // Your fixed question bank (can be replaced with API data later) private var originalQuestions: [Question] = [ Question(a: 1, b: 2), Question(a: 3, b: 2), Question(a: 8, b: 2), Question(a: 7, b: 9), Question(a: 6, b: 3) ] // Tracks questions that haven't been used yet private var availableQuestions: [Question] = [] override func viewDidLoad() { super.viewDidLoad() // Initialize available questions with the fixed bank resetAvailableQuestions() // Load the first question setNextQuestion() } }
Step 3: Add Logic to Fetch Non-Repeating Questions
Add these helper methods to handle resetting the bank and loading the next unique question:
extension MathGameViewController { private func resetAvailableQuestions() { availableQuestions = originalQuestions } private func setNextQuestion() { // If all questions are used, reset the bank guard !availableQuestions.isEmpty else { resetAvailableQuestions() } // Pick a random unused question let randomIndex = Int(arc4random_uniform(UInt32(availableQuestions.count))) let selectedQuestion = availableQuestions.remove(at: randomIndex) // Assign values to your labels lbNum1.text = String(selectedQuestion.a) lbNum2.text = String(selectedQuestion.b) // Call your existing result calculation function setResult(randomA: selectedQuestion.a, randomB: selectedQuestion.b) } // Your existing result function (adjust as needed) private func setResult(randomA: Int, randomB: Int) { let sum = randomA + randomB print("Current sum: \(sum)") // Add your logic to display or check the result here } }
Now let's update your Alamofire request to pull questions from the API and replace your fixed bank. We'll safely parse the desc field's questions array to extract a and b values.
Add this method to your view controller:
extension MathGameViewController { private func fetchDynamicQuestionBank() { Alamofire.request("test", method: .get, parameters: nil, encoding: JSONEncoding.default, headers: nil) .responseJSON { [weak self] response in guard let self = self else { return } switch response.result { case .success(let value): // Parse the API response layer by layer (safe optional binding) guard let responseArray = value as? [[String: Any]], let homeworkItem = responseArray.first, let descDict = homeworkItem["desc"] as? [String: Any], let questionsArray = descDict["questions"] as? [[String: Int]] else { print("Failed to parse API response structure") return } // Convert parsed JSON into Question objects let dynamicQuestions = questionsArray.compactMap { questionDict in guard let a = questionDict["a"], let b = questionDict["b"] else { return nil } return Question(a: a, b: b) } // Update the original bank with dynamic questions self.originalQuestions = dynamicQuestions self.resetAvailableQuestions() // Load the first dynamic question self.setNextQuestion() print("Successfully loaded dynamic question bank!") case .failure(let error): print("API request failed: \(error.localizedDescription)") } } } }
Use the Dynamic Bank
To switch from fixed to dynamic questions, just call fetchDynamicQuestionBank() in viewDidLoad() instead of initializing with the fixed bank:
override func viewDidLoad() { super.viewDidLoad() fetchDynamicQuestionBank() }
Key Fixes & Improvements
- Replaced two separate number arrays with a single
Questionstruct to keep pairs synchronized - Added
availableQuestionsto ensure no repeats until all questions are used - Safe JSON parsing with optional binding to avoid crashes from malformed API data
- Clean separation between fixed and dynamic question bank logic
内容的提问来源于stack exchange,提问作者user9683424

