【ios开发/Xcode】实现多功能备忘录

引言

一、项目来源及意义
随着当今时代科技不断的进步发展,现代快节奏的生活方式让人们每天都有很多行程安排,都是往往因为事务的堆积导致人们经常把要做的事务遗忘,或者想要及时记录的信息得不到记录。
在今天这个充斥着各种激烈竞争的重压时代,每个人都在忙碌的生活着。当今时代下对下一代人要培养很多特长的同时还要让他们完成学校布置的作业,而我们作为大学生学习任务同样很重,还面临这就业等问题,在我们这般的忙碌琐碎日常生活中,会有很多需要记忆的工作。但人的记忆是有限的,我们需要一个能提醒和安排我们工作的东西,如何井井有条的处理和安排任务,在有限的时间内完成最紧急最重要的事情,备忘录对我们而言尤为重要。
同时,在平常工作劳累之余的碎片化时间中,如何简单的放松自我也是及其重要的问题。因此我推出了一个简单易操作的多功能备忘录,在记录保存重要的信息的同时还附带计算与放松功能,极其好用。

二、项目开发平台及技术简要说明
系统:MAC OS 10.14
环境:XCode 10.2 Swift 4.3

三、项目需求分析及设计
该项目主要实现了一个多功能备忘录,包括随笔便签、计算器以及音乐播放器。在随笔便签中,每个人所保存的便签信息不同,所以根据账号可以实现显示不同的便签信息。而在需要添加便签时,可以写入新便签,并以标题的形式显示。在管理便签信息的时候可以进行删除或者调整次序等操作,当然数据要能够持久化保存。而计算器与音乐播放器则可以直接进行使用。
用户能够在注册页面注册新的账号,在使用账号登录成功后转入登录成功界面,管理和查看页面中可以查看当前存在的便签,以标题和时间的形式显示。接着能够进行信息编辑包括增加删除和修改次序等等。让你做到一件事都不漏,完全帮你管理起你的生活和工作。
在未登录时,用户可以使用计算器进行对一些事物以及数据的计算,较为方便。同时还能够听听音乐,放松放松。音乐还提供的多倍数与低倍数功能,能够尽情的根据自己的兴趣调节,非常人性化。
综上所述,根据这些功能该项目总共设计了7个主要页面:欢迎界面、登录页面、注册页面、管理和查看页面、编辑页面、音乐播放界面以及计算器界面。

四、项目实现
项目代码结构
在这里插入图片描述
项目故事版
在这里插入图片描述

具体功能及实现

注:@开头的这些代码都是需要关联控键,都需要自行在故事板中(Storyboards)进行关联
1、登录
输入系统中已经存储的或注册的账号密码可以进行登录
在这里插入图片描述

登录界面主要源代码

class LoginViewController : UIViewController{
    
    
   //键盘识别
    @IBAction func dismissKeyborad(_ sender: UITapGestureRecognizer) {
    
    
        userId.resignFirstResponder()
        password.resignFirstResponder()
    }
    //用户名
    @IBOutlet weak var userId: UITextField!
    //密码
    @IBOutlet weak var password: UITextField!
    override func viewDidLoad() {
    
    
        super.viewDidLoad()
    }
    var userpwd = [String:String]()
    //登录
    @IBAction func Login(_ sender: UIButton) {
    
    
        
        let user = userId.text!
        let pwd = password.text!
        userpwd = UserDefaults.standard.object(forKey: "userpwd")as?[String:String] ?? [String:String]()
        if userpwd[user] == pwd {
    
    
            self.performSegue(withIdentifier: "LoginSuccess", sender: nil)
        } else {
    
    
            let alertController = UIAlertController(title: "登录失败!",message: nil, preferredStyle: .alert)
            self.present(alertController, animated: true,completion: nil)
            DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 1) {
    
    self.presentedViewController?.dismiss(animated: false, completion: nil)}
        }
    }
}

