【Swift】関数の引数参照前後で値が変わる??
解決したいこと
Xcodeで定期的に処理を行うアプリをつくっています。
定期的に処理を行う中である値を参照する前後で値が変わってしまう症状が見られました。
解決方法を教えて下さい。
開発環境
Xcode Version 14.2
Interface Storyboard
macOS monterey 13.0.1
問題点
以下のコードを出力した結果、2箇所の'print(deltaDegree)'で異なる値が出力されました。
出力結果は以下のとおりです。
2023-02-02 04:25:18.089535+0900 ButtonSample[43127:1394882] [plugin] AddInstanceForFactory: No factory registered for id <CFUUID 0x600003622e00> F8BB1C28-BAE8-11D6-9C31-00039315CD46
0.12195121951219512
117480667527541.67
一つ目の結果(0.12195121951219512)は、直前の計算から得られたもので、自前の電卓を用いて計算しても同様の結果が得られました。
該当するソースコード
import UIKit
import AVFoundation
class ViewController: UIViewController {
@IBOutlet weak var btnCount: UIButton!
@IBOutlet weak var btnExplosion: UIButton!
@IBOutlet weak var imgBom: UIImageView!
// ボタンフラグ
var buttonStartFlg = true
// 現時点での回転角
var currentDegree: CGFloat = 0
// 定期割り込みのための Timer のインスタンス
var timer = Timer()
var interval: TimeInterval = 0.01
override func viewDidLoad() {
super.viewDidLoad()
}
@IBAction func btnCount(_ sender: Any) {
btnCount.isEnabled = false
btnExplosion.isEnabled = true
// 初期スピード
let degree: CGFloat = 30
// 回転処理に使われるメソッドは rotateImage)
timer = Timer.scheduledTimer(timeInterval: interval, target: self, selector: #selector(rotateImage), userInfo: degree, repeats: true)
buttonStartFlg = false
}
@IBAction func btnExplosion(_ sender: Any) {
// 初期スピード
let degree: CGFloat = 30
let stopDegree: CGFloat = 90.0
let dDmolecule = 0.5 * pow(degree, 2)
currentDegree = 0
let dDdenominator = (360.0 * 10) + stopDegree
let deltaDegree = dDmolecule / dDdenominator
print(deltaDegree)
// 定期的な呼び出しを中止する
timer.invalidate()
// 回転を徐々に止めるためのメソッドを1回だけ(repeats: false)呼び出し
// 止めるために使われるメソッドは stopImage
timer = Timer.scheduledTimer(timeInterval: interval, target: self, selector: #selector(stopImage(_:deltaDegree:)), userInfo: degree, repeats: false)
}
@objc func rotateImage(_ sender: Timer) {
let degree = sender.userInfo as! CGFloat
let angle = currentDegree * CGFloat.pi / 180 // Radian
let affine = CGAffineTransform(rotationAngle: angle)
imgBom.transform = affine
currentDegree += degree
currentDegree.formRemainder(dividingBy: 360.0)
}
// ストップボタンを押した後、止まるまで呼び出される回転処理
@objc func stopImage(_ sender: Timer , deltaDegree: CGFloat) {
print(deltaDegree)
var degree = sender.userInfo as! CGFloat
let angle = currentDegree * CGFloat.pi / 180 // Radian
let affine = CGAffineTransform(rotationAngle: angle)
imgBom.transform = affine
currentDegree += degree
currentDegree.formRemainder(dividingBy: 360.0)
// 回転角を減らす
degree -= deltaDegree
if degree > 0 {
// 回転角が正の間は、減らした回転角を使って再度タイマ割り込みを使う
timer = Timer.scheduledTimer(timeInterval: interval, target: self, selector: #selector(stopImage(_:deltaDegree:)), userInfo: degree, repeats: false)
}
}
}
自分で試したこと
このコードは以下のサイトを参考に記述しました。
0