Swift:检查存储在NSMutableArray值中的JSON值

时间:2016-08-10 21:46:02

标签: ios json swift

我无法检查用户是否已经看到JSON文件中的问题。

我在值中有一个带有存储JSON的NSArray( allEntries )。我这样创建:

let path = NSBundle.mainBundle().pathForResource("content", ofType: "json")
let jsonData : NSData = NSData(contentsOfFile: path!)!
allEntries = (try! NSJSONSerialization.JSONObjectWithData(jsonData, options: NSJSONReadingOptions.MutableContainers)) as! NSArray

如果我打印出其中一个值 allEntries [0] ,我会得到:

{
answers =     (
    Chimney,
    "Front door",
    Window,
    "Dog door"
);
difficulty = 1;
id = 2;
question = "How does Santa get into a house on Christmas eve?";
}

现在,稍后在我的代码中,我需要随机调用其中一个问题,因此我生成一个索引并将其传递给此函数:

func LoadQuestion(index : Int)
{
    let entry : NSDictionary = allEntries.objectAtIndex(index) as! NSDictionary
    let questionID : Int = entry.objectForKey("id") as! Int
    let question : NSString = entry.objectForKey("question") as! NSString
    let arr : NSMutableArray = entry.objectForKey("answers") as! NSMutableArray

    ....
}

加载问题时。我将ID值添加到另一个名为 alreadyAsked

的数组中

起初我收到此错误:

  

无法转换类型' __ NSCFString' (0x865ee0)到' NSNumber' (0x133781c)。

在这一行:

let questionID : Int = entry.objectForKey("id") as! Int

所以我将 Int 更改为NSString:

let questionID : NSString = entry.objectForKey("id") as! NSString

然后尝试像这样重铸:

let questionID = Int(questionIDRaw as! Int)

然后我得到了这个问题:

  

定义与先前值冲突

我需要做什么:

免责声明我是菜鸟。到目前为止,我已经按照Udemy的教程进行操作,并设法让应用程序正常运行。额外的检查是我想要做的事情。

所以,我希望能够检查以确保当我提出一个随机问题时,问题的id(在json中)不在 alreadyAsked 数组中。我该怎么做?

感谢所有帮助:)

编辑:

完全控制器:

import UIKit
import AVFoundation // audio


class ViewController: UIViewController {

@IBOutlet weak var buttonA: UIButton!
@IBOutlet weak var buttonB: UIButton!
@IBOutlet weak var buttonC: UIButton!
@IBOutlet weak var buttonD: UIButton!


@IBOutlet weak var labelQuestion: UILabel!

@IBOutlet weak var labelScore: UILabel!

@IBOutlet weak var labelFeedback: UILabel!

@IBOutlet weak var buttonNext: UIButton!

@IBOutlet weak var BackgroundImageView: UIImageView!

var score :Int! = 0
var allEntries : NSArray!


var currentCorrectAnswerIndex : Int = 0

var audioPlayer = AVAudioPlayer()

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.

    LoadAllQuestionsAndAnswers()

    let randomNumber = Int(arc4random_uniform(UInt32(allEntries.count)))
    LoadQuestion(randomNumber)
    LoadScore()

    AdjustInterface()
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}


func LoadScore()
{
   let defaults = NSUserDefaults.standardUserDefaults()
    score = defaults.integerForKey("score")
    labelScore.text = "score: \(score)"
}


func SaveScore()
{
    let defaults = NSUserDefaults.standardUserDefaults()
    defaults.setInteger(score, forKey: "score")
}


func LoadAllQuestionsAndAnswers()
{
    let path = NSBundle.mainBundle().pathForResource("content", ofType: "json")
    let jsonData : NSData = NSData(contentsOfFile: path!)!
    allEntries = (try! NSJSONSerialization.JSONObjectWithData(jsonData, options: NSJSONReadingOptions.MutableContainers)) as! NSArray
    //println(allEntries)

}