2、注册
若无账号密码则需要注册,点击输入用户名与密码后点击注册即可完成注册,注册成功后弹窗显示“注册成功!”
在这里插入图片描述

注册界面主要源代码

class RegisterViewController : UIViewController{
    
    
 
    @IBOutlet weak var userId: UITextField!
    @IBOutlet weak var password: UITextField!

    @IBAction func dismissKeyBoard1(_ sender: UITapGestureRecognizer) {
    
    
        userId.resignFirstResponder()
        password.resignFirstResponder()
    }
    var userpwd = [String:String]()
    
    override func viewDidLoad() {
    
    
        super.viewDidLoad()
    }
    
    override func didReceiveMemoryWarning() {
    
    
        super.didReceiveMemoryWarning()
    }
    //返回
    @IBAction func backLo(_ sender: UIButton) {
    
    
                self.dismiss(animated: true, completion: nil)
    }
    //注册
    @IBAction func register(_ sender: Any) {
    
    
        let user = userId.text!
        let pwd = password.text!
        userpwd = UserDefaults.standard.object(forKey: "userpwd")as?[String:String] ?? [String:String]()
        userpwd[user] = pwd
        UserDefaults.standard.set(userpwd, forKey: "userpwd")
        UserDefaults.standard.synchronize()
        let ok = UIAlertAction(title:"确定", style:.default){
    
    
            action in self.dismiss(animated: true,completion: nil)
        }
        
        let alter = UIAlertController(title: "注册成功!",message: nil, preferredStyle: .alert)
        alter.addAction(ok)
        self.present(alter,animated:true,completion:nil)
    }
}

3、备忘录
此功能为备忘录的主页面,页面中有“返回”、“添加”与“编辑”按钮,点击对应按钮实现对应功能。
在这里插入图片描述

注册界面主要源代码

class EducationalSystemViewController : UITableViewController{
    
    
    var studentList: StudentList
    //增加
    @IBAction func addStudent(_ sender: UIButton) {
    
    
        let theStudent = studentList.addStudent()
        if let theIndex = studentList.students.index(of:theStudent){
    
    
            let theIndexPath = IndexPath(row: theIndex, section: 0)
            tableView.insertRows(at: [theIndexPath], with: .automatic)
        }
        studentList.saveStudents()
    }
    //返回
    @IBAction func back(_ sender: UIButton) {
    
    
        self.dismiss(animated: true, completion: nil)
    }
    //编辑
    @IBAction func shiftEditMode(_ sender: UIButton) {
    
    
        if isEditing{
    
    
            sender.setTitle("编辑", for: .normal)
            setEditing(false, animated: true)
        }else{
    
    
            sender.setTitle("确定", for: .normal)
            setEditing(true, animated: true)
        }
    }
    override func viewDidLoad() {
    
    
        studentList = StudentList()
        let statusBarHeight = UIApplication.shared.statusBarFrame.height
        let insets = UIEdgeInsets(top: statusBarHeight, left: 0, bottom: 0, right: 0)
        tableView.contentInset = insets
        tableView.scrollIndicatorInsets = insets
        let theRefreshControl = UIRefreshControl()
        theRefreshControl.attributedTitle = NSAttributedString(string: "refreshing")
        theRefreshControl.addTarget(self, action: #selector(refreshing), for: UIControl.Event.valueChanged)
        refreshControl = theRefreshControl
    }
    
    @objc func refreshing(){
    
    
        if(refreshControl?.isRefreshing == true){
    
    
            refreshControl?.attributedTitle = NSAttributedString(string: "loading...")
            refreshControl?.endRefreshing()
            refreshControl?.attributedTitle = NSAttributedString(string: "refreshing")
            tableView.reloadData()   
        }
    }
    required init?(coder aDecoder: NSCoder) {
    
    
        studentList = StudentList()
        super.init(coder: aDecoder)
    }
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    
    
        return studentList.students.count
    }
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    
    
