I have a big problem, I create an serial UIbutton when I click manually on a button, I change the background color and fill color, and unclick color change for normal state.
but when my program select a random button, sequence is good, but the button not change on real time and don't see what is button is selected (no background color, not fill color) I don't understand why , I see on other question a possibility with setNeedsDisplay, setEnable, .... but don't work for my ...
have you resolve this refresh problem ? how I refresh my button (button.setNeedsDisplay() not work)
see my program for see, I use soundEnd boolean value when my mp3 ending play and nextSound boolean value when my button is on normal state. Sleep is use for slow loop and wait mp3 play ending , if not multiple choice not work ... I found this solution but not for background and fill color
Thanks !
//
// ViewController.swift
// test
//
// Created by Thierry on 03/06/2020.
// Copyright © 2020 Thierry All rights reserved.
//
import UIKit
let squareSize = 100
let borderSpace = 20
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let zone3 = UIView(frame: CGRect(x: 10, y: 10, width: view.frame.width-20, height: view.frame.height-20))
zone3.backgroundColor = .red
view.addSubview(squareDraw(contentView: zone3))
DispatchQueue.main.asyncAfter(deadline: .now() + 5.0) {
for randomInt in 1..<13 {
print(randomInt)
let subview = self.view.viewWithTag(randomInt)
let button = subview as! UIButton
button.sendActions(for: .touchDown)
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
button.sendActions(for: .touchUpInside)
}
sleep(3)
}
}
}
func squareDraw(contentView : UIView) ->UIView {
let widthScreen: Int = Int(contentView.bounds.width)
let heightScreen: Int = Int(contentView.bounds.height)
let scaleFactorX = (widthScreen*100/((3 * squareSize) + (4 * borderSpace)))
let scaleFactorY = (heightScreen*100/((4 * squareSize) + (5 * borderSpace)))
let squareSizeScaleX = (squareSize * scaleFactorX)/100
let squareSizeScaleY = (squareSize * scaleFactorY)/100
let borderSpaceScaleX = (borderSpace * scaleFactorX)/100
let borderSpaceScaleY = (borderSpace * scaleFactorY)/100
let originY = 0
var Tag = 0
for yCoord in 1...4 {
for xCoord in 1...3 {
Tag = Tag + 1
let k = button(CGRect(x: xCoord * (squareSizeScaleX + borderSpaceScaleX) - squareSizeScaleX, y: originY + (yCoord * (squareSizeScaleY + borderSpaceScaleY) - squareSizeScaleY), width: squareSizeScaleX, height: squareSizeScaleY), tag: Tag)
contentView.addSubview(k)
}
}
return contentView
}
func button(_ rect: CGRect, tag: Int) ->UIView {
let myButton = UIButton(type: .system)
myButton.frame = CGRect(x:CGFloat(rect.minX), y:CGFloat(rect.minY), width:CGFloat(rect.width), height:CGFloat(rect.height))
myButton.tag = tag
myButton.backgroundColor = .white
myButton.layer.borderWidth = 5
myButton.layer.borderColor = UIColor.white.cgColor
myButton.addTarget(self, action: #selector(buttonSelected), for: .touchUpInside)
myButton.addTarget(self, action: #selector(buttonReleased), for: .touchDown )
return myButton
}
@objc func buttonSelected(sender: UIButton) {
let button = sender
if button.isSelected == true {
} else {
button.layer.borderWidth = 5
button.layer.borderColor = UIColor.white.cgColor
}
}
@objc func buttonReleased(sender: UIButton) {
let button = sender
if button.isEnabled == true {
button.layer.borderWidth = 5
button.layer.borderColor = UIColor.black.cgColor
} else {
}
}
}
First you never want to use sleep(2)
- it freezes your program for 2 seconds, and nothing else can happen. There are rare exceptions, but you definitely do not want that here.
It's still a bit confusing what you really want to do. Your question says "soundEnd boolean value when my mp3 ending play"?
So, here is an example - using some of your code.
viewDidLoad()
viewDidAppear()
This will loop through the number of sound clips you have:
class SoundTestViewController: UIViewController, AVAudioPlayerDelegate {
let squareSize = 100
let borderSpace = 20
var myPlayer: AVAudioPlayer = AVAudioPlayer()
// start at -1 so first call to "play next" will increment it to 0
var soundNumber: Int = -1
// replace with your mp3 file names
let mp3FileNames: [String] = [
"clip1",
"clip2",
"clip3",
"clip4",
]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let zone3 = UIView(frame: CGRect(x: 10, y: 10, width: view.frame.width-20, height: view.frame.height-20))
zone3.backgroundColor = .red
view.addSubview(squareDraw(contentView: zone3))
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
playNextSoundFile()
}
func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
player.stop()
if let subview = self.view.viewWithTag(soundNumber + 1) as? UIButton {
subview.layer.borderColor = UIColor.white.cgColor
}
playNextSoundFile()
}
func playNextSoundFile() {
soundNumber += 1
if soundNumber > mp3FileNames.count - 1 {
soundNumber = 0
}
guard let url = Bundle.main.url(forResource: mp3FileNames[soundNumber], withExtension: ".mp3") else {
// mp3 file not found in bundle
return
}
do {
if let subview = self.view.viewWithTag(soundNumber + 1) as? UIButton {
subview.layer.borderColor = UIColor.black.cgColor
}
let sound = try AVAudioPlayer(contentsOf: url)
self.myPlayer = sound
// set the audio player delegate to self
sound.delegate = self
sound.numberOfLoops = 0
sound.prepareToPlay()
sound.play()
} catch {
print("error initializing audio player")
}
}
func squareDraw(contentView : UIView) ->UIView {
let widthScreen: Int = Int(contentView.bounds.width)
let heightScreen: Int = Int(contentView.bounds.height)
let scaleFactorX = (widthScreen*100/((3 * squareSize) + (4 * borderSpace)))
let scaleFactorY = (heightScreen*100/((4 * squareSize) + (5 * borderSpace)))
let squareSizeScaleX = (squareSize * scaleFactorX)/100
let squareSizeScaleY = (squareSize * scaleFactorY)/100
let borderSpaceScaleX = (borderSpace * scaleFactorX)/100
let borderSpaceScaleY = (borderSpace * scaleFactorY)/100
let originY = 0
var Tag = 0
for yCoord in 1...4 {
for xCoord in 1...3 {
Tag = Tag + 1
let k = button(CGRect(x: xCoord * (squareSizeScaleX + borderSpaceScaleX) - squareSizeScaleX, y: originY + (yCoord * (squareSizeScaleY + borderSpaceScaleY) - squareSizeScaleY), width: squareSizeScaleX, height: squareSizeScaleY), tag: Tag)
contentView.addSubview(k)
}
}
return contentView
}
func button(_ rect: CGRect, tag: Int) ->UIView {
let myButton = UIButton(type: .system)
myButton.frame = CGRect(x:CGFloat(rect.minX), y:CGFloat(rect.minY), width:CGFloat(rect.width), height:CGFloat(rect.height))
myButton.tag = tag
myButton.backgroundColor = .white
myButton.layer.borderWidth = 5
myButton.layer.borderColor = UIColor.white.cgColor
return myButton
}
}
If that is not really what you are trying to do, maybe it will at least get you in the right direction.