2016年1月

Quartz2d基本使用

基本使用,主要是画下线矩形,圆形之类的
//
//  RectangleView.swift
//  画图
//
//  Created by admin on 16/1/23.
//  Copyright © 2016年 jin. All rights reserved.
//

import UIKit

class RectangleView: UIView {
    override func drawRect(rect: CGRect) {
        self.drawRectImage()
    }
    // 图片
    func drawRectImage()
    {
        let image = UIImage(imageLiteral: "1")
        // 超过部分就没了
//        image.drawAtPoint(CGPoint.zero)
        // 图片会缩放
//        image.drawInRect(CGRectMake(0, 0, 100, 100))
        // 不够的部分会重复
        image.drawAsPatternInRect(CGRectMake(0, 0, self.frame.size.width, self.frame.size.height))
    }
    // 画文字,换文字的时候需要注意文字超过视图的边界的话就不回显示
    func drawRectText()
    {
        let str:NSString = "中蒙边境最低气温-35℃受西伯利亚冷空气的影响,地处新疆中蒙边境的新疆生产建设兵团第十师一八三团近期温度大幅下降8至10℃,最低气温降至-35℃。在当地的一户牧民家的羊圈中,笔者无意发现一只猫咪因为受不了寒冷的天气,依偎在两只小绵羊身上取暖,而且关系相处得特别融洽。"
        // 这个方式画的字不回换行,超过部分不回显示
//        str.drawAtPoint(CGPoint.zero, withAttributes: nil)
        // 这个方法会换行,但是超过设置的rect大小,超过的话也不回显示,可以通过计算字体的方式设置rect
//        str.drawInRect(CGRectMake(0, 0, self.frame.size.width, 50), withAttributes: nil)
        let attr:[String : AnyObject] = [NSFontAttributeName:UIFont.systemFontOfSize(15),NSForegroundColorAttributeName:UIColor.whiteColor()]
        let strSize = str.boundingRectWithSize(CGSizeMake(self.frame.size.width, CGFloat.max), options: NSStringDrawingOptions.UsesLineFragmentOrigin, attributes: attr, context: nil).size
        str.drawInRect(CGRectMake(0, 0, self.frame.size.width, strSize.height), withAttributes: attr)
    }
    // 画圆,注意画圆和画弧用的方法一致但是化弧需要用到额外的一个点和CGContextClosePath
    func drawRectSector()
    {
        let sector = UIGraphicsGetCurrentContext()
        let startPoint = CGPointMake(100,100)
        CGContextMoveToPoint(sector, startPoint.x, startPoint.y)
        CGContextAddArc(sector,startPoint.x, startPoint.y, 50, CGFloat(M_PI * 0.3), CGFloat(M_PI * 1.5), 0)
        CGContextClosePath(sector)
        CGContextStrokePath(sector)
    }
    // 弧度
    func drawRectArc()
    {
        let arc = UIGraphicsGetCurrentContext()
        // 参数含义分别为 圆心点,园半径,弧的开始角度,弧的结束角度,是否顺时针
        CGContextAddArc(arc, 100, 100, 50, 0, CGFloat(M_PI), 0)
//        CGContextStrokePath(arc)
        CGContextFillPath(arc)
    }
    // 花园
    func drawRectCircle()
    {
        let circle = UIGraphicsGetCurrentContext()
        CGContextAddEllipseInRect(circle, CGRectMake(100, 100, 50, 50))
        CGContextStrokePath(circle)
    }
    // 注意闭合路径(CGContextClosePath)的使用
    func drawRectTriangle()
    {
        let triangle = UIGraphicsGetCurrentContext()
        let startPoint = CGPoint(x: 10, y: 10)
        let triangleW:CGFloat = 100
        let triangleH:CGFloat = 100
        CGContextMoveToPoint(triangle, startPoint.x, startPoint.y)
        CGContextAddLineToPoint(triangle, startPoint.x + triangleW, startPoint.y)
        CGContextAddLineToPoint(triangle, 0, startPoint.x + triangleH)
        // 关闭路径
        CGContextClosePath(triangle)
//        CGContextFillPath(triangle)
        CGContextStrokePath(triangle)
    }
    // 注意使用CGContextStrokePath和CGContextFillPath渲染方式的不同
    func drawRectRectengle() {
        let rectangle = UIGraphicsGetCurrentContext()
        // 设置矩形的长宽和左上角坐标信息
        let rectangleW:CGFloat = 100
        let rectangleH:CGFloat = 200
        let startPointX:CGFloat = 10
        let startPointY:CGFloat = 10
        // *** 第一种方式:逐个点连接 ***
        // 设置起点
        //        CGContextMoveToPoint(rectangle, startPointX, startPointY)
        //        // 设置第二个点
        //        CGContextAddLineToPoint(rectangle, startPointX + rectangleW, startPointY)
        //        // 第三个点
        //        CGContextAddLineToPoint(rectangle, startPointX + rectangleW, startPointY + rectangleH)
        //        // 第四个点
        //        CGContextAddLineToPoint(rectangle, startPointX, startPointY + rectangleH)
        //        // 回到原点
        //        CGContextAddLineToPoint(rectangle, startPointX, startPointY)
        // *** 第二种方式:调用写好的函数 ***
        CGContextAddRect(rectangle, CGRectMake(startPointX, startPointY, rectangleW, rectangleH))
        // 不填充渲染
        //        CGContextStrokePath(rectangle)
        // 填充渲染
        CGContextFillPath(rectangle)
    }
    func drawRectLine()
    {
        // 获得实体上下文
        let line = UIGraphicsGetCurrentContext()

        // 设置线的颜色
        CGContextSetRGBStrokeColor(line, 1.0, 0.0, 0.0, 1)
        // 设置线的宽度
        CGContextSetLineWidth(line, 10)
        // 设置线的头的样式
        CGContextSetLineCap(line, CGLineCap.Round)
        // 设置线的连接点的样式
        CGContextSetLineJoin(line, CGLineJoin.Bevel)
        // 设置起点
        CGContextMoveToPoint(line, 30 , 30)
        // 设置第二个点
        CGContextAddLineToPoint(line, 100, 200)
        // 设置第三个点
        CGContextAddLineToPoint(line, 30, 300)
        // 渲染
        CGContextStrokePath(line)
    }
}

