ã¿ã€ããŒã¯ãã¢ããªã±ãŒã·ã§ã³ã®ã¢ã¯ã·ã§ã³ãèšç»ããããã«äœ¿çšãããŸãã ããã¯ã1åéãã®ã¢ã¯ã·ã§ã³ãŸãã¯ç¹°ãè¿ãæé ã§ãã
ãã®ã¬ã€ãã§ã¯ãiOSã§ã¿ã€ããŒãã©ã®ããã«æ©èœããããUIã®å¿çæ§ã«ã©ã®ããã«åœ±é¿ããããã¿ã€ããŒäœ¿çšæã®ããããªãŒæ¶è²»ãæé©åããæ¹æ³ãããã³ã¢ãã¡ãŒã·ã§ã³ã«CADisplayLinkã䜿çšããæ¹æ³ãåŠç¿ããŸãã
ãã¹ããµã€ããšããŠãã¢ããªã±ãŒã·ã§ã³-ããªããã£ãã¿ã¹ã¯ã¹ã±ãžã¥ãŒã©ã䜿çšããŸãã
ã¯ããã«
ãœãŒã¹ãããžã§ã¯ããããŠã³ããŒãããŸãã Xcodeã§éãããã®æ§é ãèŠãŠãã³ã³ãã€ã«ããŠå®è¡ããŸãã æãç°¡åãªã¿ã¹ã¯ã¹ã±ãžã¥ãŒã©ã衚瀺ãããŸãã