func LoadQuestion(index : Int)
{
    let entry : NSDictionary = allEntries.objectAtIndex(index) as! NSDictionary
    let question : NSString = entry.objectForKey("question") as! NSString
    let arr : NSMutableArray = entry.objectForKey("answers") as! NSMutableArray

    //println(question)
    //println(arr)

    labelQuestion.text = question as String

    let indices : [Int] = [0,1,2,3]
    let newSequence = shuffle(indices)
    var i : Int = 0
    for(i = 0; i < newSequence.count; i++)
    {
        let index = newSequence[i]
        if(index == 0)
        {
            // we need to store the correct answer index
            currentCorrectAnswerIndex =  i

        }

        let answer = arr.objectAtIndex(index) as! NSString
        switch(i)
        {
        case 0:
            buttonA.setTitle(answer as String, forState: UIControlState.Normal)
            break;

        case 1:
            buttonB.setTitle(answer as String, forState: UIControlState.Normal)
            break;

        case 2:
            buttonC.setTitle(answer as String, forState: UIControlState.Normal)
            break;

        case 3:
            buttonD.setTitle(answer as String, forState: UIControlState.Normal)
            break;

        default:
            break;
        }



    }
    buttonNext.hidden = true
    // we will need to reset the buttons to reenable them
    ResetAnswerButtons()

}

func shuffle<C: MutableCollectionType where C.Index == Int>(var list: C) -> C {
    let total = list.count
    for i in 0..<(total - 1) {
        let j = Int(arc4random_uniform(UInt32(total - i))) + i
        swap(&list[i], &list[j])
    }
    return list
}

func ResetAnswerButtons()
{
    buttonA.alpha = 1.0
    buttonB.alpha = 1.0
    buttonC.alpha = 1.0
    buttonD.alpha = 1.0
    buttonA.enabled = true
    buttonB.enabled = true
    buttonC.enabled = true
    buttonD.enabled = true
}


@IBAction func PressedButtonA(sender: UIButton) {
    print("button A pressed")
    buttonB.alpha = 0.3
    buttonC.alpha = 0.3
    buttonD.alpha = 0.3

    buttonA.enabled = false
    buttonB.enabled = false
    buttonC.enabled = false
    buttonD.enabled = false
     CheckAnswer(0)
}

@IBAction func PressedButtonB(sender: UIButton) {
    print("button B pressed")
    buttonA.alpha = 0.3
    buttonC.alpha = 0.3
    buttonD.alpha = 0.3

    buttonA.enabled = false
    buttonB.enabled = false
    buttonC.enabled = false
    buttonD.enabled = false
    CheckAnswer(1)
}

@IBAction func PressedButtonC(sender: UIButton) {
    print("button C pressed")
    buttonA.alpha = 0.3
    buttonB.alpha = 0.3
    buttonD.alpha = 0.3

    buttonA.enabled = false
    buttonB.enabled = false
    buttonC.enabled = false
    buttonD.enabled = false
    CheckAnswer(2)
}

@IBAction func PressedButtonD(sender: UIButton) {
    print("button D pressed")
    buttonA.alpha = 0.3
    buttonB.alpha = 0.3
    buttonC.alpha = 0.3

    buttonA.enabled = false
    buttonB.enabled = false
    buttonC.enabled = false
    buttonD.enabled = false
    CheckAnswer(3)
}

@IBAction func PressedButtonNext(sender: UIButton) {
    print("button Next pressed")
    let randomNumber = Int(arc4random_uniform(UInt32(allEntries.count)))
    LoadQuestion(randomNumber)
    // we need to play a sound effect for the next question coming
    PlaySoundButton()

}

func CheckAnswer( answerNumber : Int)
{
    if(answerNumber == currentCorrectAnswerIndex)
    {
        // we have the correct answer
        labelFeedback.text = "Correct! +1"
        labelFeedback.textColor = UIColor.greenColor()
        score = score + 1
        labelScore.text = "score: \(score)"
        SaveScore()
        // later we want to play a "correct" sound effect
        PlaySoundCorrect()

    }
    else
    {
        // we have the wrong answer
        labelFeedback.text = "Wrong answer"
        labelFeedback.textColor = UIColor.redColor()
        // we want to play a "incorrect" sound effect
        PlaySoundWrong()
    }

    buttonNext.enabled = true
    buttonNext.hidden = false
}

func PlaySoundCorrect()
{
   let alertSound = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("correct", ofType: "mp3")!)

    let error:NSError?
    do {
        audioPlayer = try AVAudioPlayer(contentsOfURL: alertSound)
    } catch let error1 as NSError {
        error = error1
        print(error)
    }
    audioPlayer.prepareToPlay()
    audioPlayer.play()


}

func PlaySoundWrong()
{
    let alertSound = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("wrong", ofType: "wav")!)

    var error:NSError?
    do {
        audioPlayer = try AVAudioPlayer(contentsOfURL: alertSound)
    } catch let error1 as NSError {
        error = error1
        print(error)
    }
    audioPlayer.prepareToPlay()
    audioPlayer.play()
}