        let cell = tableView.dequeueReusableCell(withIdentifier: "UITableViewCell", for: indexPath) as! StudentCell
        let student = studentList.students[indexPath.row]
        cell.nameLabel.text = student.name
        cell.scoreLabel.text = "\(student.score)"
        cell.idLabel.text = student.id
        return cell
    }
    override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
    
    
        if editingStyle == .delete{
    
    
            let theStudent = studentList.students[indexPath.row]
            studentList.deleteStudent(theStudent)
            tableView.deleteRows(at: [indexPath], with: .automatic)
        }
    }
    override func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
    
    
        studentList.transferPosition(sourceIndex: sourceIndexPath.row, destinationIndex: destinationIndexPath.row)
    }
}

4、备忘录增删改查、数据持久化等操作
点击“添加”,则会在备忘录的最后添加一条备忘录信息,点击“编辑”进入编辑界面,可以移动和删除备忘录中的信息。
在这里插入图片描述

增删改查主要源代码

class StudentList{
    
    
    var students=[Student]()
    let archiveURL: URL = {
    
    
        let documents = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)

        let document = documents.first!
        return document.appendingPathComponent("studentistList1.plist")
    }()
    init(){
    
    
        
        let fileExist = FileManager.default.fileExists(atPath: archiveURL.path)
        if !fileExist {
    
    
            let bundlePath = Bundle(for: StudentList.self).resourcePath as NSString?
            let thePath = bundlePath!.appendingPathComponent("studentsCollection.plist")
            do{
    
    
                try FileManager.default.copyItem(atPath: thePath, toPath: archiveURL.path)
            }catch{
    
    
                print("fail to copy plist file!")
            }
        }
        let theCollection = NSMutableArray(contentsOfFile: archiveURL.path)!
        for theElement in theCollection{
    
    
            let dict = theElement as! NSDictionary
            let name = dict["name"] as! String
            let score = dict["score"] as! String
            let id = dict["id"] as! String
            let theStudent = Student(name: name, score: score, id: id)
            students.append(theStudent)
        }
    }
    
    //增加
    func addStudent() -> Student {
    
    
        let theStudent = Student(name: "今天", score: "准备答辩!", id: "8:00")
        students.append(theStudent)
        saveStudents()
        return theStudent
    }
    //删除
    func deleteStudent(_ theStudent:Student) {
    
    
        if let theIndex = students.index(of: theStudent){
    
    
            students.remove(at: theIndex)
            saveStudents()
        }
    }
    //修改
    func transferPosition(sourceIndex: Int, destinationIndex: Int) {
    
    
        if sourceIndex != destinationIndex {
    
    
            let theStudent = students[sourceIndex]
            students.remove(at: sourceIndex)
            students.insert(theStudent, at: destinationIndex)
        }
        return 
    }
    //保存
    func saveStudents() -> Bool{
    
    
        let studentsArray = NSMutableArray()
        for theStudent in students{
    
    
            let studentDictionary : NSDictionary
            studentDictionary = ["name":theStudent.name,"id":theStudent.id,"score":"\(theStudent.score)"]
            studentsArray.add(studentDictionary)
        }
        studentsArray.write(toFile: archiveURL.path,atomically: true)
        print(archiveURL)
        return true
    }
}

下图所示为备忘录初始储存的备忘信息

在这里插入图片描述
5、音乐播放器
在“放松一下”功能中可以播放一段优美的音乐,同时能够根据自己的心情调节音乐的快慢,点击对应的按钮即可实现。
在这里插入图片描述

音乐播放器界面源代码