UITabBarController的使用

//
//  AppDelegate.swift
//  TabbarWithCode
//
//  Created by admin on 16/1/22.
//  Copyright © 2016年 jin. All rights reserved.
//

import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?


    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

        let window = UIWindow(frame:UIScreen.mainScreen().bounds)
        let tabbar = UITabBarController() // 初始化tabbar控制器
        window.rootViewController = tabbar // 设置window根控制器
        window.makeKeyAndVisible()
        self.window = window

        let c1 = UIViewController()
        c1.view.backgroundColor = UIColor.grayColor()
        c1.tabBarItem.title = "通讯录" // tabbarbutton的标题
        c1.tabBarItem.image = UIImage(imageLiteral: "tab_buddy_nor") // tabbarbutton的图片
        c1.tabBarItem.badgeValue = "10" // tabbarbutton显示的数字
//        tabbar.addChildViewController(c1) // 逐条添加
        let c2 = UIViewController()
        c2.view.backgroundColor = UIColor.blueColor()
        c2.tabBarItem.title = "设置"
        c2.tabBarItem.image = UIImage(imageLiteral: "tab_me_nor")
        c2.tabBarItem.badgeValue = "2"
//        tabbar.addChildViewController(c2)
        let c3 = UIViewController()
        c3.view.backgroundColor = UIColor.blackColor()
        c3.tabBarItem.title = "动态"
        c3.tabBarItem.image = UIImage(imageLiteral: "tab_qworld_nor")
        c3.tabBarItem.badgeValue = "8"
//        tabbar.addChildViewController(c3)
        let c4 = UIViewController()
        c4.view.backgroundColor = UIColor.whiteColor()
        c4.tabBarItem.title = "消息"
        c4.tabBarItem.image = UIImage(imageLiteral: "tab_recent_nor")
        c4.tabBarItem.badgeValue = "99"