æ°ããã¿ã¹ã¯ãè¿œå ããŸãã [+]ã¢ã€ã³ã³ãã¿ããããã¿ã¹ã¯ã®ååãå ¥åããŠã[OK]ãã¿ããããŸãã
è¿œå ãããã¿ã¹ã¯ã«ã¯ã¿ã€ã ã¹ã¿ã³ãããããŸãã äœæããã°ããã®æ°ããã¿ã¹ã¯ã«ã¯ãŒãç§ã®ããŒã¯ãä»ããããŸãã ã芧ã®ãšããããã®å€ã¯å¢å ããŸããã
åã¿ã¹ã¯ã¯å®äºæžã¿ãšããŠããŒã¯ã§ããŸãã ã¿ã¹ã¯ãã¿ããããŸãã ã¿ã¹ã¯åã¯åãæ¶ãç·ã§è¡šç€ºãããå®äºãšããŠããŒã¯ãããŸãã
æåã®ã¿ã€ããŒãäœæãã
ã¢ããªã±ãŒã·ã§ã³ã®ã¡ã€ã³ã¿ã€ããŒãäœæããŸãããã NSTimerãšããŠãç¥ãããTimerã¯ã©ã¹ã¯ãåäžããã³å®æçãªç¹å®ã®ç¬éã«ã¢ã¯ã·ã§ã³ãã¹ã±ãžã¥ãŒã«ãã䟿å©ãªæ¹æ³ã§ãã
TaskListViewController.swiftãéãããã®å€æ°ãTaskListViewControllerã«è¿œå ããŸãã
var timer: Timer?
次ã«ãæ¡åŒµæ©èœãè¿œå ããŸãã
// MARK: - Timer extension TaskListViewController { }
ãããŠããã®ã³ãŒããæ¡åŒµæ©èœã«è²Œãä»ããŸãã
@objc func updateTimer() { // 1 guard let visibleRowsIndexPaths = tableView.indexPathsForVisibleRows else { return } for indexPath in visibleRowsIndexPaths { // 2 if let cell = tableView.cellForRow(at: indexPath) as? TaskTableViewCell { cell.updateTime() } } }
ãã®æ¹æ³ã§ã¯ã次ã®ããšãè¡ããŸãã
- ã¿ã¹ã¯ããŒãã«ã«è¡šç€ºå¯èœãªè¡ããããã©ããã確èªããŸãã
- 衚瀺ãããŠããåã»ã«ã«å¯ŸããŠupdateTimeãåŒã³åºããŸã ã ãã®ã¡ãœããã¯ãã»ã«ã®ã¿ã€ã ã¹ã¿ã³ããæŽæ°ããŸãïŒ TaskTableViewCell.swiftãåç §ïŒã
次ã«ããã®ã³ãŒããæ¡åŒµæ©èœã«è¿œå ããŸãã
func createTimer() { // 1 if timer == nil { // 2 timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(updateTimer), userInfo: nil, repeats: true) } }
ããã«ãããŸãïŒ
- ã¿ã€ããŒã«Timerã¯ã©ã¹ã®ã€ã³ã¹ã¿ã³ã¹ãå«ãŸããŠãããã©ããã確èªããŸãã
- ããã§ãªãå Žåã¯ã updateTimerïŒïŒãæ¯ç§åŒã³åºãã¿ã€ããŒãäœæããŸãã
次ã«ããŠãŒã¶ãŒãæåã®ã¿ã¹ã¯ãè¿œå ãããããã«ã¿ã€ããŒãäœæããå¿ èŠããããŸãã presentAlertControllerïŒ_ :)ã¡ãœããã®æåã«createTimerïŒïŒãè¿œå ããŸãã
ã¢ããªã±ãŒã·ã§ã³ãèµ·åããããã€ãã®æ°ããã¿ã¹ã¯ãäœæããŸãã åã¿ã¹ã¯ã®ã¿ã€ã ã¹ã¿ã³ãã1ç§ããšã«å€åããããšãããããŸãã

ã¿ã€ããŒã®èš±å®¹å€ãè¿œå
ã¿ã€ããŒã®æ°ãå¢ãããšãUIã®å¿çæ§ãäœäžããããããªãŒæ¶è²»ãå¢å ããŸãã åã¿ã€ããŒã¯ãããã©ã«ãã§ã¯èš±å®¹å€ããŒãã§ãããããå²ãåœãŠãããæå»ã«æ£ç¢ºã«å®è¡ããããšããŸãã
ã¿ã€ããŒã®èš±å®¹å€ãè¿œå ãããšããšãã«ã®ãŒæ¶è²»ãç°¡åã«åæžã§ããŸãã ããã«ãããã·ã¹ãã ã¯ãå²ãåœãŠãããæéãšå²ãåœãŠãããæéãšèš±å®¹æéã®éã«ã¿ã€ããŒã¢ã¯ã·ã§ã³ãå®è¡ã§ããŸãã
äžåºŠã ãå®è¡ãããã¿ã€ããŒã®å Žåã蚱容å€ã¯ç¡èŠãããŸãã
createTimerïŒïŒã¡ãœããã§ãã¿ã€ããŒã®å²ãåœãŠã®çŽåŸã«ã次ã®è¡ãè¿œå ããŸãã
timer?.tolerance = 0.1
ã¢ããªãèµ·åããŸãã ãã®ç¹å®ã®ã±ãŒã¹ã§ã¯ãå¹æã¯æãââãã§ã¯ãããŸããïŒã¿ã€ããŒã¯1ã€ãããããŸããïŒããè€æ°ã®ã¿ã€ããŒã®å®éã®ç¶æ³ã§ã¯ããŠãŒã¶ãŒã¯ããå¿çæ§ã®é«ãã€ã³ã¿ãŒãã§ã€ã¹ãååŸããã¢ããªã±ãŒã·ã§ã³ã¯ãšãã«ã®ãŒå¹çãåäžããŸãã

ããã¯ã°ã©ãŠã³ãã§ã®ã¿ã€ããŒ
èå³æ·±ãããšã«ãã¢ããªã±ãŒã·ã§ã³ãããã¯ã°ã©ãŠã³ãã«ç§»è¡ãããšãã¿ã€ããŒã¯ã©ããªããŸããïŒ ããã«å¯ŸåŠããã«ã¯ã updateTimerïŒïŒã¡ãœããã®æåã«æ¬¡ã®ã³ãŒããè¿œå ããŸãã
if let fireDateDescription = timer?.fireDate.description { print(fireDateDescription) }
ããã«ãããã³ã³ãœãŒã«ã§ã¿ã€ããŒã€ãã³ãã远跡ã§ããŸãã
ã¢ããªã±ãŒã·ã§ã³ãèµ·åããã¿ã¹ã¯ãè¿œå ããŸãã ããã€ã¹ã®[ããŒã ]ãã¿ã³ãæŒããŠãã¢ããªã±ãŒã·ã§ã³ã«æ»ããŸãã
ã³ã³ãœãŒã«ã«ã¯ã次ã®ãããªãã®ã衚瀺ãããŸãã

ã芧ã®ãšãããã¢ããªã±ãŒã·ã§ã³ãããã¯ã°ã©ãŠã³ãã«ç§»è¡ãããšãiOSã¯å®è¡äžã®ãã¹ãŠã®ã¢ããªã±ãŒã·ã§ã³ã¿ã€ããŒãäžæåæ¢ããŸãã ã¢ããªã±ãŒã·ã§ã³ãã¢ã¯ãã£ãã«ãªããšãiOSã¯ã¿ã€ããŒãåéããŸãã
å®è¡ã«ãŒãã«ã€ããŠ
å®è¡ã«ãŒãã¯ãäœæ¥ãã¹ã±ãžã¥ãŒã«ããçä¿¡ã€ãã³ããåŠçããã€ãã³ãã«ãŒãã§ãã ãµã€ã¯ã«ã¯ãå®è¡äžã®ã¹ã¬ãããããžãŒç¶æ ã«ä¿ã¡ãäœæ¥ããªãå Žåãã¹ã¬ããããã¹ãªãŒããç¶æ ã«ããŸãã
ã¢ããªã±ãŒã·ã§ã³ãèµ·åãããã³ã«ãã·ã¹ãã ã¯ã¢ããªã±ãŒã·ã§ã³ã®ã¡ã€ã³ã¹ã¬ãããäœæããåã¹ã¬ããã«ã¯èªåçã«äœæãããå®è¡ã«ãŒãããããŸãã
ãããããªããã®æ å ±ããã¹ãŠããªãã«ãšã£ãŠéèŠãªã®ã§ããããïŒ ããã§ããã¹ãŠã®ã¿ã€ããŒãã¡ã€ã³ã¹ã¬ããã§éå§ãããå®è¡ã«ãŒãã«åå ããŸãã ã¡ã€ã³ã¹ã¬ããããŠãŒã¶ãŒã€ã³ã¿ãŒãã§ã€ã¹ã®ã¬ã³ããªã³ã°ãã¿ããã®åŠçãªã©ã«é¢äžããŠããããšããåç¥ã§ãããã ã¡ã€ã³ã¹ã¬ãããäœãã§ããžãŒãªå Žåãã¢ããªã±ãŒã·ã§ã³ã®ã€ã³ã¿ãŒãã§ã€ã¹ããå¿çããªããïŒãã³ã°ããïŒããšããããŸãã
ããŒãã«ãã¥ãŒããã©ãã°ããŠããã»ã«ã®ã¿ã€ã ã¹ã¿ã³ããæŽæ°ãããªãããšã«æ°ä»ããŸãããïŒ

å¥ã®ã¢ãŒãã§ã¿ã€ããŒãéå§ããããå®è¡ãµã€ã¯ã«ã«æ瀺ããããšã«ããããã®åé¡ã解決ã§ããŸãã
å®è¡ãµã€ã¯ã«ã¢ãŒãã«ã€ããŠ
å®è¡ãµã€ã¯ã«ã¢ãŒãã¯ãç»é¢ã«è§ŠãããããŠã¹ã§ã¯ãªãã¯ãããªã©ãç£èŠå¯èœãªå ¥åãœãŒã¹ã®ã»ãããšãéç¥ãåãåãããªãã¶ãŒããŒãã®ã»ããã§ãã
iOSã«ã¯3ã€ã®ã©ã³ã¿ã€ã ã¢ãŒãããããŸãã
ããã©ã«ã ïŒNSConnectionObjectsã§ã¯ãªãå ¥åãœãŒã¹ãåŠçãããŸãã
common ïŒå ¥åãµã€ã¯ã«ã®ã»ãããåŠçãããŠããŸããå ¥åãœãŒã¹ãã¿ã€ããŒãããªãã¶ãŒããŒãã®ã»ãããå®çŸ©ã§ããŸãã
ãã©ããã³ã° ïŒã¢ããªã±ãŒã·ã§ã³UIãåŠçãããŠããŸãã
ãã®ã¢ããªã±ãŒã·ã§ã³ã§ã¯ãæãé©åãªã¢ãŒããäžè¬çã§ãã ããã䜿çšããã«ã¯ã createTimerïŒïŒã¡ãœããã®å 容ã次ã®ãã®ã«çœ®ãæããŸãã
if timer == nil { let timer = Timer(timeInterval: 1.0, target: self, selector: #selector(updateTimer), userInfo: nil, repeats: true) RunLoop.current.add(timer, forMode: .common) timer.tolerance = 0.1 self.timer = timer }
åã®ã³ãŒããšã®äž»ãªéãã¯ãã¿ã€ããŒãTaskListViewControllerã«å²ãåœãŠãåã«ããã®ã¿ã€ããŒãå ±éã¢ãŒãã§å®è¡ã«ãŒãã«è¿œå ããããšã§ãã
ã¢ããªã±ãŒã·ã§ã³ãã³ã³ãã€ã«ããŠå®è¡ããŸãã

ããŒãã«ãã¹ã¯ããŒã«ãããŠããã»ã«ã®ã¿ã€ã ã¹ã¿ã³ããæŽæ°ãããããã«ãªããŸããã
ã¢ãã¡ãŒã·ã§ã³ãè¿œå ããŠãã¹ãŠã®ã¿ã¹ã¯ãå®äºããŸã
次ã«ããŠãŒã¶ãŒããã¹ãŠã®ã¿ã¹ã¯ãå®äºããããã®ãç¥ãã®ã¢ãã¡ãŒã·ã§ã³ãè¿œå ããŸããããŒã«ã¯ç»é¢ã®äžéšããæäžéšãŸã§äžæããŸãã
TaskListViewControllerã®å é ã«ãããã®å€æ°ãè¿œå ããŸãã
// 1 var animationTimer: Timer? // 2 var startTime: TimeInterval?, endTime: TimeInterval? // 3 let animationDuration = 3.0 // 4 var height: CGFloat = 0
ãããã®å€æ°ã®ç®çã¯æ¬¡ã®ãšããã§ãã
- ã¢ãã¡ãŒã·ã§ã³ã¿ã€ããŒã¹ãã¬ãŒãžã
- ã¢ãã¡ãŒã·ã§ã³ã®éå§ãšçµäºã®æéã®ä¿åã
- ã¢ãã¡ãŒã·ã§ã³æéã
- ã¢ãã¡ãŒã·ã§ã³ã®é«ãã
次ã«ã TaskListViewController.swiftãã¡ã€ã«ã®æåŸã«æ¬¡ã®TaskListViewController æ¡åŒµæ©èœãè¿œå ããŸãã
// MARK: - Animation extension TaskListViewController { func showCongratulationAnimation() { // 1 height = UIScreen.main.bounds.height + balloon.frame.size.height // 2 balloon.center = CGPoint(x: UIScreen.main.bounds.width / 2, y: height + balloon.frame.size.height / 2) balloon.isHidden = false // 3 startTime = Date().timeIntervalSince1970 endTime = animationDuration + startTime! // 4 animationTimer = Timer.scheduledTimer(withTimeInterval: 1 / 60, repeats: true) { timer in // TODO: Animation here } } }
ããã§ã¯æ¬¡ã®ããšãè¡ããŸãã
- ã¢ãã¡ãŒã·ã§ã³ã®é«ããèšç®ããããã€ã¹ç»é¢ã®é«ããååŸããŸã
- ç»é¢ã®å€åŽã«ããŒã«ãäžå€®ã«é 眮ãããã®å¯èŠæ§ãèšå®ããŸã
- ã¢ãã¡ãŒã·ã§ã³ã®éå§æéãšçµäºæéãå²ãåœãŠãŸã
- ã¢ãã¡ãŒã·ã§ã³ã¿ã€ããŒãéå§ãã1ç§ããã60åã¢ãã¡ãŒã·ã§ã³ãæŽæ°ããŸã
次ã«ããç¥ãã¢ãã¡ãŒã·ã§ã³ãæŽæ°ããããã®å®éã®ããžãã¯ãäœæããå¿ èŠããããŸãã showCongratulationAnimationïŒïŒã®åŸã«ãã®ã³ãŒããè¿œå ããŸãã
func updateAnimation() { // 1 guard let endTime = endTime, let startTime = startTime else { return } // 2 let now = Date().timeIntervalSince1970 // 3 if now >= endTime { animationTimer?.invalidate() balloon.isHidden = true } // 4 let percentage = (now - startTime) * 100 / animationDuration let y = height - ((height + balloon.frame.height / 2) / 100 * CGFloat(percentage)) // 5 balloon.center = CGPoint(x: balloon.center.x + CGFloat.random(in: -0.5...0.5), y: y) }
ç§ãã¡ãããããšïŒ
- endTimeãšstartTimeãå²ãåœãŠãããŠããããšã確èªããŸã
- çŸåšã®æéãå®æ°ã§ä¿åãã
- æçµæéããŸã å°çããŠããªãããšã確èªããŸãã ãã§ã«å°çããŠããå Žåã¯ãã¿ã€ããŒãæŽæ°ããŠããŒã«ãé衚瀺ã«ããŸã
- ããŒã«ã®æ°ããy座æšãèšç®ããŸã
- ããŒã«ã®æ°Žå¹³äœçœ®ã¯åã®äœçœ®ãåºæºã«ããŠèšç®ãããŸã
// TODOïŒAnimationãshowCongratulationAnimationïŒïŒã®æ¬¡ã®ã³ãŒãã«çœ®ãæããŸãã
self.updateAnimation()
çŸåšãã¿ã€ããŒã€ãã³ããçºçãããã³ã«updateAnimationïŒïŒãåŒã³åºãããŸãã
ã»ããã¢ãã¡ãŒã·ã§ã³ãäœæããŸããã ãã ããã¢ããªã±ãŒã·ã§ã³ãèµ·åããŠããæ°ããããšã¯äœãèµ·ãããŸãã...
ã¢ãã¡ãŒã·ã§ã³ã衚瀺ãã
ãããããæ³åã®ãšãããæ°ããã¢ãã¡ãŒã·ã§ã³ããèµ·åããããã®ã¯äœããããŸããã ãããè¡ãã«ã¯ãå¥ã®æ¹æ³ãå¿ èŠã§ãã ãã®ã³ãŒããTaskListViewControllerã¢ãã¡ãŒã·ã§ã³æ¡åŒµæ©èœã«è¿œå ããŸãã
func showCongratulationsIfNeeded() { if taskList.filter({ !$0.completed }).count == 0 { showCongratulationAnimation() } }
ãŠãŒã¶ãŒãã¿ã¹ã¯ãå®äºãšããŒã¯ãããã³ã«ãã®ã¡ãœãããåŒã³åºãããã¹ãŠã®ã¿ã¹ã¯ãå®äºãããã©ããã確èªããŸãã ãã®å Žåã showCongratulationAnimationïŒïŒãåŒã³åºããŸãã
çµè«ãšããŠã tableViewïŒ_ïŒdidSelectRowAt :)ã®æåŸã«ãã®ã¡ãœãããžã®åŒã³åºããè¿œå ããŸãã
showCongratulationsIfNeeded()
ã¢ããªã±ãŒã·ã§ã³ãèµ·åããããã€ãã®ã¿ã¹ã¯ãäœæããå®äºæžã¿ãšããŠããŒã¯ãããšãã¢ãã¡ãŒã·ã§ã³ã衚瀺ãããŸãïŒ

ã¿ã€ããŒãåæ¢ããŸã
ã³ã³ãœãŒã«ãèŠããšããŠãŒã¶ãŒããã¹ãŠã®ã¿ã¹ã¯ã«å®äºããŒã¯ãä»ããŠããŠããã¿ã€ããŒã¯åäœãç¶ããŠããããšãããããŸãã ããã¯å®å šã«ç¡æå³ãªã®ã§ãå¿ èŠã®ãªããšãã«ã¿ã€ããŒãåæ¢ããã®ã¯çã«ããªã£ãŠããŸãã
ãŸããã¿ã€ããŒãåæ¢ããæ°ããã¡ãœãããäœæããŸãã
func cancelTimer() { timer?.invalidate() timer = nil }
ããã«ããã¿ã€ããŒãæŽæ°ãããnilã«ãªã»ããããããããåŸã§åã³æ£ããäœæã§ããŸãã invalidateïŒïŒã¯ãå®è¡ã«ãŒãããã¿ã€ããŒãåé€ããå¯äžã®æ¹æ³ã§ãã å®è¡ã«ãŒãã¯ã invalidateïŒïŒãåŒã³åºããçŽåŸãŸãã¯å°ãåŸã«åŒ·åãªã¿ã€ããŒåç §ãåé€ããŸãã
次ã«ãshowCongratulationsIfNeededïŒïŒã¡ãœããã次ã®ããã«çœ®ãæããŸãã
func showCongratulationsIfNeeded() { if taskList.filter({ !$0.completed }).count == 0 { cancelTimer() showCongratulationAnimation() } else { createTimer() } }
ããã§ããŠãŒã¶ãŒããã¹ãŠã®ã¿ã¹ã¯ãå®äºãããšãã¢ããªã±ãŒã·ã§ã³ã¯æåã«ã¿ã€ããŒããªã»ããããŠããã¢ãã¡ãŒã·ã§ã³ã衚瀺ããŸãããã以å€ã®å Žåã¯ãæ°ããã¿ã€ããŒãäœæããããšããŸãã
ã¢ããªãèµ·åããŸãã

ããã§ãã¿ã€ããŒãåæ¢ããå¿ èŠã«å¿ããŠåèµ·åããŸãã
ã¹ã ãŒãºãªã¢ãã¡ãŒã·ã§ã³ã®ããã®CADisplayLink
ã¿ã€ããŒã¯ãã¢ãã¡ãŒã·ã§ã³ãå¶åŸ¡ããããã®çæ³çãªéžæã§ã¯ãããŸããã ç¹ã«ã·ãã¥ã¬ãŒã¿ã§ã¢ããªã±ãŒã·ã§ã³ãå®è¡ããå Žåãããã€ãã®ãã¬ãŒã ã§ã¢ãã¡ãŒã·ã§ã³ãã¹ããããããããšããããŸãã
ã¿ã€ããŒã60Hzã«èšå®ããŸãã ãããã£ãŠãã¿ã€ããŒã¯16ããªç§ããšã«ã¢ãã¡ãŒã·ã§ã³ãæŽæ°ããŸãã ç¶æ³ããã詳现ã«æ€èšããŠãã ããã

ã¿ã€ããŒã䜿çšããå Žåãã¢ã¯ã·ã§ã³ãéå§ãããæ£ç¢ºãªæéã¯ããããŸããã ããã¯ããã¬ãŒã ã®éå§æãŸãã¯çµäºæã«çºçããå¯èœæ§ããããŸãã ã¿ã€ããŒãåãã¬ãŒã ã®äžå€®ã§å®è¡ããããšããŸãããïŒåçã®éãç¹ïŒã 確ãã«ããã£ãŠããã®ã¯ãåŒã³åºãã16ããªç§ããšã«ãªãããšã§ãã
ããã§ãã¢ãã¡ãŒã·ã§ã³ãå®è¡ããã®ã«å¿ èŠãªæéã¯8ããªç§ã«ãªããŸããããããã§ã¯ã¢ãã¡ãŒã·ã§ã³ã«ååã§ãªãå¯èœæ§ããããŸãã å³ã®2çªç®ã®ãã¬ãŒã ãèŠãŠã¿ãŸãããã 2çªç®ã®ãã¬ãŒã ã¯å²ãåœãŠãããæéå ã«å®äºã§ããªããããã¢ããªã±ãŒã·ã§ã³ã¯ã¢ãã¡ãŒã·ã§ã³ã®2çªç®ã®ãã¬ãŒã ããªã»ããããŸãã
CADisplayLinkã¯ç§ãã¡ãå©ããŸã
CADisplayLinkã¯ãã¬ãŒã ããšã«1ååŒã³åºãããå¯èœãªéãå®éã®ã¢ãã¡ãŒã·ã§ã³ãã¬ãŒã ãåæããããšããŸãã ããã§ã16 msããã¹ãŠèªç±ã«äœ¿çšã§ããããã«ãªããiOSã¯åäžã®ãã¬ãŒã ãããããããªããªããŸãã
CADisplayLinkã䜿çšããã«ã¯ã animationTimerãæ°ããã¿ã€ãã«çœ®ãæããå¿ èŠããããŸãã
ãã®ã³ãŒãã眮ãæãã
var animationTimer: Timer?
ããã«ã€ããŠïŒ
var displayLink: CADisplayLink?
TimerãCADisplayLinkã«çœ®ãæããŸãã ã CADisplayLinkã¯ããã£ã¹ãã¬ã€ã®åçŽã¹ãã£ã³ã«é¢é£ä»ããããã¿ã€ããŒãã¥ãŒã§ãã ããã¯ãç»é¢ãGPUã³ãã³ãã®åŠçãç¶è¡ã§ããããã«ãªããŸã§ãããã€ã¹ã®GPUãäžæåæ¢ããããšãæå³ããŸãã ããã«ãããã¹ã ãŒãºãªã¢ãã¡ãŒã·ã§ã³ãåŸãããŸãã
ãã®ã³ãŒãã眮ãæãã
var startTime: TimeInterval?, endTime: TimeInterval?
ããã«ã€ããŠïŒ
var startTime: CFTimeInterval?, endTime: CFTimeInterval?
TimeDisplayãCFDisplayIntervalã«çœ®ãæããŸãããããã¯ãCADisplayLinkã§ã®äœæ¥ã«å¿ èŠã§ãã
showCongratulationAnimationïŒïŒã¡ãœããã®ããã¹ããããã«çœ®ãæããŸãïŒ
func showCongratulationAnimation() { // 1 height = UIScreen.main.bounds.height + balloon.frame.size.height balloon.center = CGPoint(x: UIScreen.main.bounds.width / 2, y: height + balloon.frame.size.height / 2) balloon.isHidden = false // 2 startTime = CACurrentMediaTime() endTime = animationDuration + startTime! // 3 displayLink = CADisplayLink(target: self, selector: #selector(updateAnimation)) displayLink?.add(to: RunLoop.main, forMode: .common) }
ããã§äœãããŠããŸããïŒ
- ã¢ãã¡ãŒã·ã§ã³ã®é«ããããŒã«ã®åº§æšãããã³å¯èŠæ§ãèšå®ããŸã-以åãšã»ãŒåãã§ãã
- ïŒDateïŒïŒã®ä»£ããã«ïŒCACurrentMediaTimeïŒïŒã§ startTimeãåæåããŸãã
- CADisplayLinkã¯ã©ã¹ã®ã€ã³ã¹ã¿ã³ã¹ãäœæãããããå ±éã¢ãŒãã§å®è¡ã«ãŒãã«è¿œå ããŸãã
updateAnimationïŒïŒã次ã®ã³ãŒãã«çœ®ãæããŸãã
// 1 @objc func updateAnimation() { guard let endTime = endTime, let startTime = startTime else { return } // 2 let now = CACurrentMediaTime() if now >= endTime { // 3 displayLink?.isPaused = true displayLink?.invalidate() balloon.isHidden = true } let percentage = (now - startTime) * 100 / animationDuration let y = height - ((height + balloon.frame.height / 2) / 100 * CGFloat(percentage)) balloon.center = CGPoint(x: balloon.center.x + CGFloat.random(in: -0.5...0.5), y: y) }
- ã¡ãœããã·ã°ããã£ã«objcãè¿œå ããŸãïŒCADisplayLinkã®å Žåãselectorãã©ã¡ãŒã¿ãŒã«ã¯ãã®ãããªã·ã°ããã£ãå¿ èŠã§ãïŒã
- åæåãDateïŒïŒã«çœ®ãæããŠã CoreAnimationã®æ¥ä»ãåæåããŸãã
- animationTimer.invalidateïŒïŒåŒã³åºããCADisplayLinkã®äžæåæ¢ã«çœ®ãæããŠç¡å¹ã«ããŸãã ããã«ãããå®è¡ã«ãŒãããCADisplayLinkãåé€ãããŸãã
ã¢ããªãèµ·åããŠãã ããïŒ

ãããïŒ ã¿ã€ããŒããŒã¹ã®ã¢ãã¡ãŒã·ã§ã³ãããé©åãªCADisplayLinkã«çœ®ãæããããšã«æåããŸããã
ãããã«
ãã®ã¬ã€ãã§ã¯ãiOSã§Timerã¯ã©ã¹ãã©ã®ããã«æ©èœããããå®è¡ãµã€ã¯ã«ãäœã§ããããã€ã³ã¿ãŒãã§ã€ã¹ã«é¢ããŠã¢ããªã±ãŒã·ã§ã³ã®å¿çæ§ãé«ããæ¹æ³ãããã³ã¹ã ãŒãºãªã¢ãã¡ãŒã·ã§ã³ã®ããã«Timerã®ä»£ããã«CADisplayLinkã䜿çšããæ¹æ³ãç解ããŸããã