class bgmController: UIViewController {
    
    
    //图片展示
    @IBOutlet weak var imageView: UIImageView!
    override func viewDidLoad() {
    
    
        super.viewDidLoad()
        //获取图片路径
        guard let path = Bundle.main.path(forResource: "p1.gif", ofType: nil),
            let data = NSData(contentsOfFile: path),
            let imageSource = CGImageSourceCreateWithData(data, nil) else {
    
     return }
        
        var images = [UIImage]()
        var totalDuration : TimeInterval = 0
        for i in 0..<CGImageSourceGetCount(imageSource) {
    
    
            guard let cgImage = CGImageSourceCreateImageAtIndex(imageSource, i, nil) else {
    
     continue }
            let image = UIImage(cgImage: cgImage)
            i == 0 ? imageView.image = image : ()
            images.append(image)
            guard let properties = CGImageSourceCopyPropertiesAtIndex(imageSource, i, nil) as? NSDictionary,
                let gifDict = properties[kCGImagePropertyGIFDictionary] as? NSDictionary,
                let frameDuration = gifDict[kCGImagePropertyGIFDelayTime] as? NSNumber else {
    
     continue }
            totalDuration += frameDuration.doubleValue
        }
        
        imageView.animationImages = images
        imageView.animationDuration = totalDuration
        imageView.animationRepeatCount = 0
        imageView.startAnimating()
    }

    lazy var player: AVAudioPlayer? = {
    
    
        let url = Bundle.main.url(forResource: "bgm.mp3", withExtension: nil)
        do {
    
    
            let player = try AVAudioPlayer(contentsOf: url!)
            player.delegate = self
            // 播放速率
            player.enableRate = true
            // 准备播放
            player.prepareToPlay()
            return player
        }catch {
    
    
            print(error)
            return nil
        }
    }()
    
    // 获取音乐
    func playBack() -> () {
    
    
        let audioSession: AVAudioSession = AVAudioSession.sharedInstance()
        do {
    
    
            if #available(iOS 10.0, *) {
    
    
                try audioSession.setCategory(.playback, mode: .default, options: .defaultToSpeaker)
            } else {
    
    
            }
            try audioSession.setActive(true)
        }catch {
    
    
            print(error)
        }
    }
    
    //开始
    @IBAction func play() {
    
    
        playBack()
        player?.play()
    }
    //暂停
    @IBAction func pauseM(_ sender: Any) {
    
    
        player?.pause()
    }
    //停止
    @IBAction func stopM(_ sender: UIButton) {
    
    
        player?.currentTime = 0
        player?.stop()
    }
    //快速
    @IBAction func kuaisu(_ sender: UIButton) {
    
    
        player?.rate = 3
    }
    //原速
    @IBAction func yuansu(_ sender: UIButton) {
    
    
        player?.rate = 1
    }
    
    //慢速
    @IBAction func mansu(_ sender: UIButton) {
    
    
        player?.rate = 0.5
    }
    //返回
    @IBAction func back(_ sender: UIButton) {
    
    
                self.dismiss(animated: true, completion: nil)
    }
}
extension bgmController: AVAudioPlayerDelegate {
    
    
    func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
    
    
    }
}

6、计算器
计算器功能中实现了标准计算器的计算功能,包括加减乘除、三角函数、幂等等。
在这里插入图片描述

计算器界面源代码

class calculatorCTL: UIViewController {
    
    
    var Priority = ["+","-","*","÷","="]
    var isEq:Bool = false//判断是否输入等于号
    var isMinus:Bool = false//判断是否负数
    var isControl:Bool = false//判断是否输入操作符
    var input:Double = 0.0//存储输入数字
    var lastRes:Double = 0.0//存储上一个数字
    var res:Double = 0.0//存储答案
    var fh:Int = 0//符号标记
    var math:Int = 0//运算符标记
    