//        tabbar.addChildViewController(c4)
        tabbar.viewControllers = [c1,c2,c3,c4]// 一次性添加
        return true
    }

    func applicationWillResignActive(application: UIApplication) {

    }

    func applicationDidEnterBackground(application: UIApplication) {
            }

    func applicationWillEnterForeground(application: UIApplication) {

    }

    func applicationDidBecomeActive(application: UIApplication) {

    }

    func applicationWillTerminate(application: UIApplication) {

    }
}

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)
}

swift数据持久化的方式

之前有一篇文章,是说沙盒文件读写的,但是不详细,这个详细的记录下
数据持久化的方式分为几种,

1.plist
//
//  ViewController.swift
//  持久化数据-ns
//
//  Created by admin on 16/1/19.
//  Copyright © 2016年 jin. All rights reserved.
//

import UIKit

class ViewController: UIViewController {
    let filePath = "\(NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true).last!)/data.plist"
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    // 保存数据方法
    @IBAction func saveData(sender: AnyObject) {
        // 字串保存,NSString类型和这个保存方式一致
        let string:String = "string"
        _ = try? string.writeToFile(filePath, atomically: true, encoding: NSUTF8StringEncoding)
        // 数组保存,NSArray类型才可以
        let array:NSArray = [1,2,3]
        array.writeToFile(filePath, atomically: true)
        // 字典保存,NSDictionary才可以
        let dictionary:NSDictionary = ["dic":"aaa"]
        dictionary.writeToFile(filePath, atomically: true)

    }
    // 读取数据方法
    @IBAction func readData(sender: AnyObject) {
        let string:String! = try? String(contentsOfFile: filePath)
        // 数组读取
        let array = NSArray(contentsOfFile: filePath)
        // 字典读取
        let dictionary = NSDictionary(contentsOfFile: filePath)
        print(dictionary)
    }



}
2.系统偏好设置
//
//  ViewController.swift
//  持久化数据-偏好设置
//
//  Created by admin on 16/1/19.
//  Copyright © 2016年 jin. All rights reserved.
//

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        self.saveData()
        self.readData()
    }
    func saveData()
    {
        // 获得 NSUserDefaults 对象
        let def = NSUserDefaults.standardUserDefaults()
        // 设置值,还可以设置其它值,就不一一尝试了
        def.setObject("test", forKey: "def")
        // 设置值之后,并不是立即保存到文件的,这里需要保存下
        def.synchronize()
    }
    func readData()
    {
        // 先获取对象
        let def = NSUserDefaults.standardUserDefaults()
        // 再获取值
        print(def.objectForKey("def"))
    }
}
3.NSCoding,自定以对象存储的时候注意实现协议的方法
//
//  ViewController.swift
//  数据持久化-NSCoding
//
//  Created by admin on 16/1/19.
//  Copyright © 2016年 jin. All rights reserved.
//

import UIKit