func PlaySoundButton()
{
    let alertSound = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("button", ofType: "wav")!)

    let error:NSError?
    do {
        audioPlayer = try AVAudioPlayer(contentsOfURL: alertSound)
    } catch let error1 as NSError {
        error = error1
        print(error)
    }
    audioPlayer.prepareToPlay()
    audioPlayer.play()
}


func AdjustInterface()
{
    let screenSize: CGRect = UIScreen.mainScreen().bounds
    let screenWidth = screenSize.width
    let screenHeight = screenSize.height

    buttonA.center = CGPointMake(screenWidth / 2, buttonA.center.y)
    buttonB.center = CGPointMake(screenWidth / 2, buttonB.center.y)
    buttonC.center = CGPointMake(screenWidth / 2, buttonC.center.y)
    buttonD.center = CGPointMake(screenWidth / 2, buttonD.center.y)
    buttonNext.center = CGPointMake(screenWidth / 2, buttonNext.center.y)
    labelQuestion.center = CGPointMake(screenWidth / 2, labelQuestion.center.y)

    BackgroundImageView.frame = CGRectMake(0, 0, screenWidth, screenHeight)


}

}

在我开始尝试检查问题是否已被查看之前,此视图控制器是完整的。那么,澄清一下,在上面的viewcontroller我怎么做:

  • 从问题
  • 中的JSON条目中获取ID
  • 将其存储在名为 alreadyAsked
  • 的数组中
  • 检查是否已经看到加载的问题。如果是,请跳过并选择其他
  • 如果看到所有问题,请在控制台中显示无人查看

2 个答案:

答案 0 :(得分:0)

  • 从问题
  • 中的JSON条目中获取ID

您需要在Int中拥有ID内容吗? 如果不是,请将questionID保留为字符串。

let questionID = entry["id"] as! String

(如果是的话,你可以这样做,但我省略了这种情况。)

        let questionID = Int(entry["id"] as! String)!

(假设你的&#34; content.json&#34;永远不会包含意外的值......)

  • 将其存储在名为alreadyAsked
  • 的数组中

将实例属性声明为:

    var alreadyAsked: Set<String> = []

并将questionID附加为:

        alreadyAsked.insert(questionID)

(我希望你知道你需要把这一行放在哪里。)

  • 检查是否已经看到加载的问题。如果是,请跳过并选择其他

您可以在代码中随处查看,但有一个可能位于LoadQuestion(_:)方法内。

您可能需要返回一个值,表明已经提出问题:

    func loadQuestion(index : Int) -> Bool

(您最好遵循一个简单的命名准则:仅针对类型使用上层驼峰案例。这样可以提高代码共享时的可读性。我的意思是&#34;共享&#34 ;包括在Q&amp; A网站上发布问题。)

获得questionID后,请检查:

        if alreadyAsked.contains(questionID) {
            return false //already asked, so not again
        }

您需要将return true放在loadQuestion(_:)的末尾。

您可能需要重复,直到loadQuestion(_:)返回true。

        var randomNumber: Int
        repeat {
            randomNumber = Int(arc4random_uniform(UInt32(allEntries.count)))
        } while !loadQuestion(randomNumber)

(这不是很有效,但实际上(&#34;看似&#34;会更合适?)它有效。保持你的话语#34;如果是这样,跳过并选择另一个&#34;)

  • 如果看到所有问题,请在控制台中显示无人查看

在进入上面的循环之前检查它:

        if allEntries.count > alreadyAsked.count {
            var randomNumber: Int
            repeat {
                randomNumber = Int(arc4random_uniform(UInt32(allEntries.count)))
            } while !loadQuestion(randomNumber)
            loadScore()

            adjustInterface()
        } else {
            //display in console none left to view
            //...
        }

您的代码有许多不安全或不良的部分,其中一些可能很关键。如果您自己无法解决,可以发布另一个问题。

答案 1 :(得分:-1)

而不是像这样向下转换为Int:

let questionID : Int = entry.objectForKey("id") as! Int

尝试使用Int构造函数

let questionID : Int = Int(entry.objectForKey("id"))

至于你的其他错误

  

让questionID:NSString = entry.objectForKey(“id”)为!的NSString

     

然后尝试像这样重铸:

     

让questionID = Int(questionIDRaw as!Int)

您不能将变量设为String,然后在下一行中将其设为Int。它必须保持相同的类型