Swift学习笔记七:实用进阶(一)
八、实用进阶
1.Swift语言中的两种单利模式
//单例模式可以保证一个类仅有一个实例。
import UIKit
//final修饰符:可以防止类被继承,还可以防止子类重写父类的属性、方法以及下标。该修饰符不能修饰结构体和枚举。
final class SingleClass: NSObject
{
//使用static修饰符,定义一个静态常量。静态常量在实例调用结束后不会消失,并且保留原值,即其内存不会被释放。当下次调用实例时,仍然使用常量原有的值。
static let shared = SingleClass()
//为了保持一个单例的唯一性,单例的构造器必须是private的。以防止其他对象也能创建出单例类的实例
private override init() {}
func say()
{
print("Hello, CoolKeTang!")
}
}
SingleClass.shared.say()
final class SecondSingletonClass: NSObject
{
//使用static修饰符,定义一个静态变量。
static var shared: SecondSingletonClass
{
//借助结构体来存储类型变量(class var),并使用let修饰符来保证线程的安全
struct Static
{
static let instance: SecondSingletonClass = SecondSingletonClass()
}
return Static.instance
}
//为了保持一个单例的唯一性,单例的构造器必须是私有的,以防止其它对象也能创建出单例类的实例
private override init() {}
func say()
{
print("Hello, CoolKeTang!")
}
}
SecondSingletonClass.shared.say()
2.Swift语言中的三种消息传递模式
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let width = Int(self.view.frame.size.width - 40)
let greetingButton = UIButton(frame: CGRect(x: 20, y: 100, width: width, height: 40))
greetingButton.setTitle("Greeting", for: .normal)
greetingButton.backgroundColor = .orange
//绑定按钮点击事件
greetingButton.addTarget(self, action: #selector(ViewController.buttonTapped), for: .touchUpInside)
//如果方法位于当前的类中,可以省略方法名称前方的类名
greetingButton.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)
greetingButton.tag = 1
//(_:)->小括号表示该方法拥有参数,下划线表示隐藏外部参数名
greetingButton.addTarget(self, action: #selector(buttonTappedFor(_:)), for: .touchUpInside)
//初始化一个选择器对象,并设置它的方法名称
let anotherMethod : Selector = #selector(buttonTappedFor(_:))
greetingButton.addTarget(self, action: anotherMethod, for: .touchUpInside)
//添加按钮
self.view.addSubview(greetingButton)
//创建选择器
let timerSelector = #selector(ViewController.timerAction(_:))
//创建定时器
Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: timerSelector, userInfo: "parameter", repeats: true)
let newSelector = #selector(calledByController)
//通过视图控制器对象的perform方法,在子线程中调用该选择器
self.perform(newSelector)
//延迟2秒
self.perform(newSelector, with: nil, afterDelay: 2.0)
//在主线程中调用选择器,并等待动作的执行。当对界面元素进行操作时,需要在主线程中进行
self.perform(newSelector, on: .main, with: nil, waitUntilDone: true)
//在后台线程中运行整个方法
self.performSelector(inBackground: newSelector, with: nil)
}
@objc func buttonTapped()
{
print("buttonTapped")
}
@objc func buttonTappedFor(_ sender: UIButton)
{
let tag = sender.tag
print("button tag: \(tag)")
}
@objc func timerAction(_ timer:Timer)
{
let parameter = timer.userInfo
print(parameter ?? "")
}
@objc func calledByController()
{
print("calledByController")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
3.闭包在定时任务、动画和线程中的使用
import UIKit
class ViewController: UIViewController {
//初始化一个视图
var animationVeiw : UIView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
//定时器执行闭包
Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { (timer:Timer) in
print("Timer action...")
}
animationVeiw = UIView(frame: CGRect(x: 0, y: 40, width: 50, height: 50))
animationVeiw.backgroundColor = .orange
self.view.addSubview(animationVeiw)
//动画
UIView.animate(withDuration: 1.0, animations: {
self.animationVeiw.frame = CGRect(x: 200, y: 40, width: 50, height: 50)
}) { (end:Bool) in
print("Animation done.")
}
//分离一个新的线程,并在新的线程中执行闭包语句中的任务
Thread.detachNewThread {
print("Do something on a new thread.")
}
//在调度队列中,异步执行闭包语句中的任务
DispatchQueue.main.async {
print("DispatchQueue.main.async")
}
//2秒后,异步执行闭包语句中的任务
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 2.0) {
print("DispatchQueue.main.asyncAfter")
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
4.通过protocol在两个对象中进行消息传递
CustomView.swift
import UIKit
//创建协议,校验输入框中的文本内容
protocol DemoDelegate
{
func checkForm()
}
//遵守UITextField协议
class CustomView: UIView, UITextFieldDelegate {
var textField : UITextField!
var delegate : DemoDelegate? //添加协议属性
override init(frame: CGRect) {
super.init(frame: frame)
textField = UITextField(frame:CGRect(x: 0, y: 0, width: self.frame.size.width, height: self.frame.size.height))
textField.font = UIFont.boldSystemFont(ofSize: 14)
textField.textColor = .purple
textField.layer.shadowColor = UIColor.black.cgColor
textField.layer.shadowOffset = CGSize(width: 0.0, height: 3.0)
textField.layer.shadowOpacity = 0.45
textField.layer.shadowRadius = 3
textField.backgroundColor = .lightGray
textField.delegate = self
self.addSubview(textField)
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
self.delegate?.checkForm()
return true
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
ViewController.swift
import UIKit
class ViewController: UIViewController, DemoDelegate {
var nameField : CustomView!
var passwordField : CustomView!
var submitButton : UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let width = Int(self.view.frame.size.width) - 40
let height = 40
nameField = CustomView(frame: CGRect(x: 20, y: 80, width: width, height: height))
nameField.delegate = self
self.view.addSubview(nameField)
passwordField = CustomView(frame: CGRect(x: 20, y: 140, width: width, height: height))
passwordField.delegate = self
self.view.addSubview(passwordField)
submitButton = UIButton(frame: CGRect(x: 20, y: 240, width: width, height: height))
submitButton.setTitle("Sumbit", for: .normal)
submitButton.addTarget(self, action: #selector(ViewController.submitForm(_:)), for: .touchUpInside)
submitButton.backgroundColor = .gray
submitButton.isEnabled = false
self.view.addSubview(submitButton)
}
func checkForm()
{
if self.nameField.textField.text != "" && self.passwordField.textField.text != ""
{
self.submitButton.isEnabled = true
submitButton.backgroundColor = .orange
}
else
{
self.submitButton.isEnabled = false
submitButton.backgroundColor = .gray
}
}
@objc func submitForm(_ sender:UIButton)
{
print("submitForm....")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
5.通过间接代理进行对象间的消息传递
CustomView.swift
import UIKit
class CustomView: UIView {
var textField : UITextField!
override init(frame: CGRect) {
super.init(frame: frame)
textField = UITextField(frame:CGRect(x: 0, y: 0, width: self.frame.size.width, height: self.frame.size.height))
textField.font = UIFont.boldSystemFont(ofSize: 14)
textField.textColor = .purple
textField.layer.shadowColor = UIColor.black.cgColor
textField.layer.shadowOffset = CGSize(width: 0.0, height: 3.0)
textField.layer.shadowOpacity = 0.45
textField.layer.shadowRadius = 3
textField.backgroundColor = .lightGray
self.addSubview(textField)
}
func setController(controller : ViewController)
{
self.textField.delegate = controller
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
ViewController.swift
import UIKit
class ViewController: UIViewController, UITextFieldDelegate {
var nameField : CustomView!
var passwordField : CustomView!
var submitButton : UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let width = Int(self.view.frame.size.width) - 40
let height = 40
nameField = CustomView(frame: CGRect(x: 20, y: 80, width: width, height: height))
nameField.setController(controller: self)
self.view.addSubview(nameField)
passwordField = CustomView(frame: CGRect(x: 20, y: 140, width: width, height: height))
passwordField.setController(controller: self)
self.view.addSubview(passwordField)
submitButton = UIButton(frame: CGRect(x: 20, y: 240, width: width, height: height))
submitButton.setTitle("Sumbit", for: .normal)
submitButton.addTarget(self, action: #selector(ViewController.submitForm(_:)), for: .touchUpInside)
submitButton.backgroundColor = .gray
submitButton.isEnabled = false
self.view.addSubview(submitButton)
}
@objc func submitForm(_ sender:UIButton)
{
print("submitForm....")
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool
{
if self.nameField.textField.text != "" && self.passwordField.textField.text != ""
{
self.submitButton.isEnabled = true
submitButton.backgroundColor = .orange
}
else
{
self.submitButton.isEnabled = false
submitButton.backgroundColor = .gray
}
return true
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
6.通过属性进行对象间的消息传递
CustomView.swift
import UIKit
class CustomView: UIView, UITextFieldDelegate {
var textField : UITextField!
weak var controller : ViewController?
override init(frame: CGRect) {
super.init(frame: frame)
textField = UITextField(frame:CGRect(x: 0, y: 0, width: self.frame.size.width, height: self.frame.size.height))
textField.font = UIFont.boldSystemFont(ofSize: 14)
textField.textColor = .purple
textField.layer.shadowColor = UIColor.black.cgColor
textField.layer.shadowOffset = CGSize(width: 0.0, height: 3.0)
textField.layer.shadowOpacity = 0.45
textField.layer.shadowRadius = 3
textField.backgroundColor = .lightGray
textField.delegate = self
self.addSubview(textField)
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
self.controller?.checkForm()
return true
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
ViewController.swift
import UIKit
class ViewController: UIViewController {
var nameField : CustomView!
var passwordField : CustomView!
var submitButton : UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let width = Int(self.view.frame.size.width) - 40
let height = 40
nameField = CustomView(frame: CGRect(x: 20, y: 80, width: width, height: height))
nameField.controller = self
self.view.addSubview(nameField)
passwordField = CustomView(frame: CGRect(x: 20, y: 140, width: width, height: height))
passwordField.controller = self
self.view.addSubview(passwordField)
submitButton = UIButton(frame: CGRect(x: 20, y: 240, width: width, height: height))
submitButton.setTitle("Sumbit", for: .normal)
submitButton.addTarget(self, action: #selector(ViewController.submitForm(_:)), for: .touchUpInside)
submitButton.backgroundColor = .gray
submitButton.isEnabled = false
self.view.addSubview(submitButton)
}
func checkForm()
{
if self.nameField.textField.text != "" && self.passwordField.textField.text != ""
{
self.submitButton.isEnabled = true
submitButton.backgroundColor = .orange
}
else
{
self.submitButton.isEnabled = false
submitButton.backgroundColor = .gray
}
}
func submitForm(_ sender:UIButton)
{
print("submitForm....")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
7.使用通知的方法进行对象间的数据传递
CustomView.swift
import UIKit
class CustomView: UIView, UITextFieldDelegate {
var textField : UITextField!
override init(frame: CGRect) {
super.init(frame: frame)
textField = UITextField(frame:CGRect(x: 0, y: 0, width: self.frame.size.width, height: self.frame.size.height))
textField.font = UIFont.boldSystemFont(ofSize: 14)
textField.textColor = .purple
textField.layer.shadowColor = UIColor.black.cgColor
textField.layer.shadowOffset = CGSize(width: 0.0, height: 3.0)
textField.layer.shadowOpacity = 0.45
textField.layer.shadowRadius = 3
textField.backgroundColor = .lightGray
textField.delegate = self
self.addSubview(textField)
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool
{
//发送通知
NotificationCenter.default.post(name: NSNotification.Name(rawValue: "checkFormNotification"),
object: nil,
userInfo: nil)
return true
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
/*
// Only override draw() if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
override func draw(_ rect: CGRect) {
// Drawing code
}
*/
}
ViewController.swift
//通知中心是一个调度消息通知的类,采用单例设计模式,实现数据传递、回调等功能。
import UIKit
class ViewController: UIViewController {
var nameField : CustomView!
var passwordField : CustomView!
var submitButton : UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let width = Int(self.view.frame.size.width) - 40
let height = 40
nameField = CustomView(frame: CGRect(x: 20, y: 80, width: width, height: height))
self.view.addSubview(nameField)
passwordField = CustomView(frame: CGRect(x: 20, y: 140, width: width, height: height))
self.view.addSubview(passwordField)
submitButton = UIButton(frame: CGRect(x: 20, y: 240, width: width, height: height))
submitButton.setTitle("Sumbit", for: .normal)
submitButton.addTarget(self, action: #selector(ViewController.submitForm(_:)), for: .touchUpInside)
submitButton.backgroundColor = .gray
submitButton.isEnabled = false
self.view.addSubview(submitButton)
//接收通知
NotificationCenter.default.addObserver(self,
selector: #selector(ViewController.checkForm(_:)),
name: NSNotification.Name(rawValue: "checkFormNotification"),
object: nil)
}
@objc func checkForm(_ notification: Notification?)
{
if self.nameField.textField.text != "" && self.passwordField.textField.text != ""
{
self.submitButton.isEnabled = true
submitButton.backgroundColor = .orange
}
else
{
self.submitButton.isEnabled = false
submitButton.backgroundColor = .gray
}
}
@objc func submitForm(_ sender:UIButton)
{
print("submitForm....")
}
deinit
{
//销毁通知(必写)
NotificationCenter.default.removeObserver(self)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
8.使用performSegue在故事板页面之间进行数据传递
DetailViewController.swift
import UIKit
class DetailViewController: UIViewController {
var parameter : String!
@IBOutlet var detailLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.detailLabel.text = self.parameter
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
ViewController.swift
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
@IBAction func showDetail(_ sender: Any) {
//点击按钮时,通过指定名称的连接线,在导航控制器中,跳转到第二个视图控制器
self.performSegue(withIdentifier: "showDetail", sender: nil)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//重写父类方法,用来监听故事版中的连接线的跳转动作
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let vc = segue.destination as! DetailViewController
vc.parameter = "Hello, CoolKeTang!"
}
}
9.Swift中的栈Stack和队列Queue详解
Swift语言并没有提供内设的栈和队列,很多扩展类库都是使用泛型来实现栈或队列。下面将采用数组来实现栈和队列等数据结构。
import UIKit
//栈:后进先出的线性结构
class Stack
{
var stack: [AnyObject]
//初始化
init()
{
stack = [AnyObject]()
}
//非空判断
func isEmpty() -> Bool
{
return stack.isEmpty
}
//大小
func size() -> Int
{
return stack.count
}
//进栈
func push(object: AnyObject)
{
stack.append(object)
}
//出栈
func pop() -> AnyObject?
{
if isEmpty()
{
return nil
}
else
{
return stack.removeLast() //最后一个数组元素
}
}
}
var stack = Stack()
stack.isEmpty()
stack.push(object: UIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0))
stack.push(object: UIColor(red: 1.0, green: 1.0, blue: 0.0, alpha: 1.0))
stack.pop()
//队列:先进先出的线性结构
class Queue
{
var queue: [AnyObject]
//初始化
init()
{
queue = [AnyObject]()
}
//非空判断
func isEmpty() -> Bool
{
return queue.isEmpty
}
//大小
func size() -> Int
{
return queue.count
}
//加入队列
func joinQueue(object: AnyObject)
{
queue.append(object)
}
//出队列
func deQueue() -> AnyObject?
{
if isEmpty()
{
return nil
}
else
{
return queue.removeFirst()//第一个元素
}
}
}
var queue = Queue()
queue.isEmpty()
queue.joinQueue(object: UIColor(red: 0.0, green: 0.0, blue: 1.0, alpha: 1.0))
queue.joinQueue(object: UIColor(red: 1.0, green: 1.0, blue: 0.0, alpha: 1.0))
queue.deQueue()
10.Swift中的链表LinkedList详解
链表是一种物理存储单元上的非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。
链表由一系列节点组成,每个节点包括两个部分,一个是存储数据元素的数据域,另一个是存储下个节点地址的指针域。
class LinkedListNode
{
var content: Int //链表的数据域
var nextNode: LinkedListNode? //链表的指针域
init(_ content: Int)
{
self.content = content
self.nextNode = nil
}
}
class LinkedList
{
var head: LinkedListNode? //头节点
var end: LinkedListNode? //尾节点
//添加到当前节点头部
func appendToHead(content: Int)
{
if head == nil
{
head = LinkedListNode(content)
end = head
}
else
{
let temporaryNode = LinkedListNode(content)
temporaryNode.nextNode = head
head = temporaryNode
}
}
//添加到当前节点尾部
func appendToEnd(content: Int)
{
if end == nil
{
end = LinkedListNode(content)
head = end
}
else
{
end?.nextNode = LinkedListNode(content)
end = end?.nextNode
}
}
}
上一篇: Swift 的函数派发理解
推荐阅读