Swift-----类型转换 、 嵌套类型 、 扩展 、 协议 、 访问控制
使用is和as操作符判断和转换数组中的对象类型 1.1 问题 类型转换可以判断实例的类型,也可以将实例看做是其父类或者子类的实例。在Swift中使用is和as操作符实现类型转换。 本案例定义一个媒体类MediaItem,它有两个子类Movie和Song,创建一个存放Movie实例和Song实例的媒体数组library,使用is和as操作符判断和转化library数组中的实例类型。 1.2 方案 使用类型检查操作符is来检查一个实例是否属于特定子类型,如果属于该子类型操作符返回true,否则返回false。 某类型的一个常量或变量可能实际上属于某一个子类,使用类型转换操作符as可以将其转换成子类型。转换过程可能会失败,因此类型转换操作符有两种不同的形式,可选形式as?和强制形式as。 1.3 步骤 实现此案例需要按照如下步骤进行。 步骤一:定义MediaItem类 首先定义一个MediaItem媒体类,包含一个String类型的name属性,和一个init构造方法,代码如下所示: //媒体类
class MediaItem {
var name : String
init(name:String){
self.name = name
}
}
然后定义MediaItem的两个子类,第一个子类Movie在父类的基础上增加一个director属性,和相应的构造方法。第二个子类Song,在父类的基础上增加了一个artist属性,和相应的构造方法,代码如下所示: //电影类
class Movie : MediaItem {
var director : String
init(name: String, director:String){
self.director = director
super.init(name: name)
}
}
//歌曲类
class Song: MediaItem {
var airtist : String
init(name: String, airtist: String) {
self.airtist = airtist
super.init(name: name)
}
}
最后一个创建一个数组常量library,包含两个Movie实例和三个Song实例,library的类型是在它被初始化时根据它数组中包含的内容推断来的,Swift的类型检测能够推断出Movie和Song有共同的父类MediaItem,所以推断出library的类型是MediaItem[],从library中取出的也是MediaItem类型,代码如下所示: //媒体数组
let library /*: [MediaItem]*/ = [
Movie(name: "星际穿越", director: "Daniel"),
Song(name: "小苹果", airtist: "筷子兄弟"),
Movie(name: "Breaking Bad", director: "Guodh"),
Song(name: "最炫民族风", airtist: "凤凰传奇"),
Song(name: "菊花台", airtist: "Jay")
]
步骤二:检测类型 定义两个变量movieCount和songCount,用来计算数组library中Movie和Song类型的实例数量。 遍历数组library中的每一个实例,使用is操作符判断类型,代码如下所示: //电影多少部?歌曲多少首
var movieCount =
var songCount =
//is用于判断引用指向的对象是否是指定类型
for item in library {
if item is Movie {
movieCount++
}else if item is Song {
songCount++
}
}
movieCount
songCount
运行结果如图-1所示: 图- 步骤三:转换类型 遍历library里的每一个MediaItem实例,并打印出适当的描述,item需要真正作为Movie或Song的类型来使用,这是需要使用as操作符进行类型转换,代码如下所示: //遍历每个媒体,并打印详细信息
for item in library {
if item is Movie {
//as用于强制装换,能转就转,不能转的话程序直接崩溃
let movie = item as! Movie
println("电影名:\(movie.name),导演:\(movie.director)")
}else if item is Song {
let song = item as! Song
println("歌曲名:\(song.name), 演唱者:\(song.airtist)")
}
}
但是数组中的每一个item可能是Movie或Song,所以这里使用可选类型的转换符更合适,代码如下所示: for item in library {
//as?与as功能相同,能转就转,不能转返回nil,程序不会崩溃,返回的是一个可选值
if let movie = item as? Movie {
println("电影名:\(movie.name),导演:\(movie.director)")
} else if let song = item as? Song {
println("歌曲名:\(song.name), 演唱者:\(song.airtist)")
}
}
1.4 完整代码 本案例中,完整代码如下所示: import UIKit
//媒体类
class MediaItem {
var name : String
init(name:String){
self.name = name
}
}
//电影类
class Movie : MediaItem {
var director : String
init(name: String, director:String){
self.director = director
super.init(name: name)
}
}
//歌曲类
class Song: MediaItem {
var airtist : String
init(name: String, airtist: String) {
self.airtist = airtist
super.init(name: name)
}
}
//媒体数组
let library /*: [MediaItem]*/ = [
Movie(name: "星际穿越", director: "Daniel"),
Song(name: "小苹果", airtist: "筷子兄弟"),
Movie(name: "Breaking Bad", director: "Guodh"),
Song(name: "最炫民族风", airtist: "凤凰传奇"),
Song(name: "菊花台", airtist: "Jay")
]
//电影多少部?歌曲多少首
var movieCount =
var songCount =
//is用于判断引用指向的对象是否是指定类型
for item in library {
if item is Movie {
movieCount++
}else if item is Song {
songCount++
}
}
movieCount
songCount
//遍历每个媒体,并打印详细信息
for item in library {
if item is Movie {
//as用于强制装换,能转就转,不能转的话程序直接崩溃
let movie = item as! Movie
println("电影名:\(movie.name),导演:\(movie.director)")
}else if item is Song {
let song = item as! Song
println("歌曲名:\(song.name), 演唱者:\(song.airtist)")
}
}
for item in library {
//as?与as功能相同,能转就转,不能转返回nil,程序不会崩溃,返回的是一个可选值
if let movie = item as? Movie {
println("电影名:\(movie.name),导演:\(movie.director)")
} else if let song = item as? Song {
println("歌曲名:\(song.name), 演唱者:\(song.airtist)")
}
} 扩展的使用 2.1 问题 扩展就是向一个已有的类、结构体或枚举添加新功能,和OC的分类类似。本案例演示Swift中扩展的用法,包括在扩展中添加计算属性、构造方法。实例方法和类型方法等。 2.2 方案 Swift中的扩展可以向已有的类型添加计算型实例属性和计算型类型属性,但是不可以添加存储属性,也不可以向已有属性添加属性观测器。 扩展还可以向已有的类型添加新的构造器,新构造器有责任保证构造过程能够让所有属性全都初始化。对于类而言扩展只能添加新的便利构造器,不能添加新的指定构造器和析构方法,指定构造器和析构方法必须总是由原始的类提供。 扩展可以向已有类型添加新的实例方法和类型方法。 2.3 步骤 实现此案例需要按照如下步骤进行。 步骤一:添加计算型属性 下面这个例子向已有的类型添加计算型属性,向Swift中的Double类型添加五个计算型实例属性,从而提供对距离单位的支持,这些属性都是可以通过点语法来访问。 这些属性表达的含义是把一个Double类型的值看做是某单位下的长度值,.0用来表示一米单位为m,其他单位则需要一些转换来表示在米下测量的值,km表示千米,ft表示英尺,cm表示厘米,mm表示毫米。 这些属性都是只读的计算属性,所以可以省略get关键字,返回类型都是Double类型,代码如下所示: extension Double {
var km:Double {
return self*
}
var m:Double {
return self
}
var cm:Double {
return self/
}
var mm:Double {
return self/
}
var ft:Double {
return self/3.28084
}
}
let oneIch = 25.4.mm
let threeFeet = .ft
运行结果如图-2所示: 图- 步骤二:添加构造方法 定义一个用于描述几何矩形的定制结构体Rect,这个例子同时定义了两个辅助结构体Size和Point,.0作为所有属性的默认值,代码如下所示: struct Point {
var x = 0.0
var y = 0.0
}
struct Size {
var width = 0.0
var height = 0.0
}
struct Rect {
var origin = Point()
var size = Size()
}
再使用扩展提供一个额外的构造器,可以使用中心点来进行构造,代码如下所示: extension Rect {
init(center:Point,size:Size) {
var originX = center.x - size.width/
var originY = center.y - size.height/
self.origin = Point(x: originX, y: originY)
self.size = size
}
}
var rect = Rect(center: Point(x: , y: ), size: Size(width: , height: ))
运行结果如图-3所示: 图- 步骤三:添加方法 向Int类型添加一个名为repetitions的新的实例方法,代码如下所示: extension Int {
func repetition(task:()->()) {
for i in ...self {
task()
}
}
}
var i =
i.repetition({println("hehe")})
运行结果如图-4所示: 图- 2.4 完整代码 本案例中,完整代码如下所示: import UIKit
//扩展计算属性
extension Double {
var km:Double {
return self*
}
var m:Double {
return self
}
var cm:Double {
return self/
}
var mm:Double {
return self/
}
var ft:Double {
return self/3.28084
}
}
let oneIch = 25.4.mm
let threeFeet = .ft
//扩展构造器
struct Point {
var x = 0.0
var y = 0.0
}
struct Size {
var width = 0.0
var height = 0.0
}
struct Rect {
var origin = Point()
var size = Size()
}
extension Rect {
init(center:Point,size:Size) {
var originX = center.x - size.width/
var originY = center.y - size.height/
self.origin = Point(x: originX, y: originY)
self.size = size
}
}
var rect = Rect(center: Point(x: , y: ), size: Size(width: , height: ))
//扩展方法
extension Int {
func repetition(task:()->()) {
for i in ...self {
task()
}
}
}
var i =
repetition({println("hehe")}) 计时器 3.1 问题 本案例学习使用Swift语言使用纯代码的方式实现第一个Swift项目——一个简单的计时器,如图-,图-6所示: 图- 图- 3.2 方案 首先使用Xcode创建一个SingleViewApplication项目,编程语言选择Swift,可以看到Xcode已经提供的项目代码全都换成Swift语言实现,如图-7所示: 图- 本案例采用纯代码的方式实现所以删除Storyboard,将程序的MainInterface清空,在程序的启动方法中,采用手写代码的方式创建的window,如图-8所示: 图- 接下来使用代码搭建计时器项目的界面,界面上方是一个现实倒计时的Label控件,下方是一排预设的时间按钮,最下方是启动和复位按钮。 扩展可以向已有类型添加新的实例方法和类型方法。 3.3 步骤 实现此案例需要按照如下步骤进行。 步骤一:创建window对象和根视图控制器 首先在AppDeleagte类中程序加载完成的方法中创建一个和屏幕大小一样的window对象,并将window的背景颜色设置为白色,代码如下所示: func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
//可选链,设置背景颜色
self.window?.backgroundColor = UIColor.whiteColor()
self.window?.makeKeyAndVisible()
return true
}
然后创建window的根视图控制器,根视图控制器是ViewController类型,Swift项目中不需要导入头文件就可以使用项目中定义好的ViewController类,代码如下所示: func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
//可选链,设置背景颜色
self.window?.backgroundColor = UIColor.whiteColor()
//创建根视图控制器
self.window?.rootViewController = ViewController()
self.window?.makeKeyAndVisible()
return true
}
由上面的代码可以看出OC语言提供的类和方法完全可以在Swift中使用,只是换成Swift的语法而已,IOS程序的运行原理和开发思想与之前所学完全一致。 步骤二:搭建界面 计时器的界面上方是一个现实倒计时的Label控件,下方是一排预设的时间按钮,最下方是启动和复位按钮,首先将这些控件全都设置为ViewController的存储属性,在viewDidLoad方法中进行初始状态的设置,布局代码写在viewDidLayoutSubviews方法中,代码如下所示: class ViewController: UIViewController {
var timeLabel:UILabel!
var timeButtons:[UIButton]!
var startButton:UIButton!
var resetButton:UIButton!
func setupTimeLabel(){
timeLabel = UILabel()
timeLabel.textColor = UIColor.whiteColor()
timeLabel.font = UIFont.boldSystemFontOfSize()
timeLabel.backgroundColor = UIColor.blackColor()
timeLabel.textAlignment = NSTextAlignment.Center
view.addSubview(timeLabel)
}
//预设时间按钮的信息
let timeButtonsInfo = [("1min",),("3min",),("5min",),("sec",)]
func setupTimeButtons(){
timeButtons = []
for (title,sec) in timeButtonsInfo {
let button = UIButton()
button.backgroundColor = UIColor.orangeColor()
button.setTitle(title, forState:UIControlState.Normal)
button.setTitleColor(UIColor.whiteColor(), forState: UIControlState.Normal)
button.setTitleColor(UIColor.blackColor(), forState: UIControlState.Highlighted)
//记录对应的时间给tag
button.tag = sec
view.addSubview(button)
timeButtons.append(button)
}
}
func timeButtonTapped (button:UIButton){
remainingSeconds = button.tag
}
//设置启动,复位按钮
func setupActionButtons() {
startButton = UIButton()
startButton.backgroundColor = UIColor.redColor()
startButton.setTitleColor(UIColor.whiteColor(), forState: .Normal)
startButton.setTitleColor(UIColor.blackColor(), forState: .Highlighted)
startButton.setTitle("Start", forState: .Normal)
view.addSubview(startButton)
resetButton = UIButton()
resetButton.backgroundColor = UIColor.redColor()
resetButton.setTitleColor(UIColor.whiteColor(), forState: .Normal)
resetButton.setTitleColor(UIColor.blackColor(), forState: .Highlighted)
resetButton.setTitle("Reset", forState: .Normal)
view.addSubview(resetButton)
}
override func viewDidLoad() {
super.viewDidLoad()
setupTimeLabel()
setupTimeButtons()
setupActionButtons()
}
//布局代码
override func viewDidLayoutSubviews() {
//时间窗口的布局
timeLabel.frame = CGRect(x: , y: , width: view.bounds.size.width-, height: )
//时间按钮的布局:按钮大小:64x44,按钮之间的间隔
let cnt = timeButtons.count -
let width = view.bounds.width - *2.0 - CGFloat(timeButtons.count) * 64.0
let gap = width / CGFloat(cnt)
for (index, button) in enumerate(timeButtons) {
let buttonLeft = 10.0 + CGFloat(index) * (64.0 + gap)
button.frame = CGRectMake(CGFloat(buttonLeft), view.bounds.height-120.0, , )
}
//启动复位按钮的布局
startButton.frame = CGRectMake(, view.bounds.height - , view.bounds.width - - , )
resetButton.frame = CGRectMake( + startButton.frame.width+, view.bounds.height - , , )
}
}
运行程序完成的界面如图-9所示: 图- 步骤三:实现计时功能 首先设置一个记录当前剩余秒数的属性remainingSeconds,该属性是一个整型的计算属性,当remainingSeconds的值发生改变就更新timeLabel的显示内容,因此给该属性添加一个属性监视器,通过newValue计算出timeLabel显示的内容,代码如下所示: //计算剩余时间
var remainingSeconds:Int = {
//属性监视器
willSet {
let min = newValue/
let sec = newValue%
timeLabel.text = String(NSString(format: "%02d:%02d", min,sec))
}
}
其次给预设时间按钮添加点击事件timeButtonTapped:,该方法将用户选择的时间秒数赋值给remainingSeconds,代码如下所示: //预设时间按钮的信息
let timeButtonsInfo = [("1min",),("3min",),("5min",),("sec",)]
func setupTimeButtons(){
timeButtons = []
for (title,sec) in timeButtonsInfo {
let button = UIButton()
button.backgroundColor = UIColor.orangeColor()
button.setTitle(title, forState:UIControlState.Normal)
button.setTitleColor(UIColor.whiteColor(), forState: UIControlState.Normal)
button.setTitleColor(UIColor.blackColor(), forState: UIControlState.Highlighted)
//记录对应的时间给tag
button.tag = sec
//给按钮添加点击事件
button.addTarget(self, action: Selector("timeButtonTapped:"), forControlEvents: UIControlEvents.TouchUpInside)
view.addSubview(button)
timeButtons.append(button)
}
}
func timeButtonTapped (button:UIButton){
remainingSeconds += button.tag
}
然后给启动和复位按钮添加点击事件startButtonTapped:和resetButtonTapped:,代码如下所示: //设置启动,复位按钮
func setupActionButtons() {
startButton = UIButton()
startButton.backgroundColor = UIColor.redColor()
startButton.setTitleColor(UIColor.whiteColor(), forState: .Normal)
startButton.setTitleColor(UIColor.blackColor(), forState: .Highlighted)
startButton.setTitle("Start", forState: .Normal)
view.addSubview(startButton)
//添加事件
startButton.addTarget(self, action: "startButtonTapped:", forControlEvents: .TouchUpInside)
resetButton = UIButton()
resetButton.backgroundColor = UIColor.redColor()
resetButton.setTitleColor(UIColor.whiteColor(), forState: .Normal)
resetButton.setTitleColor(UIColor.blackColor(), forState: .Highlighted)
resetButton.setTitle("Reset", forState: .Normal)
view.addSubview(resetButton)
resetButton.addTarget(self, action: "resetButtonTapped:", forControlEvents: .TouchUpInside)
}
接下来需要实现startButtonTapped:和resetButtonTapped:方法,当点击启动按钮时计时器开始计时,因此需要开启一个timer。 在实现startButtonTapped:和resetButtonTapped:方法之前需要在ViewController类中定义一个NSTimer类型的存储属性timer,以及一个用于记录当前计时状态的Bool类型的计算属性isCounting,并带有一个属性监视器。当isCounting属性值为true则表示当前处于计时状态,对timer进行初始化并开始计时,当isCounting属性值为false则表示当前停止计时,timer停止计时并清空,代码如下所示: //计时器计算属性
var timer:NSTimer?
var isCounting:Bool = false {
//添加属性监视器,当计时开始创建timer否则停止
willSet {
if newValue {
timer = NSTimer.scheduledTimerWithTimeInterval(, target: self, selector: Selector("updateTimer:"), userInfo: nil, repeats: true)
}else {
timer?.invalidate()
timer = nil
}
setSettingButtonsEnabled(!newValue)
}
}
//计时方法每一秒调用改变timeLable的显示,直到计时结束
func updateTimer(timer:NSTimer){
remainingSeconds--
if remainingSeconds<= {
isCounting = false
var alertVC = UIAlertController(title: "时间到", message: "", preferredStyle:.Alert)
let action = UIAlertAction(title: "确定", style: UIAlertActionStyle.Default, handler: { (action) -> Void in
println("被按了")
})
alertVC.addAction(action)
self.presentViewController(alertVC, animated: true, completion: nil)
}
}
//打开或关闭设置时间的按钮
func setSettingButtonsEnabled(enable:Bool) {
for button in timeButtons {
button.enabled = enable
button.alpha = enable ?1.0 : 0.3
}
resetButton.enabled = enable
resetButton.alpha = enable ?1.0 : 0.3
let title = enable ? "启动" : "停止"
startButton.setTitle(title, forState: .Normal)
}
此时再实现startButtonTapped:和resetButtonTapped:方法,代码如下所示: func startButtonTapped(button:UIButton){
isCounting = !isCounting
}
func resetButtonTapped(){
remainingSeconds =
}
步骤四:后台计时,推送消息 IOS8对程序的后台运行有很好的支持,当计时器退到后台,不用做任何操作就会自动后台计时,但是当计时完成用户并不知道计时已经完成,所以这个时候就需要使用IOS系统提供的本地消息推送功能,首先需要在程序加载成功的方法中请求用户同意接受消息推送,代码如下所示: func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
//可选链,设置背景颜色
self.window?.backgroundColor = UIColor.whiteColor()
self.window?.rootViewController = ViewController()
self.window?.makeKeyAndVisible()
//请求用户获取消息推送权限
let settings = UIUserNotificationSettings(forTypes: UIUserNotificationType.Alert | UIUserNotificationType.Sound | UIUserNotificationType.Badge,categories: nil)
application.registerUserNotificationSettings(settings)
return true
}
其次从计时开始就添加消息推送,当计时完成时推送消息,代码如下所示: func startButtonTapped(button:UIButton){
isCounting = !isCounting
if isCounting {
//添加消息推送
createAndFireLocalNotificationAfterSeconds(Double(remainingSeconds))
}else {
//计时结束退出消息推送
UIApplication.sharedApplication().cancelAllLocalNotifications()
}
}
//添加消息推送方法
func createAndFireLocalNotificationAfterSeconds(seconds:NSTimeInterval) {
UIApplication.sharedApplication().cancelAllLocalNotifications()
let notification = UILocalNotification()
//推送时间
notification.fireDate = NSDate(timeIntervalSinceNow: seconds)
//推送时区
notification.timeZone = NSTimeZone.systemTimeZone()
//推送通知的内容
notification.alertBody = "Time is up!"
UIApplication.sharedApplication().scheduleLocalNotification(notification)
}
运行程序消息推送效果如图-10所示: 图- 3.4 完整代码 本案例中,AppDelegate.swift文件中完整代码如下所示: import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
//可选链,设置背景颜色
self.window?.backgroundColor = UIColor.whiteColor()
self.window?.rootViewController = ViewController()
self.window?.makeKeyAndVisible()
//请求用户获取消息推送权限
let settings = UIUserNotificationSettings(forTypes: UIUserNotificationType.Alert | UIUserNotificationType.Sound | UIUserNotificationType.Badge,categories: nil)
application.registerUserNotificationSettings(settings)
return true
}
} 本案例中,ViewController.swift文件中完整代码如下所示: import UIKit
class ViewController: UIViewController {
var timeLabel:UILabel!
var timeButtons:[UIButton]!
var startButton:UIButton!
var resetButton:UIButton!
//计算剩余时间
var remainingSeconds:Int = {
//属性监视器
willSet {
let min = newValue/
let sec = newValue%
timeLabel.text = String(NSString(format: "%02d:%02d", min,sec))
}
}
//计时器计算属性
var timer:NSTimer?
var isCounting:Bool = false {
//添加属性监视器,当计时开始创建timer否则停止
willSet {
if newValue {
timer = NSTimer.scheduledTimerWithTimeInterval(, target: self, selector: Selector("updateTimer:"), userInfo: nil, repeats: true)
}else {
timer?.invalidate()
timer = nil
}
setSettingButtonsEnabled(!newValue)
}
}
//计时方法每一秒调用改变timeLable的显示,直到计时结束
func updateTimer(timer:NSTimer){
remainingSeconds--
if remainingSeconds<= {
isCounting = false
var alertVC = UIAlertController(title: "time is up", message: "", preferredStyle:.Alert)
let action = UIAlertAction(title: "Done", style: UIAlertActionStyle.Default, handler: { (action) -> Void in
println("被按了")
})
alertVC.addAction(action)
self.presentViewController(alertVC, animated: true, completion: nil)
}
}
//打开或关闭设置时间的按钮
func setSettingButtonsEnabled(enable:Bool) {
for button in timeButtons {
button.enabled = enable
button.alpha = enable ?1.0 : 0.3
}
resetButton.enabled = enable
resetButton.alpha = enable ?1.0 : 0.3
let title = enable ? "Start" : "Stop"
startButton.setTitle(title, forState: .Normal)
}
func setupTimeLabel(){
timeLabel = UILabel()
timeLabel.textColor = UIColor.whiteColor()
timeLabel.font = UIFont.boldSystemFontOfSize()
timeLabel.backgroundColor = UIColor.blackColor()
timeLabel.textAlignment = NSTextAlignment.Center
view.addSubview(timeLabel)
}
//预设时间按钮的信息
let timeButtonsInfo = [("1min",),("3min",),("5min",),("sec",)]
func setupTimeButtons(){
timeButtons = []
for (title,sec) in timeButtonsInfo {
let button = UIButton()
button.backgroundColor = UIColor.orangeColor()
button.setTitle(title, forState:UIControlState.Normal)
button.setTitleColor(UIColor.whiteColor(), forState: UIControlState.Normal)
button.setTitleColor(UIColor.blackColor(), forState: UIControlState.Highlighted)
//记录对应的时间给tag
button.tag = sec
//给按钮添加点击事件
button.addTarget(self, action: Selector("timeButtonTapped:"), forControlEvents: UIControlEvents.TouchUpInside)
view.addSubview(button)
timeButtons.append(button)
}
}
func timeButtonTapped (button:UIButton){
remainingSeconds += button.tag
}
//设置启动,复位按钮
func setupActionButtons() {
startButton = UIButton()
startButton.backgroundColor = UIColor.redColor()
startButton.setTitleColor(UIColor.whiteColor(), forState: .Normal)
startButton.setTitleColor(UIColor.blackColor(), forState: .Highlighted)
startButton.setTitle("Start", forState: .Normal)
view.addSubview(startButton)
//添加事件
startButton.addTarget(self, action: "startButtonTapped:", forControlEvents: .TouchUpInside)
resetButton = UIButton()
resetButton.backgroundColor = UIColor.redColor()
resetButton.setTitleColor(UIColor.whiteColor(), forState: .Normal)
resetButton.setTitleColor(UIColor.blackColor(), forState: .Highlighted)
resetButton.setTitle("Reset", forState: .Normal)
view.addSubview(resetButton)
resetButton.addTarget(self, action: "resetButtonTapped:", forControlEvents: .TouchUpInside)
}
func startButtonTapped(button:UIButton){
isCounting = !isCounting
if isCounting {
//添加消息推送
createAndFireLocalNotificationAfterSeconds(Double(remainingSeconds))
}else {
//计时结束退出消息推送
UIApplication.sharedApplication().cancelAllLocalNotifications()
}
}
func resetButtonTapped(button:UIButton){
remainingSeconds =
}
//添加消息推送方法
func createAndFireLocalNotificationAfterSeconds(seconds:NSTimeInterval) {
//取消之前所有的消息推送
UIApplication.sharedApplication().cancelAllLocalNotifications()
let notification = UILocalNotification()
//推送时间
notification.fireDate = NSDate(timeIntervalSinceNow: seconds)
//推送时区
notification.timeZone = NSTimeZone.systemTimeZone()
//推送通知的内容
notification.alertBody = "Time is up!"
UIApplication.sharedApplication().scheduleLocalNotification(notification)
}
override func viewDidLoad() {
super.viewDidLoad()
setupTimeLabel()
setupTimeButtons()
setupActionButtons()
}
//布局代码
override func viewDidLayoutSubviews() {
//时间窗口的布局
timeLabel.frame = CGRect(x: , y: , width: view.bounds.size.width-, height: )
//时间按钮的布局:按钮大小:64x44,按钮之间的间隔
let cnt = timeButtons.count -
let width = view.bounds.width - *2.0 - CGFloat(timeButtons.count) * 64.0
let gap = width / CGFloat(cnt)
for (index, button) in enumerate(timeButtons) {
let buttonLeft = 10.0 + CGFloat(index) * (64.0 + gap)
button.frame = CGRectMake(CGFloat(buttonLeft), view.bounds.height-120.0, , )
}
//启动复位按钮的布局
startButton.frame = CGRectMake(, view.bounds.height - , view.bounds.width - - , )
resetButton.frame = CGRectMake( + startButton.frame.width+, view.bounds.height - , , )
}
}
Swift-----类型转换 、 嵌套类型 、 扩展 、 协议 、 访问控制的更多相关文章
- Swift的可选链,类型转换和扩展
可选链(Optional Chaining) 可选链是一种请求或调用属性.方法,子脚本的过程. 可选性体现于请求或调用的目标当前可能为nil.若不为nil则成功调用.否则返回nil并将链失效. 调用可 ...
- swift学习笔记之-协议
//协议(Protocols) import UIKit /*协议(Protocols) 1.协议定义了一个蓝图,规定了用来实现某一特定任务或者功能的方法.属性,以及其他需要的东西 2.类.结构体或枚 ...
- swift 学习- 23 -- 扩展
// 扩展 就是为一个已有的 类, 结构体, 枚举, 或者 协议类型添加新功能, 这包括在没有权限获取 原始代码的情况下 扩展类型的能力 (即 逆向建模), 扩展和 OC 中的分类类似, (与 OC ...
- swift开发之--Protocol(协议)
使用object-c语言的同学们肯定对协议都不陌生,但在swift中苹果将protocol这种语法发扬的更加深入和彻底. Swift中的protocol不仅能定义方法还能定义属性,配合extensio ...
- Swift 学习笔记(面向协议编程)
在Swift中协议不仅可以定义方法和属性,而且协议是可以扩展的,最关键的是,在协议的扩展中可以添加一些方法的默认实现,就是在协议的方法中可以实现一些逻辑,由于这个特性,Swift是可以面向协议进行编程 ...
- Swift - 类型转换(as as! as?)
swift 类型转换 一,as 1,as使用场合 (1)从派生类转换为基类,向上转型(upcasts) class Animal {} class Cat: Animal {} let cat = C ...
- OAuth 2.0 扩展协议之 PKCE
前言 阅读本文前需要了解 OAuth 2.0 授权协议的相关内容, 可以参考我的上一篇文章 OAuth 2.0 的探险之旅. PKCE 全称是 Proof Key for Code Exchange, ...
- Swift中文教程(七)--协议,扩展和泛型
Protocols and Extensions 协议(接口)和扩展 Swift使用关键字protocol声明一个协议(接口): 类(classes),枚举(enumerations)和结构(stru ...
- Swift 4.0:访问级别(访问控制)
基础篇 注: 下文中所提及的类和类型为Class, Enum和Struct Swift中的访问级别有以下五种: open: 公开权限, 最高的权限, 可以被其他模块访问, 继承及复写. public: ...
- swift:类型转换(is用作判断检测、as用作类型向下转换)
类型转换是一种检查类实例的方式,并且哦或者也是让实例作为它的父类或者子类的一种方式. 类型转换在Swift中使用is 和 as操作符实现.这两个操作符提供了一种简单达意的方式去检查值的类型或者转换 ...
随机推荐
- 图片上传预览 (URL.createObjectURL)
知识预备:1. URL.createObjectURL() 静态方法会创建一个 DOMString,它的 URL 表示参数中的对象.这个 URL 的生命周期和创建它的窗口中的 document 绑定. ...
- AntiXSS v4.0中Sanitizer.GetSafeHtmlFragment等方法将部分汉字编码为乱码的解决方案
AntiXSS v4.0中Sanitizer.GetSafeHtmlFragment等方法将部分汉字编码为乱码的解决方案 以下代码为asp.net环境下,c#语言编写的解决方案.数据用Dictiona ...
- P53 T5
北京某高校可用的电话号码有以下几类:校内电话号码由4位数字,第1位数字不是0:校外电话又分为本市电话和外地电话两类,拔校外电话需先拔0,若是本市电话则再接着拔8位数字(第一位不是0),若是外地电话则拔 ...
- NSTimer “定时器”
•NSTimer叫做“定时器”,它的作用如下 Ø在指定的时间执行指定的任务 Ø每隔一段时间执行指定的任务 Ø •调用下面的方法就会开启一个定时任务 + (NSTimer *)scheduledTime ...
- socketserver 分块记录
网络编程 Socket(TCP,IP)套接字 服务端 运行起来, 客户端 客户端 客户端 客户端 服务端: import socket sk = socket.socket() #绑定端口号 sk.b ...
- Fair Scheduler中的Delay Schedule分析
延迟调度的主要目的是提高数据本地性(data locality),减少数据在网络中的传输.对于那些输入数据不在本地的MapTask,调度器将会延迟调度他们,而把slot分配给那些具备本地性的MapTa ...
- Python Day 01
What is variables? 一段命名的内存空间 变量即在程序运行过程中,它的值是允许改变的量 1.变量命名: 合法: 显式.通俗易懂. nums_of_jay_gf = 19 NumsOfJ ...
- Maven 导出依赖Jar,生成source.jar,javadoc.jar
下载最新版的Maven http://maven.apache.org/download.cgi 解压到本地文件夹 新建环境变量 MAVEN_HOME maven解压目录 在path加 ...
- 在VBA中新建工作簿
用程序计算数据,得到不同公司.不同项目的数据结果,最终还要将每个公司的数据结果放在各自的单独文件中.这就需要在vba中新建.保存excel文件.掌握几个东西就能很熟练了:1.要想保存在当前目录下,需要 ...
- <textarea>使用的时候发现的两个问题的总结
在练习表单的过程中,使用<textarea>时,遇到2个问题: 1.文本开始前有好多空格. 原来的代码是这样的: <textarea row="20" col=& ...