ãã®èšäºã§ã¯ãããŒãã«ã»ã«ãã¹ã¯ããŒã«ããŠç»åãåçŽã«ç§»åãããšãã«ãæ¢åã®ã¢ããªã±ãŒã·ã§ã³ã«Swiftæ¡åŒµããã°ã©ãã³ã°èšèªã䜿çšããŸãã UIKitãžã®å€ææ¹æ³ã説æãããŠãããç»é¢äžã§åæã«çºçããã¢ã¯ã·ã§ã³ãå€ãããããšã«ããéè² è·ãé¿ããããã®äŸ¿å©ãªäœ¿çšæ³ã説æãããŠããŸãã ã¿ã¹ã¯ãã·ã³ãã«ãã€æ確ã«ãªããã¡ã€ã³ã³ã³ãããŒã©ãŒãã·ã³ãã«ã«ãªãããã«ãããã°ã©ã ã³ãŒããæŽçããæ¹æ³ã«é¢ãããã³ããåãåããŸãã
å§ããã«ã¯ãUITableViewãšSwiftã®åºæ¬çãªèŠçŽ ãæäœããæ¹æ³ã«æ £ããå¿ èŠããããŸãã ããã«æ £ããå¿ èŠãããå Žåã¯ã衚圢åŒã®ãã¬ãŒã³ããŒã·ã§ã³ã¢ããªã±ãŒã·ã§ã³ã«é¢ããSwiftèšèªã§ã®äœæ¥ã®åºæ¬ãåŠç¿ããSwiftãã¥ãŒããªã¢ã«ã·ãªãŒãºã«æ £ããããšãã§ããŸãã
å§ããŸãããã
ã¹ã¿ãŒã¿ãŒãããžã§ã¯ããããŠã³ããŒãããXcode 6ã§éããŸãããããžã§ã¯ãã®ç°¡åãªèª¬æïŒUITableViewControllerïŒãµãã¯ã©ã¹ïŒMainViewControllerïŒã衚瀺ãããéçºè ã衚瀺ããUITableViewCellïŒCardTableViewCellïŒãèšå®ãããŸãã ãŸããããŒã ã¡ã³ããŒã«é¢ãããã¹ãŠã®æ å ±ãèšè¿°ããã¢ããªã±ãŒã·ã§ã³å ã«ããJSONãã¡ã€ã«ãããã®æ å ±ãæœåºããæ¹æ³ãç¥ã£ãŠããMemberã¯ã©ã¹ã®äŸããããŸãã
ãããžã§ã¯ããã³ã³ãã€ã«ããŠå®è¡ããŸãã 以äžã衚瀺ãããŸãã
åªãããã¶ã€ã³ãç¹å¥ãªã¿ãããšæŽç·Žãäžããæºåãã§ããŠ
ã¢ããªã±ãŒã·ã§ã³ã¯ããã«äœ¿çšã§ããŸãããããå°ãå人䞻矩ãå«ããããšãã§ããŸããããã°ãç¬èªã®ããã€ã©ã€ãããæã€ããšãã§ããŸãã ãããããªãã®ä»äºã§ãã Core Animationã§ããã€ãã®ããªãã¯ã䜿çšããŠãããŒã¿ã»ã«ã«ã¹ãã€ã¹ãå ããŸãã
å¯èœãªéãç°¡åãªã¢ãã¡ãŒã·ã§ã³æ¹æ³ãç¹å®ããŸãã
ã¢ããªã±ãŒã·ã§ã³ã®åºæ¬æ§é ãååŸããã«ã¯ãç°¡åãªãã«ããŒã¯ã©ã¹ãäœæããããšããå§ããŸãã File \ New \ File ...ã«ç§»åãã空ã®Swiftãã¡ã€ã«ã®iOS \ Source \ Swift Fileã®ã¿ã€ããéžæããŸãã [次ãž]ãã¯ãªãã¯ãããã¡ã€ã«ã«TipInCellAnimator.swiftãšããååãä»ããŠã[äœæ]ãã¯ãªãã¯ããŸãã
ãã¡ã€ã«ã®å 容ã次ã®ã³ãŒãã«çœ®ãæããŸãã
import UIKit class TipInCellAnimator { // placeholder for things to come -- only fades in for now class func animate(cell:UITableViewCell) { if let view = cell.contentView { view.layer.opacity = 0.1 UIView.animateWithDuration(1.4) { view.layer.opacity = 1 } } } }
ãã®åçŽãªã¯ã©ã¹ã«ã¯ãããŒã¿ãå«ãã»ã«ãååŸãããã®ã³ã³ãã³ãïŒcontentViewïŒã«ã¢ã¯ã»ã¹ããã¬ã€ã€ãŒã®åæéæ床ã0.1ã«èšå®ããã¢ã«ãŽãªãºã ãå«ãŸããŠããŸãã 次ã«ã1.4ç§åŸãçµäºåŒã®ããã°ã©ã ã³ãŒãã¯ã¬ã€ã€ãŒã®éæ床ã1.0ã«æ»ããŸãã
æ³šïŒ Swift ã®åŒã¯ãå€éšå€æ°ã«ãŸãããããšãã§ããã³ãŒãã®ãããã¯ã§ãã ããšãã°ã{}ã¯åçŽãªåŒã§ãã funcãšããŠæå®ãããé¢æ°ã¯ãååä»ãåŒã®äŸã§ãã Swiftã§ã¯ãä»ã®é¢æ°å ã®é¢æ°ãéãããšãã§ããŸãã
åŒãé¢æ°ã®æåŸã®åŒæ°ãšããŠæž¡ããå Žåãç¹å¥ãªæ«å°Ÿã¯ããŒãžã£ãŒæ§æïŒæçµåŒïŒã䜿çšããŠãåŒãé¢æ°åŒã³åºãã®å€åŽã«ç§»åã§ããŸãã
åŒã®è©³çŽ°ã«ã€ããŠã¯ãSwiftããã°ã©ãã³ã°èšèªã®æ¬ãåç §ããããWikipediaã®ã¯ããŒãžã£ãŒã®è±å¯ãªèšäºãåç §ããŠãã ããã
ã¢ãã¡ãŒã·ã§ã³ã³ãŒãã®æºåãã§ããããããŒã¿ã»ã«ã衚瀺ããããšãã«æ°ããã¢ãã¡ãŒã·ã§ã³ãéå§ããããã«ããŒãã«ãæ§æããå¿ èŠããããŸãã
ã¢ãã¡ãŒã·ã§ã³ãéå§
ã¢ãã¡ãŒã·ã§ã³ãéå§ããã«ã¯ãMainViewController.swiftãã¡ã€ã«ãéãã次ã®ã¡ãœãããè¿œå ããŸãã
override func tableView(tableView: UITableView!, willDisplayCell cell: UITableViewCell!, forRowAtIndexPath indexPath: NSIndexPath!) { TipInCellAnimator.animate(cell) }
ãã®ã¢ã«ãŽãªãºã ã¯ãUITableViewDelegateãããã³ã«ã§å®çŸ©ãããã»ã«ãç»é¢ã«è¡šç€ºãããåã«åŒã³åºãããŸãã 次ã«ãã¢ãã¡ãŒã·ã§ã³ãéå§ããããã«ãTipInCellAnimatorã¯ã©ã¹ã¢ã«ãŽãªãºã ãåã»ã«ã«å¯ŸããŠåŒã³åºãããŸãã
ã¢ããªã±ãŒã·ã§ã³ãã³ã³ãã€ã«ããŠå®è¡ããŸãã æ å ±ã®è¡šãã¹ã¯ããŒã«ããŠãã»ã«ããã£ããæ¶ããæ§åã確èªããŸãã
å転å¹æ
ã¢ããªã±ãŒã·ã§ã³ãããã«é åçã«ããå転ãè¿œå ããŸãããã ããã¯ãããã¢ããã¢ãã¡ãŒã·ã§ã³ãšåãããã«æ©èœããŸãããå€æã®éå§ãšçµäºã®äž¡æ¹ãæå®ããŸãã
TipInCellAnimator.swiftãã¡ã€ã«ãéããå 容ã次ã®ãã®ã«çœ®ãæããŸãã
import UIKit import QuartzCore // 1 class TipInCellAnimator { class func animate(cell:UITableViewCell) { if let view = cell.contentView { let rotationDegrees: CGFloat = -15.0 let rotationRadians: CGFloat = rotationDegrees * (CGFloat(M_PI)/180.0) let offset = CGPointMake(-20, -20) var startTransform = CATransform3DIdentity // 2 startTransform = CATransform3DRotate(CATransform3DIdentity, rotationRadians, 0.0, 0.0, 1.0) // 3 startTransform = CATransform3DTranslate(startTransform, offset.x, offset.y, 0.0) // 4 // 5 view.layer.transform = startTransform view.layer.opacity = 0.8 // 6 UIView.animateWithDuration(0.4) { view.layer.transform = CATransform3DIdentity view.layer.opacity = 1 } } } }
ä»åã¯åããéããªãïŒ0.4ç§ïŒããããŒãã£ã³ã°ããã䟿å©ã«ãªããèå³æ·±ãå転å¹æãåŸãããŸãã åè¿°ã®ã¢ãã¡ãŒã·ã§ã³ã®ããŒã¯ãã»ã«ãå ã®äœçœ®ã«æ»ãstartTransformãããªãã¯ã¹ã«ãã£ãŠæ±ºãŸããŸãã ãããã©ã®ããã«çºçããããç解ããŸãã
1.ãã®ã¯ã©ã¹ã¯ããŒã¢ãã¡ãŒã·ã§ã³å€æã䜿çšãããããQuartzCoreãã€ã³ããŒãããå¿ èŠããããŸãã
2.ããããŒæäœãã®ç®è¡åŒã§ããå€æãèªèããããšããå§ããŸãã ãããããã©ã«ãã®ç»åå€æã§ãã
3. CATransform3DRotateã«ç§»åããŠã15床ã®å転ãååŸããŸãããã€ãã¹èšå·ã¯åæèšåãã®å転ã瀺ããŸãã 移åã¯è»ž0.0ã0.0ã1.0ãäžå¿ã«å®è¡ãããåçŽè»žzãè¡šããŸããx= 0ãy = 0ãz = 1ã§ãã
4.ããŒãã«/ã°ã©ãã¯ãã®äžå¿ã«å¯ŸããŠå転ãããããå転ã ãã®äœ¿çšã§ã¯äžååã§ãã è§åºŠããå転ããå¹æãäœæããã«ã¯ãã·ãããŸãã¯ãªãã»ãããè¿œå ããŸããè² ã®å€ã¯ãå·Šäžãžã®ç§»åã瀺ããŸãã
5.å€æçµæãå ã®ãã¥ãŒã«èšå®ããŸãã
6.ç»åãåãããŠãå ã®å€ã«æ»ããŸãã
次ã®å³ã«ç€ºãããã«ãæçµçãªå€æãäœæã§ããããšã«æ³šæããŠãã ããã
泚ïŒå€æã®ä»»æã®ãã§ãŒã³ã¯ãæçµçã«åäžã®ãããªãã¯ã¹ã§è¡šãããšãã§ããŸãã åŠæ ¡ã§è¡å代æ°ãåŠãã å Žåãè¡åã®ä¹ç®ã®ã¢ã¯ã·ã§ã³ãèŠããŠãããŠãã ããã åã¹ãããã¯ãæçµçãªãããªãã¯ã¹ã«å°éãããŸã§æ°ããå€æŽãä¹ç®ããŸãã
ãŸããã»ã«èªäœã§ã¯ãªããã»ã«ã®ã幌çšãªãå€èŠ³ãå€åããŠããããšã«æ°ä»ãã§ãããã ã»ã«å šäœãå転ããããšãäžäžã®éšåã衚瀺ãããªããªããæ¯åãã»ã«ã®ããªãã³ã°ãªã©ã®å¥åŠãªèŠèŠå¹æãåŸãããŸãã ContentViewã»ã«ã«ã¯ããã¹ãŠã®æ§æèŠçŽ ãå«ãŸããŸãã
ãã¹ãŠã®ããããã£ãã¢ãã¡ãŒã·ã§ã³ããµããŒãããããã§ã¯ãããŸããã ã ã³ã¢ã¢ãã¡ãŒã·ã§ã³ããã°ã©ãã³ã°ã¬ã€ããã«ã¯ãæ確ã«ããããã®ã¢ãã¡ãŒã·ã§ã³å¯èœãªããããã£ã®ãªã¹ãããããŸã ã
ã¢ããªã±ãŒã·ã§ã³ãã³ã³ãã€ã«ããŠå®è¡ããŸãã ããŒã¿ã»ã«ãã©ã®ããã«åŸããã確èªããŸãã
è¿ éãªãªãã¡ã¯ã¿ãªã³ã°
Objective-Cã®æ£èŠããŒãžã§ã³ã¯ãå€æã®éå§ãäžåºŠã ã決å®ããŸãã åè¿°ã®ãœãŒã¹ã³ãŒãã®ããŒãžã§ã³ã§ã¯ãæ¯åæ°ããæ¹æ³ã§animateïŒïŒã«ãã£ãŠèšç®ãããŸãã Swiftã§ãããè¡ãæ¹æ³ã¯ïŒ
1ã€ã®æ¹æ³ã¯ãåŒãžã®é·ç§»ã«ãã£ãŠæ±ºå®ãããäžå€ã¹ãã¬ãŒãžã䜿çšããããšã§ãã TipInCellAnimator.swiftãã¡ã€ã«ã®å 容ã次ã®ãã®ã«çœ®ãæããŸãã
import UIKit import QuartzCore let TipInCellAnimatorStartTransform:CATransform3D = { let rotationDegrees: CGFloat = -15.0 let rotationRadians: CGFloat = rotationDegrees * (CGFloat(M_PI)/180.0) let offset = CGPointMake(-20, -20) var startTransform = CATransform3DIdentity startTransform = CATransform3DRotate(CATransform3DIdentity, rotationRadians, 0.0, 0.0, 1.0) startTransform = CATransform3DTranslate(startTransform, offset.x, offset.y, 0.0) return startTransform }() class TipInCellAnimator { class func animate(cell:UITableViewCell) { if let view = cell.contentView { view.layer.transform = TipInCellAnimatorStartTransform view.layer.opacity = 0.8 UIView.animateWithDuration(0.4) { view.layer.transform = CATransform3DIdentity view.layer.opacity = 1 } } } }
startTransformãçæããããã°ã©ã ã³ãŒãã«æ³šæããŠãã ããã ããã¯ãTipInã¯ã©ã¹CellAnimatorStartTransformã®ããããã£ã«ãªããŸããã äœæã¡ãœããã®ããããã£ãšåãªã¯ãšã¹ãã®å€æŽãå®çŸ©ãã代ããã«ãåŒãå²ãåœãŠã空ã®æ¬åŒ§ã®ãã¢ãå²ãåœãŠãããšã«ãããããã©ã«ãã®å€æããããã£ãèšå®ããŸãã ãã©ã±ããã䜿çšãããšãåŒãããã«åŒã³åºããŠãããããã£ã«æ»ãå€ãå²ãåœãŠãããšãã§ããŸãã ãã®åæåã€ãã£ãªã ã¯ãåæåã»ã¯ã·ã§ã³ã®Appleã®Swiftã®æ¬ã§èª¬æãããŠããŸãã 詳现ã«ã€ããŠã¯ããåŒãŸãã¯é¢æ°ã®ããã©ã«ãå€ã®èšå®ããåç §ããŠãã ããã
æ³šïŒ TipInCellAnimatorStartTransformã¯ã©ã¹ã§TipInCellAnimatorããããã£ãäœæãããšäŸ¿å©ã§ãããå·çæç¹ã§ã¯ãã¯ã©ã¹ããããã£ã¯ãŸã Swiftã«å®è£ ãããŠããŸããã
å€æã«å¶çŽãè¿œå ãã
ã¢ãã¡ãŒã·ã§ã³å¹æã¯ããªãç°¡æœã§ãããæ éã«äœ¿çšããŠãã ããã ãµãŠã³ããšãã§ã¯ããŸãã¯ã¢ãã¡ãŒã·ã§ã³ãšãã§ã¯ãã®ä¹±çšãåå ã§ãã¬ãŒã³ããŒã·ã§ã³ãèŠãŠãããšãã«äžå¿«æãçµéšããããšãããå Žåã¯ãéå°ãŸãã¯ä¹±çšãäœã§ããããææ¡ã§ããŸãã ãããžã§ã¯ãã§ã¯ãã»ã«ãæåã«è¡šç€ºããããšãïŒäžããäžãžã¹ã¯ããŒã«ãããšãïŒã«ã®ã¿ã¢ãã¡ãŒã·ã§ã³ã衚瀺ãããããã«ããŸãã äžã«ã¹ã¯ããŒã«ãããšãã»ã«ã¯ã¢ãã¡ãŒã·ã§ã³ãªãã«ãªããŸãã
以åã«è¡šç€ºãããã»ã«ã®ã¢ãã¡ãŒã·ã§ã³ã®ç¹°ãè¿ããé¿ããããã«ããã®ãããªæ¹æ³ãéçºããå¿ èŠããããŸãã ãããè¡ãã«ã¯ãããŒã«ããã¯ã€ãã¯æ€çŽ¢ãæäŸããSwift DictionaryïŒDictionaryïŒã衚瀺ãããŸãã
泚ïŒåœä»€ã®ã»ããã¯ãéè€ã®ãªãäžæã®ã¬ã³ãŒãã®é åºä»ããããŠããªãã³ã¬ã¯ã·ã§ã³ã§ãããé åã¯éè€ãèš±å¯ããé åºä»ããããã»ããã§ãã Swift LibraryïŒSwift Standard LibraryïŒã«ã¯äžé£ã®æ瀺ã¯å«ãŸããŠããŸããããDictionary of Boolsãç°¡åã«åçã§ããŸãã
ãããã£ãŠãèŸæžã®äœ¿çšã«å¯Ÿããããã«ãã£ã¯å°ãããããããããSwiftéçºããŒã ã¯ããããæåã®ãªãªãŒã¹ããåé€ããŸããã åœä»€ãŸãã¯èŸæžããŒã®ã»ããã®äžè¬çãªæ¬ ç¹ã¯ãäžè²«æ§ãä¿èšŒããªãããšã§ãããã»ã«ã®é åºä»ãã¯ããŒã¿ãžã§ãã¬ãŒã¿ãŒã«ãã£ãŠè¡ããããããããã¯åé¡ã§ã¯ãããŸããã
MainViewController.swiftãéãã次ã®ã¯ã©ã¹ããããã£ãè¿œå ããŸãã
var didAnimateCell:[NSIndexPath: Bool] = [:]
ããã§ã¯ãNSIndexPathãããŒãšããŠãBoolsãããããã£ãšããŠèªèãã空ã®èŸæžïŒèŸæžïŒãäœæããŸãã 次ã«ãtableViewã¡ãœããïŒtableViewïŒãwillDisplayCellïŒãforRowAtIndexPath :)ã次ã®ããã«çœ®ãæããŸãã
override func tableView(tableView: UITableView!, willDisplayCell cell: UITableViewCell!, forRowAtIndexPath indexPath: NSIndexPath!) { if didAnimateCell[indexPath] == nil || didAnimateCell[indexPath]! == false { didAnimateCell[indexPath] = true TipInCellAnimator.animate(cell) } }
ããŒãã«ãäžäžã«ã¹ã¯ããŒã«ããªããã»ã«ã衚瀺ãããã³ã«ã¢ãã¡ãŒã·ã§ã³åãã代ããã«ãã»ã«ã®indexPathãèŸæžã«ä¿åãããŠããããšã確èªããŠãã ããã ããã§ãªãå Žåã¯ãã»ã«ãåããŠè¡šç€ºããããããã¢ãã¡ãŒã·ã§ã³ãéå§ããindexPathãåœä»€ã»ããã«è¿œå ããå¿ èŠããããŸãã ãã§ã«ãããã«å«ãŸããŠããå Žåã¯ãäœãããªãã§ãã ããã
ãããžã§ã¯ããã³ã³ãã€ã«ããŠå®è¡ããŸãã Tableviewãäžäžã«ã¹ã¯ã€ããããšãç»é¢ã«æåã«è¡šç€ºããããšãã«ã¢ãã¡ãŒã·ã§ã³åãããã»ã«ã®ã¿ã衚瀺ãããŸãã
次ã«äœãããïŒ
ãã®ãã¥ãŒããªã¢ã«ã§ã¯ãæšæºã®èŠèŠåå¶åŸ¡æ¹æ³ã«ã¢ãã¡ãŒã·ã§ã³ãè¿œå ããŸããã ã¢ãã¡ãŒã·ã§ã³å®è£ ã®è©³çŽ°ã¯ãMainViewControllerã¯ã©ã¹ã§æå®ãããŠããŸããã ããã©ãããããããã¯è£å©ã¯ã©ã¹ã«ç§»ãããŸããã ç¹ã«ãã£ã¹ãã¬ã€ã³ã³ãããŒã©ãŒã®ã¢ã¯ãã£ããªç¶æ ã§ã¯ã©ã¹ã®è²¬ä»»ãç¶æããããšã¯ãIOSã®éçºã«ãããäž»èŠãªèª²é¡ã®1ã€ã§ãã å®æãããããžã§ã¯ããããŠã³ããŒãã§ããŸã
ã»ã«ã«ã¢ãã¡ãŒã·ã§ã³ãè¿œå ããåºæ¬ãåŠç¿ããã®ã§ãå€æã®å€ãå€æŽããŠãäœæã§ããä»ã®å¹æã確èªããŠãã ããã ããã€ãã®ã¢ã€ãã¢ïŒ
1.ã¢ãã¡ãŒã·ã§ã³ã®é«éåãŸãã¯äœéåã
2.ãã倧ããªåŸæè§ã
3.ç°ãªããªãã»ããïŒå転è§åºŠãå€æŽããå Žåãã»ãšãã©ã®å Žåãç»åããŸã£ããã«èŠããããã«ãªãã»ãããå€æŽããå¿ èŠããããŸãã ãªãã»ãããå®å šã«çç¥ãããã©ã¡ãŒã¿ãŒã®å€ïŒ0ã0ïŒã䜿çšãããšãã€ã¡ãŒãžã¯ã©ã®ããã«ãªããŸããïŒ
4.åµé æ§ãçºæ®ãããªãªãžãã«ã®ç»åãäœæããŸãã
5.äžçŽãŠãŒã¶ãŒåãïŒæ°Žå¹³è»žãŸãã¯åçŽè»žã§ããŒãã«ãå転ãããå¹æãåŸãããšãã§ããŸããïŒ å®å šãªã¯ãŒãã¿ãŒã®ããã«èŠããããšã¯ã§ããŸããïŒ
6.äžçŽãŠãŒã¶ãŒã®å ŽåïŒelseå¥ãtableViewïŒtableViewïŒãwillDisplayCellïŒãforRowAtIndexPath :)ã«è¿œå ããããŒã¿ã»ã«ã2åç®ã«è¡šç€ºããããšãã«ç°ãªãã¢ãã¡ãŒã·ã§ã³å¹æãååŸããŸãã
ããŒã¿ã»ã«ã«é©çšã§ããã¯ã¬ã€ãžãŒãªã²ããã
ãã®èšäºããã¢ãã¡ãŒã·ã§ã³ãäœæããããã®ç°¡åãªã¬ã€ããåŠç¿ãããšããŠãããã®æ å ±ã«åºã¥ããŠç¡éã®ããªãšãŒã·ã§ã³ãäœæã§ããŸãã ã¢ãã¡ãŒã·ã§ã³ã¯ããŠãŒã¶ãŒã®ã¢ã¯ã·ã§ã³ã«å€§ããè¿œå ã§ããŸããããšãã°ãã»ã«ãå圢ã«å転ãããããã§ãŒãã¢ãŠããããããã¬ãŒã³ããŒã·ã§ã³ã«è¡šç€ºããããã»ã«ãåé€ãããã§ããŸãã
ps翻蚳ã¯ãHabréã§æãæ£ç¢ºã§æé«ã®ç¿»èš³ã§ãããµããããŸãããã³ã¡ã³ããããã°ãå人ã§æžããŠãç·šéããŸãã ãç解ããã ãããããšãããããŸãã