    //返回
    @IBAction func back(_ sender: UIButton) {
    
    
        self.dismiss(animated: true, completion: nil)
    }
    //结果显示
    @IBOutlet weak var resultsum: UILabel!
    override func viewDidLoad() {
    
    
        super.viewDidLoad()
    }
    //数字
    @IBAction func takesum(_ sender: UIButton) {
    
    
        if isMinus {
    
    
            resultsum.text = "0"
        }
        if isControl{
    
    
            resultsum.text = "0"
        }
        if(resultsum.text! != "0"){
    
    
            resultsum.text! += String(sender.tag)
        }else{
    
    
            resultsum.text! = String(sender.tag)
        }
        input = (resultsum.text! as NSString).doubleValue
        //获得数字并存储
        isEq = false
        isMinus = false
        isControl = false
    }
    //小数点
    @IBAction func touchPoint(_ sender: UIButton) {
    
    
        resultsum.text! += "."
    }
    //负号
    @IBAction func touchMinus(_ sender: UIButton) {
    
    
        if (res == 0){
    
    
            equal(sender)
            res = -input
        } else{
    
    
            res = -res
        }
        resultsum.text = String(res)
        isMinus = true
    }
    //等号
    @IBAction func equal(_ sender: UIButton) {
    
    
        switch(fh) {
    
    
        case 1:
            res = lastRes + input
        case 2:
            res = lastRes - input
        case 3:
            res = lastRes * input
        case 4:
            res = lastRes / input
        default:
            break
        }
        resultsum.text! = "\(res)"
        lastRes = res
        isEq = true
        isControl = true
    }
    //删除
    @IBAction func backC(_ sender: UIButton) {
    
    
        if resultsum.text?.count == 1 {
    
    
            resultsum.text = "0"
        }
        else if (resultsum.text! as NSString).doubleValue != 0 {
    
    
            resultsum.text?.removeLast()
        }
        input = (resultsum.text! as NSString).doubleValue
    }
    //加减乘除
    @IBAction func getsign(_ sender: UIButton){
    
    
        if sender.tag < 5 {
    
    
            resultsum.text! = Priority[sender.tag - 1]
            if isEq {
    
    
                lastRes = res
            }
            else {
    
    
                lastRes = input
            }
        }
        fh = sender.tag
        isControl = true
    }
    //清空
    @IBAction func touchClean(_ sender: UIButton) {
    
    
        res = 0
        lastRes = 0
        input = 0
        resultsum.text = "0"
        isControl = false
    }
    //其他运算
    @IBAction func touchMath(_ sender: UIButton) {
    
    
        math = sender.tag
        if(res == 0){
    
    
            res = input
        }
        switch(math){
    
    
        case 7:
            res = res * 3.14
        case 8:
            res = res * res
        case 9:
            res = sin(res)
        case 10:
            res = cos(res)
        default:
            break
        }
        resultsum.text! = "\(res)"
        lastRes = res
        isEq = true 
    }
}

所有源码下载

csdn下载点【这里
百度云下载点【这里】提取码 2333
条件允许的话用CSDN下载支持一下吧!

总结

本项目实现了一个简约易用的多功能备忘录,可以帮助你随时随地随心所欲的记录你的事物,让你不在忘记重要事项!同时,在记录的过程中肯定有一些需要计算的地方,因此我们还加入了计算器功能,让你可以直接进行计算,方便生活。不仅如此,若你的事物很多,那看着肯定心烦意乱,因此我设计了“轻松一下功能”,能够让你在烦躁的时候听听音乐轻松一下,若心情急躁还可以采用慢速播放,反之能够快速播放,非常人性化的让你记录生活中的点点滴滴。
在该项目中,通过实现简约实用的多功能备忘录,对更多的IOS开发知识有你了更加深入的理解。同时,在项目的进行过程中也出现的很多的挫折,例如一些按钮的关联出现了问题导致跳转错误、一些控件的某些参数改错了导致无法正确运行、数据持久化过程中无法正确存储等等。
但是通过不断的努力学习与互联网工具和老师同学的指导,逐步解决了这些问题,最终让项目完整的呈现出来。从中深刻的领会到了相互交流与向他人学习的重要性,今后会更加努力的学习更多知识。

猜你喜欢

转载自blog.csdn.net/qq_43605229/article/details/123455660