[ios development/Xcode] Implement multi-functional memo

introduction

1. Project Source and Significance
With the continuous advancement and development of science and technology in today's era, the modern fast-paced lifestyle allows people to have many schedules every day. This is often due to the accumulation of things that people often forget about the things they need to do, or think about it. Information that needs to be recorded promptly is not recorded.
In today's stressful era full of fierce competition, everyone is living a busy life. In today's era, the next generation must cultivate many specialties and at the same time let them complete the homework assigned by the school. As college students, we also have a heavy learning task, and we also face employment and other issues. In our busy and trivial daily life, , there will be a lot of work that requires memorization. But human memory is limited. We need something that can remind and arrange our work, how to handle and arrange tasks in an orderly manner, and complete the most urgent and important things within a limited time. Memos are particularly important to us.
At the same time, how to simply relax yourself in the fragmented time after normal work is also an extremely important issue. Therefore, I launched a simple and easy-to-operate multi-functional memo, which not only records and saves important information, but also has calculation and relaxation functions, which is extremely easy to use.

2. Brief description of project development platform and technology
System: MAC OS 10.14
Environment: XCode 10.2 Swift 4.3

3. Project Requirements Analysis and Design
This project mainly implements a multi-functional memo, including notes, calculator and music player. In the casual notes, each person saves different note information, so different note information can be displayed according to the account. When you need to add a note, you can write a new note and display it as a title. When managing note information, you can delete or adjust the order. Of course, the data must be persisted. The calculator and music player can be used directly.
Users can register a new account on the registration page. After successfully logging in with the account, they will be redirected to the login success interface. The currently existing notes can be viewed on the management and viewing pages, displayed in the form of title and time. Then you can edit the information, including adding, deleting, modifying the order, etc. Let you do not miss a thing and completely help you manage your life and work.
When not logged in, users can use the calculator to calculate some things and data, which is more convenient. You can also listen to music and relax. Music also provides multi-magnification and low-magnification functions, which can be adjusted according to one's own interests, which is very user-friendly.
To sum up, based on these functions, the project has designed a total of 7 main pages: welcome interface, login page, registration page, management and viewing page, editing page, music playback interface and calculator interface.

4. Project Implementation
Project Code Structure
Insert image description here
Project Storyboard
Insert image description here

Specific functions and implementation

Note: These codes starting with @ all need to be associated with control keys, and they need to be associated in storyboards.
1. Log in. Enter
the account and password that have been stored or registered in the system to log in.
Insert image description here

Main source code of login interface

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. Registration
If you do not have an account and password, you need to register. Click to enter the user name and password and then click Register to complete the registration. After successful registration, a pop-up window will display "Registration Successful!"
Insert image description here

Main source code of registration interface

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. Memo
This function is the main page of the memo. There are "Return", "Add" and "Edit" buttons on the page. Click the corresponding button to realize the corresponding function.
Insert image description here

Main source code of registration interface

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. Operations such as addition, deletion, modification, and data persistence of
memos. Click "Add" to add a memo information at the end of the memo. Click "Edit" to enter the editing interface, where you can move and delete the information in the memo.
Insert image description here

Add, delete, modify and check the main source code

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

The figure below shows the memo information initially stored in the memo.

Insert image description here
5. Music player
In the "Relax" function, you can play a piece of beautiful music, and at the same time, you can adjust the speed of the music according to your mood, just click the corresponding button.
Insert image description here

Music player interface source code

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. Calculator
The calculator function implements the calculation functions of a standard calculator, including addition, subtraction, multiplication and division, trigonometric functions, powers, etc.
Insert image description here

Calculator interface source code

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

All source code downloads

csdn download point [ here ]
Baidu cloud download point [ here ] extraction code 2333,
if conditions permit, use CSDN download to support it!

Summarize

This project implements a simple and easy-to-use multi-functional memo, which can help you record your things anytime, anywhere, so that you will never forget important things! At the same time, there must be some calculations that need to be made during the recording process, so we have also added a calculator function so that you can perform calculations directly to make your life easier. Not only that, if you have a lot of things, you will definitely be upset. Therefore, I designed the "Relaxation Function" to allow you to listen to music and relax when you are irritable. If you are impatient, you can also play it at a slow speed. On the contrary, it can be played back quickly, which is very user-friendly and allows you to record every bit of your life.
In this project, by implementing a simple and practical multi-functional memo, you will have a deeper understanding of more IOS development knowledge. At the same time, there were many setbacks during the project, such as problems with the association of some buttons that led to jump errors, incorrect parameters of some controls that caused them to fail to run correctly, and data that could not be stored correctly during persistence. etc.
However, through continuous hard study, Internet tools and the guidance of teachers and classmates, these problems were gradually solved, and the project was finally presented in its entirety. From this I deeply understood the importance of mutual communication and learning from others, and I will work harder to learn more knowledge in the future.

Guess you like

Origin blog.csdn.net/qq_43605229/article/details/123455660