简体   繁体   中英

EXC_BAD_INSTRUCTION when setting UILabel.text in swift

I am a swift newbie. I am studying iOS Programming The Big Nerd Ranch Guide 4th Edition. The code in the book is in objc. I am translating them to swift. The following code from page 150 does not work for me. It throws EXC_BAD_INSTRUCTION. Could anybody please point where I am wrong? Thank you for your help.

func drawHypnoticMessage(message: NSString) {
    for i in 0..20 {
        let messageLabel = UILabel()
        messageLabel.backgroundColor = UIColor.clearColor()
        messageLabel.textColor = UIColor.whiteColor()
        messageLabel.text = message // Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP,subcode0x0)

        messageLabel.sizeToFit()

        let width = self.view.bounds.size.width - messageLabel.bounds.size.width

        let x = Int(arc4random()) % Int(width)

        let height = (self.view.bounds.size.height - messageLabel.bounds.size.height)
        let y = Int(arc4random()) % Int(height)

        var frame = messageLabel.frame
        frame.origin = CGPointMake(CGFloat(x), CGFloat(y))
        messageLabel.frame = frame

        self.view.addSubview(messageLabel)
    }
}

NB: I have tried replacing

messageLabel.text = message

with

messageLabel.text = "text"

UPDATE 1:

I found the solution

func drawHypnoticMessage(message: NSString) {
    for i in 0..<20 {
        let messageLabel = UILabel()
        messageLabel.backgroundColor = UIColor.clearColor()
        messageLabel.textColor = UIColor.whiteColor()
        messageLabel.text = message

        messageLabel.sizeToFit()

        let width = self.view.bounds.size.width - messageLabel.bounds.size.width

        let x = Int(arc4random() % UInt32(width))

        let height = (self.view.bounds.size.height - messageLabel.bounds.size.height)
        let y = Int(arc4random() % UInt32(height))

        var frame = messageLabel.frame
        frame.origin = CGPointMake(CGFloat(x), CGFloat(y))
        messageLabel.frame = frame

        self.view.addSubview(messageLabel)
    }
}

Basically, I change let x = Int(arc4random()) % Int(width) to let x = Int(arc4random() % UInt32(width)) . Does anybody know why it work?

UPDATE 2:

Latest revision using arc4random_uniform :

func drawHypnoticMessage(message: NSString) {
    for i in 0..<20 {
        let messageLabel = UILabel()
        messageLabel.backgroundColor = UIColor.clearColor()
        messageLabel.textColor = UIColor.whiteColor()
        messageLabel.text = message

        messageLabel.sizeToFit()

        let width = self.view.bounds.size.width - messageLabel.bounds.size.width

        let x = CGFloat(arc4random_uniform(UInt32(width)))

        let height = (self.view.bounds.size.height - messageLabel.bounds.size.height)
        let y = CGFloat(arc4random_uniform(UInt32(height)))

        var frame = messageLabel.frame
        frame.origin = CGPointMake(x, y)
        messageLabel.frame = frame

        self.view.addSubview(messageLabel)
    }
}

Judging by the fix you provided, I think the problem is that arc4random returns a 32 bit unsigned integer between 0 and 2 32 - 1. You were then converting it to an Int which (I believe) is a 32 bit signed integer in iOS (32 bit mode), so half your random numbers (those between 2 31 and 2 32 - 1) are not expressible as an Int .

In the new code, you limit the random number to either 0 to width or 0 to height brefore you try to convert it to Int which is why it doesn't crash.

NB. Rather than using % you should use arc4random_uniform() . Taking the mod of a random number introduces a bias, that is avoided with arc4random_uniform().

Have you tried to change "let messageLabel" to "var messageLabel"?

Edit: I want to correct myself. In this case, "let messageLabel" is the right way to declare the UILabel. "let" is for constants, but when declaring "let messageLabel = UILabel()," we are saying that the pointer to UILabel is constant, not that UILabel can't be changed after declaration.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM