美文网首页
Swift学习记录 Day 4

Swift学习记录 Day 4

作者: 那不是随你 | 来源:发表于2018-02-07 18:11 被阅读0次

    100 Days of Swift中学习,实践

    目前正在学习swift , 刚刚接触了解了一部分语法后就因为自己在OC上使用reactiveOBJC还算熟练,想直接学会rxswift和reactiveswift ,中间因为xcode有时候索引失效和一些其他原因,想过放弃学习,无意中看到 关于iOS学习进阶的必读一些博客总结 这个文章时看到了 100 Days of Swift, 感觉从一次次项目中,更加能够坚实我的基础, 所以决定从基础开始,跟着一步步往前走


    Day 4

    可以先来说一下我的ViewController分层
    代码:

    //MARK:-视图加载
    
    //MARK:-自定义方法
    
    //MARK:-事件
    
    //MARK:-代理方法
    
    //MARK:-数据源
    
    
    //MARK:-生命周期
    override func viewDidLoad() {
        super.viewDidLoad()
        
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    //MARK:-懒加载
    
    

    当然在extension 里面实现delegate


    PROJECT 7 - PASSING DATA TO ANOTHER VIEW
    传递数据到另一个view**

    代码:

    //FirstViewController
    let secondVC:SecondViewController = UIStoryboard.init(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "SecondViewController") as! SecondViewController
    secondVC.restoreText = self.message
    
    //SecondViewController
     var  restoreText:String?
    

    PROJECT 8 - SWIPE TO DISMISS KEYBOARD
    实现一个向下拖拽的方法,使键盘消失
    代码:

        @IBOutlet weak var MessageTextView: UITextView!
    
       fileprivate func initEvents(){
            let swipeDownGesture = UISwipeGestureRecognizer(target: self, action:#selector(downGesture(_:)))
            swipeDownGesture.direction = UISwipeGestureRecognizerDirection.down //不设置是右
            MessageTextView.addGestureRecognizer(swipeDownGesture)
       }
        @objc fileprivate func downGesture(_ gesture:UISwipeGestureRecognizer){
            MessageTextView.resignFirstResponder()
        }
    
    

    PROJECT 9 - ADD PHOTO FROM CAMERA ROLL

    • Access the Camera Roll from within the App
    • Create Image Picker Controller
    • Handle a selected image in the Camera Roll
    • Control how the image is displayed to prevent stretching

    主要难点在于添加图片到textview中
    思路:
    1.首先要能够进入相册(我这里直接使用了相册, 并没有使用camera)
    2.选中图片后获取到图片
    3.富文本内容, 用NSAttributeString承接
    4.在接收到图片以后需要进行哪里处理?
    先将已有内容保存下来,然后用NSAttachment接收到Image ,然后通过其内的方法转为NSAttributeString

    需要注意的事项

    1. NSAttachment.bounds可以用来调整图片大小和图片位置
    2. 在添加完图片以后需要调整光标位置,并且将view移动到光标处,并且需要设置内容的字体大小(之前设置的是textFont, NSAttributedText的字体还未设置)

    未解决的问题

    • 在textview中 直接在NSAttributerString中追加"\n" 或者"\r\n" 无法换行,如果设置图片的模式是适配textview的宽度,那么就会导致添加图片后,光标在图片右边,而换行后的位置。 目前我还没有好的解决方案, 只能先做成在添加完图片以后,textview失去第一响应,来让用户自己选择光标位置。如果有什么好的解决方案, 请联系我!!

    (学习过程用, 遇到不太会的知识, 尽量去找文档, 翻Dash,也许会比直接baidu现成的代码更好)
    代码

    import UIKit
    
    enum ImageAttachmentMode {
        case Default  //默认(不改变大小)
        case FitTextLine  //使尺寸适应行高
        case FitTextView  //使尺寸适应textView
    }
    
    class ViewController: UIViewController {
    
        @IBOutlet weak var MessageTextView: UITextView!
        
        var message:String?
        
        //MARK:-视图加载
        fileprivate func setupUI() {
    //        let rightItem = UIBarButtonItem.init(title: "Done", style: UIBarButtonItemStyle.done, target: self, action: #selector(rightBtnClick(_:)))
            let rightItem = UIBarButtonItem.init(barButtonSystemItem: UIBarButtonSystemItem.camera, target: self, action: #selector(rightBtnClick(_:)))
    //        rightItem.setBackgroundImage(UIImage(), for: UIControlState.normal, barMetrics: UIBarMetrics.default)
    //        rightItem.setBackgroundImage(UIImage(), for: UIControlState.highlighted, barMetrics: UIBarMetrics.default)
    //        rightItem.
            self.navigationItem.rightBarButtonItem = rightItem
            
        }
        //MARK:-自定义方法
        
        fileprivate func initEvents(){
            let swipeDownGesture = UISwipeGestureRecognizer(target: self, action:#selector(downGesture(_:)))
            swipeDownGesture.direction = UISwipeGestureRecognizerDirection.down //不设置是右
            MessageTextView.addGestureRecognizer(swipeDownGesture)
        }
        
        fileprivate func insertPicture(_ image:UIImage,_ model:ImageAttachmentMode = .Default){
            //将现存所有文字转为 NSMutableAttributedString
            let mutableString = NSMutableAttributedString.init()
            mutableString.append(MessageTextView.attributedText)
            //获取光标的位置
            let mutableSelectRange = MessageTextView.selectedRange
            
            //创建附件,来保存图片
            let imgAttachment = NSTextAttachment.init()
            
            //用来保存附件 attachment转化的attributeString
            var imageAttributeString:NSAttributedString
            
            //主要两个属性   一个image,图片资源,   一个bounds 图片位置
            imgAttachment.image = image
            
            //根据模式选择图片放置的模式
            switch model {
                //适应文字大小
            case .FitTextLine:
                imgAttachment.bounds = CGRect.init(x: 0, y: -4, width: (MessageTextView.font?.lineHeight)!, height: (MessageTextView.font?.lineHeight)!)
                //适应textview的宽度 撑满一行
            case .FitTextView:
                let imageWidth = MessageTextView.bounds.width-10
                let imageHeight = image.size.height/image.size.width*imageWidth
                imgAttachment.bounds = CGRect.init(x: 0, y: 0, width: imageWidth, height: imageHeight)
            
            default:
                break
            }
            
            imageAttributeString = NSAttributedString.init(attachment: imgAttachment)
            
            mutableString.append(imageAttributeString)
     
            mutableString.addAttribute(NSAttributedStringKey.font, value: UIFont.systemFont(ofSize: 17), range: NSMakeRange(0,mutableString.length))
            
            //记住新的光标位置
            let newSelectRange = NSMakeRange(mutableSelectRange.location+1,0)
            
            //赋值到textview
            MessageTextView.attributedText = mutableString
            //刷新光标
            MessageTextView.selectedRange = newSelectRange
            //滚动到光标位置
            MessageTextView.scrollRangeToVisible(newSelectRange)
            
        }
        
        
        //MARK:-事件
        @objc fileprivate func rightBtnClick(_ sender:UIBarButtonItem){
    
    //        let secondVC:SecondViewController = UIStoryboard.init(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "SecondViewController") as! SecondViewController
    //        secondVC.restoreText = self.message
    //        self.navigationController?.pushViewController(secondVC, animated: true)
            
            //访问相册页面
            //从Dash文档上根据文档说明,步骤进行开发
            if UIImagePickerController.isSourceTypeAvailable(UIImagePickerControllerSourceType.photoLibrary){
                UIImagePickerController.availableMediaTypes(for: UIImagePickerControllerSourceType.photoLibrary)
                
                let vc = UIImagePickerController.init()
    
                vc.delegate = self
                
                self.present(vc, animated: true, completion: {
                    
                })
                
            }
            else {
    
            }
      
        }
        
        @objc fileprivate func downGesture(_ gesture:UISwipeGestureRecognizer){
            MessageTextView.resignFirstResponder()
        }
        
        //MARK:-代理方法
        
        
        
        //MARK:-数据源
        
        
        //MARK:-生命周期
        override func viewDidLoad() {
            super.viewDidLoad()
            setupUI()
            initEvents()
        }
        
        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
            // Dispose of any resources that can be recreated.
        }
      
        //MARK:-懒加载
    }
    
    extension ViewController: UIImagePickerControllerDelegate,UINavigationControllerDelegate{
        func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
            
        }
        func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {
            let image = info[UIImagePickerControllerOriginalImage]
            self.insertPicture(image as! UIImage,.FitTextView)
            self.MessageTextView.resignFirstResponder()
            picker.dismiss(animated: true, completion: nil)
        }   
    }
    
    extension ViewController:UITextViewDelegate{
        func textViewDidEndEditing(_ textView: UITextView) {
            message = textView.text
            textView.resignFirstResponder()
        }
    
    }
    
    

    PROJECT 10 - PULL TO REFRESH TABLE VIEW (未完成自定义refresh功能)

    • Build a custom Table View Controller
    • Create custom Refresh Control
    • Stop refresh animation when data finishes updating
    • Update the table with refreshed local data

    还在学习MJRefresh源码中, 之后补上

    PROJECT 11 - DELETING AND REARRANGING

    • Remove data from Data Source
    • Delete data from Table Row
    • Animate the item deletion
    • Handle rearranging Table Rows
    • Enable swipe to delete Table Row

    PROJECT 12 - ADD NEW ITEM

    • Create a Model to interact with View Controllers
    • Add data to the Model
    • Update the Table View when the View loads
    • Dismiss the View from the Keyboard Done key
    • Segue to new Views from a Button (没有使用segue)

    除了project 10 其他内容也相对简单,整合在一起记录。

    • 使用ViewModel的Array 作为tableview的数据源
    • 查找tableview的delegate方法, 删除,移动,根据操作修改ViewModel的Array数据
    • 从SecondViewController中点击Done 添加此数据到ViewModel的Array中。并且通过闭包回调到FirstViewController,刷新tableview

    代码:
    FirstViewController

    import UIKit
    
    class ViewController: UITableViewController {
    
        //MARK:-视图加载
        
        //MARK:-自定义方法
        
        //MARK:-事件
        @objc func Edit(){
            self.tableView.isEditing = !self.tableView.isEditing
        }
        @objc func Add(){
            let vc:AddViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "AddViewController") as! AddViewController
            self.navigationController?.pushViewController(vc, animated: true)
            weak var weakself = self
    //回调方法
            vc.sendHandler { (str) in
                weakself?.viewmodel.Movies.append(str)
                weakself?.tableView.reloadData()
            }
            
            
        }
        
        //MARK:-代理方法
        override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    //        UIStoryboard mainStoryboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
    //        MainViewController *mainController = [mainStoryboard instantiateViewControllerWithIdentifier:@"MainViewController"];
            let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "TimeViewController")
            self.navigationController?.pushViewController(vc, animated: true)
            
        }
        
        override func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
            let tmp:String = viewmodel.Movies[sourceIndexPath.row]
            viewmodel.Movies.remove(at: sourceIndexPath.row)
            viewmodel.Movies.insert(tmp, at: destinationIndexPath.row)
            
        }
        
        override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
            print("\(#function)")
            if editingStyle == .delete {
                    viewmodel.Movies.remove(at: indexPath.row)
                    tableView.reloadData()
            }
            else if editingStyle == .insert
            {
                
                
            }
            
        }
        
    
        
        
        //MARK:-数据源
        override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return viewmodel.Movies.count
        }
        override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
            return 50
        }
        override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
            
            cell.textLabel?.text = viewmodel.Movies[indexPath.row]
            cell.accessoryType = UITableViewCellAccessoryType.disclosureIndicator
            cell.selectionStyle = .none
            
            return cell
        }
        
        override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
            return true
        }
        
        
        
        
        
        //MARK:-生命周期
        override func viewDidLoad() {
            super.viewDidLoad()
    //        self.tableView.delegate = self
    //        self.tableView.dataSource = self
            self.tableView.tableFooterView = UIView.init(frame: CGRect.zero)
            self.tableView.register(object_getClass(UITableViewCell()), forCellReuseIdentifier: "cell")
            
            
            let leftItem  = UIBarButtonItem.init(title: "Edit", style: UIBarButtonItemStyle.plain, target: self, action: #selector(Edit))
            self.navigationItem.leftBarButtonItem = leftItem
            
            let rightAddItem = UIBarButtonItem.init(barButtonSystemItem: UIBarButtonSystemItem.add, target: self, action: #selector(Add))
            self.navigationItem.rightBarButtonItem = rightAddItem
            
        }
        
        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
            // Dispose of any resources that can be recreated.
        }
        
        //MARK:-懒加载
        lazy var viewmodel: ViewModel = {
            let vm = ViewModel()
            return vm
        }()
    
    
    }
    
    

    SecondViewController

    import UIKit
    
    class AddViewController: UIViewController {
    //闭包定义
        typealias SendBlockHandler = (_ str:String)->Void
        var sendHandlerClosuer:SendBlockHandler?
    //必须要用方法承接闭包, 不能像OC一样定义完Block以后,可以直接使用这个属性 
        func sendHandler(closure:@escaping SendBlockHandler) -> Void {
            sendHandlerClosuer = closure
        }
        
        override func viewDidLoad() {
            super.viewDidLoad()
            AddTextView.becomeFirstResponder()
    
            // Do any additional setup after loading the view.
        }
    
        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
            // Dispose of any resources that can be recreated.
        }
        
        @IBOutlet weak var AddTextView: UITextView!
        @IBAction func SwipDownGesture(_ sender: Any) {
            AddTextView.resignFirstResponder()
        }
        
    
    }
    
    extension AddViewController:UITextViewDelegate{
    //控制Return
        func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
            if text == "\n" {
                
                textView.resignFirstResponder()
                self.navigationController?.popViewController(animated: true)
                sendHandlerClosuer!(textView.text)
                return false
            }
            
            
            return true
        }
        
    }
    
    

    在实际项目中实践,在书写记录中巩固,每日一记。

    相关文章

      网友评论

          本文标题:Swift学习记录 Day 4

          本文链接:https://www.haomeiwen.com/subject/wblazxtx.html