最近在看iOS核心動畫高級技巧,OC語言與Swift轉換有點使人頭疼,某些類和Api改動至關大。因此遇到我很困擾的語法我都會記錄一下,也方便往後回顧。git
首先是關於時間的類NSCalendargithub
這是iOS核心動畫高級技巧——3.圖層幾何學——3.2錨點裏的原文bash
- (void)tick
{
//convert time to hours, minutes and seconds
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSUInteger units = NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit;
NSDateComponents *components = [calendar components:units fromDate:[NSDate date]];
CGFloat hoursAngle = (components.hour / 12.0) * M_PI * 2.0;
//calculate hour hand angle //calculate minute hand angle
CGFloat minsAngle = (components.minute / 60.0) * M_PI * 2.0;
//calculate second hand angle
CGFloat secsAngle = (components.second / 60.0) * M_PI * 2.0;
//rotate hands
self.hourHand.transform = CGAffineTransformMakeRotation(hoursAngle);
self.minuteHand.transform = CGAffineTransformMakeRotation(minsAngle);
self.secondHand.transform = CGAffineTransformMakeRotation(secsAngle);
}
複製代碼
在我前先後後的各類查找語法糖的狀況下,摸索出三種寫法。ide
由於這句代碼NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit
中或的寫法,是在是不知道怎麼轉,因此就暫時沒管它佈局
@objc func tick(){
let calendar = NSCalendar.init(identifier: NSCalendar.Identifier.gregorian)
let hoursAngle = (getComponents(calendar!, unit: .hour) / 12.0) * CGFloat.pi * 2.0
let minsAngle = (getComponents(calendar!, unit: .minute) / 60.0) * CGFloat.pi * 2.0
let secsAngle = (getComponents(calendar!, unit: .second) / 60.0) * CGFloat.pi * 2.0
self.hourHand.transform = CGAffineTransform.init(rotationAngle: hoursAngle)
self.minuteHand.transform = CGAffineTransform.init(rotationAngle: minsAngle)
self.secondHand.transform = CGAffineTransform.init(rotationAngle: secsAngle)
}
func getComponents(_ cal:NSCalendar, unit:NSCalendar.Unit) -> CGFloat{
return CGFloat(cal.component(unit, from: Date()))
}
複製代碼
後來老是想着,OC能夠Swift確定也行的,而後發現是這樣寫的動畫
@objc func tick2(){
let calendar = NSCalendar.init(identifier: NSCalendar.Identifier.gregorian)
let units:NSCalendar.Unit = [.hour, .minute, .second]
let comp = calendar!.components(units, from: Date())
setDigit(digit: comp.hour! / 10, forView: self.digitViews[0])
setDigit(digit: comp.hour! % 10, forView: self.digitViews[1])
setDigit(digit: comp.minute! / 10, forView: self.digitViews[2])
setDigit(digit: comp.minute! % 10, forView: self.digitViews[3])
setDigit(digit: comp.second! / 10, forView: self.digitViews[4])
setDigit(digit: comp.second! % 10, forView: self.digitViews[5])
}
複製代碼
NS開頭的,Swift確定是會重寫成本身的類的,試試?ui
@objc func tick3(){
let calendar = Calendar.init(identifier: .gregorian)
let ccc:Set<Calendar.Component> = [Calendar.Component.hour, Calendar.Component.minute, Calendar.Component.second]
let comp = calendar.dateComponents(ccc, from: Date())
setDigit(digit: comp.hour! / 10, forView: self.digitViews[0])
setDigit(digit: comp.hour! % 10, forView: self.digitViews[1])
setDigit(digit: comp.minute! / 10, forView: self.digitViews[2])
setDigit(digit: comp.minute! % 10, forView: self.digitViews[3])
setDigit(digit: comp.second! / 10, forView: self.digitViews[4])
setDigit(digit: comp.second! % 10, forView: self.digitViews[5])
}
複製代碼
這些代碼只是語法的轉換,不是完整代碼。並且代碼量很小,我也不想上傳github,因此直接貼出來,可是沒包括Interface Builder中的佈局,因此我截了張XIB的圖出來。還有不要給約束。 spa
class ClockController: UIViewController {
@IBOutlet weak var hourHand: UIImageView!
@IBOutlet weak var minuteHand: UIImageView!
@IBOutlet weak var secondHand: UIImageView!
var timer:Timer!
var timer2:Timer!
@IBOutlet var digitViews:[UIView]!
override func viewDidLoad() {
super.viewDidLoad()
self.secondHand.layer.anchorPoint = CGPoint.init(x: 0.5, y: 0.9)
self.minuteHand.layer.anchorPoint = CGPoint.init(x: 0.5, y: 0.9)
self.hourHand.layer.anchorPoint = CGPoint.init(x: 0.5, y: 0.9)
timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(tick), userInfo: nil, repeats: true)
// Do any additional setup after loading the view.
tick()
setupTick2()
}
@objc func tick(){
let calendar = NSCalendar.init(identifier: NSCalendar.Identifier.gregorian)
let hoursAngle = (getComponents(calendar!, unit: .hour) / 12.0) * CGFloat.pi * 2.0
let minsAngle = (getComponents(calendar!, unit: .minute) / 60.0) * CGFloat.pi * 2.0
let secsAngle = (getComponents(calendar!, unit: .second) / 60.0) * CGFloat.pi * 2.0
self.hourHand.transform = CGAffineTransform.init(rotationAngle: hoursAngle)
self.minuteHand.transform = CGAffineTransform.init(rotationAngle: minsAngle)
self.secondHand.transform = CGAffineTransform.init(rotationAngle: secsAngle)
}
func getComponents(_ cal:NSCalendar, unit:NSCalendar.Unit) -> CGFloat{
return CGFloat(cal.component(unit, from: Date()))
}
func setupTick2(){
let digits = UIImage.init(named: "Digits")
for vi in self.digitViews {
vi.layer.contents = digits?.cgImage
vi.layer.contentsRect = CGRect.init(x: 0, y: 0, width: 0.1, height: 1.0)
vi.layer.contentsGravity = kCAGravityResizeAspect
vi.layer.magnificationFilter = kCAFilterNearest
}
timer2 = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(tick2), userInfo: nil, repeats: true)
self.tick2()
}
@objc func tick2(){
let calendar = NSCalendar.init(identifier: NSCalendar.Identifier.gregorian)
let units:NSCalendar.Unit = [.hour, .minute, .second]
let comp = calendar!.components(units, from: Date())
setDigit(digit: comp.hour! / 10, forView: self.digitViews[0])
setDigit(digit: comp.hour! % 10, forView: self.digitViews[1])
setDigit(digit: comp.minute! / 10, forView: self.digitViews[2])
setDigit(digit: comp.minute! % 10, forView: self.digitViews[3])
setDigit(digit: comp.second! / 10, forView: self.digitViews[4])
setDigit(digit: comp.second! % 10, forView: self.digitViews[5])
}
@objc func tick3(){
let calendar = Calendar.init(identifier: .gregorian)
let ccc:Set<Calendar.Component> = [Calendar.Component.hour, Calendar.Component.minute, Calendar.Component.second]
let comp = calendar.dateComponents(ccc, from: Date())
setDigit(digit: comp.hour! / 10, forView: self.digitViews[0])
setDigit(digit: comp.hour! % 10, forView: self.digitViews[1])
setDigit(digit: comp.minute! / 10, forView: self.digitViews[2])
setDigit(digit: comp.minute! % 10, forView: self.digitViews[3])
setDigit(digit: comp.second! / 10, forView: self.digitViews[4])
setDigit(digit: comp.second! % 10, forView: self.digitViews[5])
}
func setDigit(digit:Int, forView view:UIView){
let num = Double(digit)
view.layer.contentsRect = CGRect.init(x: num * 0.1, y: 0, width: 0.1, height: 1.0)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
複製代碼