class ViewController: UIViewController {
    let filePath = "\(NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true).last!)/data.plist"
    override func viewDidLoad() {
        super.viewDidLoad()
        let arr:Array = [1,2,3]
        // 遵循了NSCoding协议并实现了 编码方法和构造方法才能使用
        // 写入,就不一一测试了
//        NSKeyedArchiver.archiveRootObject(arr, toFile: filePath)
        // 读取
//        print(NSKeyedUnarchiver.unarchiveObjectWithFile(filePath))
        // 自定义单个对象的读写
        let dog = Dog(name: "dog")
        // 写入
        NSKeyedArchiver.archiveRootObject(dog, toFile: filePath)
        // 读取
        let encodeDog = NSKeyedUnarchiver.unarchiveObjectWithFile(filePath) as! Dog
        print(encodeDog.name)

        // 存放多个对象到同一个文件中时使用 NSMutableData
        // 写入
        // 初始化多个对象
        let dogA = Dog(name: "dogA")
        let dogB = Dog(name: "dogB")
        // 初始化 Data 对象
        let dataEncoding = NSMutableData()
        // 初始化 archiver 对象
        let archiverEncoding = NSKeyedArchiver(forWritingWithMutableData: dataEncoding)
        // 编码对象
        archiverEncoding.encodeObject(dogA, forKey: "dogA")
        archiverEncoding.encodeObject(dogB, forKey: "dogB")
        // 结束编码
        archiverEncoding.finishEncoding()
        // 写入文件中
        dataEncoding.writeToFile(filePath, atomically: true)

        // 读取
        // 从文件中初始化Data对象
        let dataDecoding = NSMutableData(contentsOfFile: filePath)
        // 初始化解码对象
        let archiveDecoding = NSKeyedUnarchiver(forReadingWithData: dataDecoding!)
        // 根据键值还原对象
        let dogAencoding:Dog = archiveDecoding.decodeObjectForKey("dogA") as! Dog
        archiveDecoding.finishDecoding()
        print(dogAencoding.name)

    }
}
// 自定义对象,注意腰继承的对象和遵守的协议
class Dog:NSObject,NSCoding {
    var name:String
    // 自定义的构造方法
    @objc init(name:String)
    {
        self.name = name
    }
    // 协议的写入数据的方法
    @objc func encodeWithCoder(aCoder: NSCoder) {
        aCoder.encodeObject(self.name, forKey: "name")
    }
    // 协议的读取数据的方法
    @objc required init?(coder aDecoder: NSCoder) {
        self.name = aDecoder.decodeObjectForKey("name") as! String
//        return nil
    }
}

注册界面

注意点:移动uiview的,键盘事件监听和使用,自定义inputAccessoryView

xib部分代码
//
//  TextFiledKeyboardAccessory.swift
//  登陆排版界面
//
//  Created by zhang on 16/1/17.
//  Copyright © 2016年 jin. All rights reserved.
//

import UIKit
@objc protocol TextFiledKeyboardAccessoryDelagate
{
    optional func textFiledKeyboardAccessoryPreClicked(sender: UIBarButtonItem,other:UIBarButtonItem)
    optional func textFiledKeyboardAccessoryNextClicked(sender: UIBarButtonItem,other:UIBarButtonItem)
    optional func textFiledKeyboardAccessoryDownClicked()
}
class TextFiledKeyboardAccessory: UIToolbar {
    weak var accessorydDelegate:TextFiledKeyboardAccessoryDelagate!

    @IBOutlet weak var preButton: UIBarButtonItem!

    @IBOutlet weak var nextButton: UIBarButtonItem!
    class func instance()->TextFiledKeyboardAccessory
    {
        return NSBundle.mainBundle().loadNibNamed("TextFiledKeyboardAccessory", owner: nil, options: nil).last as! TextFiledKeyboardAccessory
    }
    @IBAction func preClicked(sender: UIBarButtonItem) {
        self.accessorydDelegate?.textFiledKeyboardAccessoryPreClicked?(sender,other: self.nextButton)
    }
    @IBAction func nexClicked(sender: UIBarButtonItem) {
        self.accessorydDelegate?.textFiledKeyboardAccessoryNextClicked?(sender,other: self.preButton)
    }
    @IBAction func downClicked() {
        self.accessorydDelegate?.textFiledKeyboardAccessoryDownClicked?()
    }

}
控制器代码
//
//  ViewController.swift
//  登陆排版界面
//
//  Created by zhang on 16/1/17.
//  Copyright © 2016年 jin. All rights reserved.
//

import UIKit

class ViewController: UIViewController,TextFiledKeyboardAccessoryDelagate,UITextFieldDelegate {

