swift版本通讯录
注意点:控制器之间的跳转(navigation),数据本地存储,控制器之前传递数据
首先是数据模型,主要注意遵循了NSCoding协议和实现了协议的方法,这样对象才能存储
//
// Adress.swift
// AdressBook
//
// Created by admin on 16/1/21.
// Copyright © 2016年 jin. All rights reserved.
//
import UIKit
// 遵循了NSCoding协议
class Address: NSObject,NSCoding {
var name:NSString!
var address:NSString!
// 构造方法
init(name:NSString,address:NSString) {
self.name = name
self.address = address
}
// NSCoding协议构造方法
required init?(coder aDecoder: NSCoder) {
self.name = aDecoder.decodeObjectForKey("name") as! NSString
self.address = aDecoder.decodeObjectForKey("address") as! NSString
}
// NSCoding协议解码方法
func encodeWithCoder(aCoder: NSCoder) {
aCoder.encodeObject(self.name, forKey: "name")
aCoder.encodeObject(self.name, forKey: "address")
}
// 写文件类方法,其实开始我是打算用 NSMutableData的方法来存储的,用NSMutableData的话,在读取的时候会有点麻烦
class func writeAddresses(addresses:[Address])
{
NSKeyedArchiver.archiveRootObject(addresses, toFile: addressesPath)
}
// 对文件类方法
class func readeAddresses()->[Address]
{
let mutableData = NSKeyedUnarchiver.unarchiveObjectWithFile(addressesPath)
if mutableData == nil
{
return []
}
else
{
return mutableData as! [Address]
}
}
}
两个路径配置
import Foundation
// 用户信息存放路径
let userInfoPath = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true).last! + "/userInfo.plist"
let addressesPath = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true).last! + "/addresses.plist"
登录控制器
//
// LoginController.swift
// AddressBook
//
// Created by admin on 16/1/20.
// Copyright © 2016年 jin. All rights reserved.
//
import UIKit
class LoginController: UIViewController {
@IBOutlet weak var userName: UITextField!
@IBOutlet weak var password: UITextField!
@IBOutlet weak var loginButton: UIButton!
@IBOutlet weak var rememberPassword: UISwitch!
@IBOutlet weak var autoLogin: UISwitch!
override func viewDidLoad() {
super.viewDidLoad()
}
// 文本框改变的时候修改登录按钮的可见性
@IBAction func checkUserInfo() {
if(userName.text! == "" || password.text! == "")
{
loginButton.enabled = false
}
else
{
loginButton.enabled = true
}
}
// 登录
@IBAction func loginAction(sender: AnyObject) {
let progress = MBProgressHUD(view: self.view)
self.view.addSubview(progress)
progress.dimBackground = true
progress.labelText = "正在登录...."
progress.show(true)
self.view.endEditing(true)
//这里设置下延时执行,之前没用过的一种方式,这个参数有一些特别,而且没有提示。。。。记录下
let minseconds = 1 * Double(NSEC_PER_SEC)
let dtime = dispatch_time(DISPATCH_TIME_NOW, Int64(minseconds))
dispatch_after(dtime, dispatch_get_main_queue(), { () -> Void in
progress.hide(true)
if(self.userName.text! == "jin" && self.password.text! == "jin")
{
// 进入下个控制器,以segue的方式跳转
self.performSegueWithIdentifier("AddressBook", sender: nil)
let userDefault = NSUserDefaults.standardUserDefaults()
// 记录用户偏好
userDefault.setBool(self.rememberPassword.on, forKey: "rememberPassword")
userDefault.setBool(self.autoLogin.on, forKey: "autoLogin")
userDefault.synchronize()
// 如果选择了记住密码就记住密码
if self.rememberPassword.on
{
self.savePasssword()
}
}
else
{
let hud = MBProgressHUD.showHUDAddedTo(self.view, animated: true)
hud.mode = MBProgressHUDMode.Text
hud.labelText = "登录失败,请重试。。。"
hud.hide(true, afterDelay: 2)
}
})
}
// 保存密码到文件
func savePasssword()
{
// 这里保存的方式是直接使用的数据类型自带的写文件方法
let userInfo = NSMutableDictionary()
userInfo.setValue(self.userName.text, forKey: "userName")
userInfo.setValue(self.password.text, forKey: "password")
userInfo.writeToFile(userInfoPath, atomically: true)
}
// 自动登录时勾选记住密码
@IBAction func autolLoginAction(sender: AnyObject) {
self.rememberPassword.setOn(self.autoLogin.on ? self.autoLogin.on : self.rememberPassword.on, animated: true)
}
@IBAction func rememberChange(sender: AnyObject) {
self.autoLogin.setOn(self.rememberPassword.on ? self.autoLogin.on : self.rememberPassword.on, animated: true)
}
override func viewWillAppear(animated: Bool) {
// 从文件中读取保存的用户信息
let userInfo = NSDictionary(contentsOfFile: userInfoPath)
// 给控件赋值
self.userName.text = (userInfo?["userName"] != nil) ? (userInfo?["userName"] as! String) : ""
self.password.text = (userInfo?["password"] != nil) ? (userInfo?["password"] as! String) : ""
// 检查用户框的信息,用以开启登录按钮可用性
checkUserInfo()
// 获得用户偏好设置,
let userDefault = NSUserDefaults.standardUserDefaults()
// 设置偏好设置按钮的状态
self.rememberPassword.on = userDefault.boolForKey("rememberPassword")
self.autoLogin.on = userDefault.boolForKey("autoLogin")
// 检查状态,符合则自动登录
if self.autoLogin.on && loginButton.enabled
{
self.loginAction(self)
}
}
// 转向下个控制器的时候会调用这个方法,
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
super.prepareForSegue(segue, sender: sender)
// 源控制器
// print(segue.sourceViewController)
// 目标控制器
// print(segue.destinationViewController)
if(segue.destinationViewController is AddressBookController)
{
// 设置控制器的标题
segue.destinationViewController.title = self.userName.text
segue.destinationViewController.navigationItem.title = self.userName.text
}
}
}
联系人列表
//
// AddressBookController.swift
// AddressBook
//
// Created by admin on 16/1/20.
// Copyright © 2016年 jin. All rights reserved.
//
import UIKit
// 遵循了两个自定的代理协议
class AddressBookController: UITableViewController,AddAddressControllerDelegate,EditAddressControllerDelegate {
@IBOutlet weak var titleView: UINavigationItem!
// 联系人数据数组
var addreses:[Address]! = Address.readeAddresses()
{
didSet
{
Address.writeAddresses(addreses)
}
}
override func viewDidLoad() {
super.viewDidLoad()
}
// 登出
@IBAction func logout(sender: UIBarButtonItem) {
let userInfo = NSDictionary(contentsOfFile: userInfoPath)
// userInfo.setValue("", forKey: "userName")
userInfo!.setValue("", forKey: "password")
userInfo!.writeToFile(userInfoPath, atomically: true)
self.navigationController?.popToRootViewControllerAnimated(true)
}
// 删除按钮点击之后,改变编辑状态
@IBAction func deleteAddress(sender: UIBarButtonItem) {
self.tableView.editing = !self.tableView.editing
}
// 根据编辑状态做相应操作
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
switch editingStyle
{
case UITableViewCellEditingStyle.Delete :
self.addreses.removeAtIndex(indexPath.row)
self.tableView.deleteRowsAtIndexPaths([NSIndexPath(forRow: indexPath.row, inSection: 0)], withRowAnimation: UITableViewRowAnimation.Fade)
break
default :
break
}
}
// 跳转时判断,不同的控制器做不同的操作
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
super.prepareForSegue(segue, sender: nil)
if segue.destinationViewController is LoginController// 返回登录控制器直接返回
{
segue.destinationViewController.viewDidLoad()
}
else if segue.destinationViewController is AddAddressController// 添加控制器则设置代理
{
(segue.destinationViewController as! AddAddressController).addAddressDelegate = self
}
else if segue.destinationViewController is EditAddressController// 编辑控制器则设置代理以及传递当前选择的address模型
{
let dest = segue.destinationViewController as! EditAddressController
dest.address = self.addreses[(tableView.indexPathForSelectedRow?.row)!]
dest.editAddressDelegate = self
}
}
// 执行保存数据代理方法
func saveAddressButtonClicked(address: Address) {
self.addreses.append(address)
// 插入新行数据
self.tableView.insertRowsAtIndexPaths([NSIndexPath(forRow: self.addreses.count - 1, inSection: 0)], withRowAnimation: UITableViewRowAnimation.Fade)
}
// 编辑address代理方法,用以刷新数据之后改变cell为最新内容
func ediitAddressSaveButonClicked(address:Address) {
let index = self.addreses.indexOf(address)// 找到当前改变的addree的下标
self.addreses[index!] = address // 覆盖值
self.tableView.reloadRowsAtIndexPaths([NSIndexPath(forRow: index!, inSection: 0)], withRowAnimation: UITableViewRowAnimation.Fade) // 刷新cell
// print(index)
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.addreses.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let identifer = "addressCell"
// 从缓冲池中获取cell
var cell:UITableViewCell! = tableView.dequeueReusableCellWithIdentifier(identifer)
// 当没有获取到cell的时候,实例化新的cell
cell = (cell == nil) ? UITableViewCell(style: UITableViewCellStyle.Value1, reuseIdentifier: identifer) : cell
cell.textLabel?.text = self.addreses[indexPath.row].name as String
cell.detailTextLabel?.text = self.addreses[indexPath.row].address as String
return cell
}
// 点击cell执行方法
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.performSegueWithIdentifier("EditAddress", sender: nil)
}
// 设置cell编辑状态的style
override func tableView(tableView: UITableView, editingStyleForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCellEditingStyle {
return UITableViewCellEditingStyle.Delete
}
}
添加联系人
//
// AddAdressController.swift
// AdressBook
//
// Created by admin on 16/1/21.
// Copyright © 2016年 jin. All rights reserved.
//
import UIKit
class AddAddressController: UIViewController {
@IBOutlet weak var saveAddressButton: UIBarButtonItem!
@IBOutlet weak var name: UITextField!
@IBOutlet weak var address: UITextField!
weak var addAddressDelegate:AddAddressControllerDelegate!
// 检测信息是否出入完全
@IBAction func checkAddressInfo(sender: AnyObject) {
self.saveAddressButton.enabled = self.name.text != "" && self.address.text != ""
}
// 保存数据按钮
@IBAction func saveAddress(sender: AnyObject) {
let address = Address(name: self.name.text!, address: self.address.text!)
self.addAddressDelegate?.saveAddressButtonClicked?(address)
self.navigationController?.popViewControllerAnimated(true)
}
}
// 保存数据代理协议
@objc protocol AddAddressControllerDelegate
{
optional func saveAddressButtonClicked(address:Address)
}
编辑联系人
//
// EditAddressController.swift
// AdressBook
//
// Created by admin on 16/1/22.
// Copyright © 2016年 jin. All rights reserved.
//
import UIKit
class EditAddressController: UIViewController,UIAlertViewDelegate {
@IBOutlet weak var nameTextfield: UITextField!
@IBOutlet weak var addressTextfield: UITextField!
@IBOutlet weak var down: UIBarButtonItem!
weak var address:Address! // 当前修改的模型
weak var editAddressDelegate:EditAddressControllerDelegate!// 代理
override func viewDidLoad() {
self.nameTextfield.text = address.name as String
self.addressTextfield.text = address.address as String
}
// 保存修改之后的数据
@IBAction func saveAddress(sender: UIBarButtonItem) {
// 更改模型数据
self.address.name = self.nameTextfield.text! as String
self.address.address = self.addressTextfield.text! as String
// 执行代理方法
self.editAddressDelegate?.ediitAddressSaveButonClicked?(self.address)
// 返回控制器
self.navigationController?.popViewControllerAnimated(true)
}
// 判断用户修改改变确认按钮可用性
@IBAction func checkAddress(sender: UITextField) {
if nameTextfield.text != "" && addressTextfield.text != "" && nameTextfield.text != self.address.name && addressTextfield.text != self.address.address
{
down.enabled = true
}
else
{
down.enabled = false
}
}
// 退出按钮事件
@IBAction func cancel(sender: UIBarButtonItem) {
if self.down.enabled
{
// 使用 UIAlertView 会有警告,所以改用 UIAlertController 了
// let alert = UIAlertView(title: "确认放弃修改么?", message: "确认放弃修改么?", delegate: self, cancelButtonTitle: "继续修改", otherButtonTitles:"放弃修改")
// alert.delegate = self
// alert.show()
// 使用 UIAlertController
let alert = UIAlertController(title: "确认放弃修改么?", message: "确认放弃修改么?", preferredStyle: UIAlertControllerStyle.Alert)
// 添加按钮
alert.addAction(UIAlertAction(title: "放弃修改", style: UIAlertActionStyle.Destructive, handler: {
alert in
self.navigationController?.popViewControllerAnimated(true)
}))
// 添加按钮
alert.addAction(UIAlertAction(title: "继续修改", style: UIAlertActionStyle.Destructive, handler: nil))
// 显示
self.view.window?.rootViewController?.presentViewController(alert, animated: true, completion: nil)
}
else
{
self.navigationController?.popViewControllerAnimated(true)
}
}
// UIAlertView 代理方法
func alertView(alertView: UIAlertView, clickedButtonAtIndex buttonIndex: Int) {
if buttonIndex == 1
{
self.navigationController?.popViewControllerAnimated(true)
}
}
}
// 修改address代理协议
@objc protocol EditAddressControllerDelegate
{
optional func ediitAddressSaveButonClicked(address:Address)
}