    // 存放登陆空间的view
    @IBOutlet weak var buttonView: UIView!
    // 懒加载所有的文本框
    lazy var textFields:[UITextField] =
    {
        let subViews:[UIView] = self.buttonView.subviews
        var textFields:[UITextField] = []
        subViews.forEach{
            if $0.tag == 3
            {
                textFields.append($0 as! UITextField)
            }
        }
        return textFields
    }()
    // 懒加载view
    lazy var textFiledKeyboardAccessory = TextFiledKeyboardAccessory.instance()
    // 当前活动获得焦点的 TextField 在对象数组中的下标
    var activeTextFieldIndex = 0
    override func viewDidLoad() {
        super.viewDidLoad()
        // 循环设置 TextField 的代理和键盘 accessory
        self.textFields.forEach{
            self.textFiledKeyboardAccessory.accessorydDelegate = self
            $0.inputAccessoryView = self.textFiledKeyboardAccessory
            $0.delegate = self
        }
//        NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardChange:", name: UIKeyboardWillChangeFrameNotification, object: nil)
        // 监听键盘时间
        NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardShow:", name: UIKeyboardWillShowNotification, object: nil)
        NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardHide:", name: UIKeyboardWillHideNotification, object: nil)
    }
    // 代理方法,收回键盘
    func textFiledKeyboardAccessoryDownClicked() {
        self.view.endEditing(true)
    }
    // 代理方法,下一个文本框
    func textFiledKeyboardAccessoryNextClicked(sender: UIBarButtonItem,other:UIBarButtonItem) {
        self.activeTextFieldIndex = self.activeTextFieldIndex + 1
        self.textFields[self.activeTextFieldIndex].becomeFirstResponder()
        if self.activeTextFieldIndex == self.textFields.count - 1
        {
            sender.enabled = false
        }
        other.enabled = self.activeTextFieldIndex != 0
    }
    // 上一个文本框
    func textFiledKeyboardAccessoryPreClicked(sender: UIBarButtonItem,other:UIBarButtonItem) {
        self.activeTextFieldIndex = self.activeTextFieldIndex - 1
        // 设置当前获得焦点的文本框
        self.textFields[self.activeTextFieldIndex].becomeFirstResponder()
        if self.activeTextFieldIndex == 0
        {
            sender.enabled = false
        }
        other.enabled = self.activeTextFieldIndex < self.textFields.count - 1
    }
    // 设置当前获得窗口的下标
    func textFieldDidBeginEditing(textField: UITextField) {
        self.activeTextFieldIndex = (self.textFields as NSArray).indexOfObject(textField)
    }
    // 键盘出现时响应的时间,用户改变view的位置
    func keyboardShow(notification:NSNotification)
    {
        // 获得改变位置之后的位置信息
        let endFrame:CGRect = ((notification.userInfo!)["UIKeyboardFrameEndUserInfoKey"]!).CGRectValue

        let activeMaxY = CGRectGetMaxY(self.textFields[self.activeTextFieldIndex].frame)
        let activeMinY = CGRectGetMinY(self.textFields[self.activeTextFieldIndex].frame)

        if activeMaxY > endFrame.origin.y
        {
            self.buttonView.transform = CGAffineTransformMakeTranslation(0, endFrame.origin.y - activeMaxY)
        }
        if -self.buttonView.transform.ty > activeMinY
        {
            self.buttonView.transform = CGAffineTransformMakeTranslation(0, 0 - activeMinY)
        }
//[UIKeyboardFrameBeginUserInfoKey: NSRect: {{0, 667}, {375, 302}}, UIKeyboardCenterEndUserInfoKey: NSPoint: {187.5, 516}, UIKeyboardBoundsUserInfoKey: NSRect: {{0, 0}, {375, 302}}, UIKeyboardFrameEndUserInfoKey: NSRect: {{0, 365}, {375, 302}}, UIKeyboardAnimationDurationUserInfoKey: 0.25, UIKeyboardCenterBeginUserInfoKey: NSPoint: {187.5, 818}, UIKeyboardAnimationCurveUserInfoKey: 7, UIKeyboardIsLocalUserInfoKey: 1]
    }
    // 键盘收回时候执行的方法
    func keyboardHide(notification:NSNotification)
    {
        self.buttonView.transform = CGAffineTransformMakeTranslation(0, 0)
    }
}