Swift學(xué)習(xí)記錄 Day 4

100 Days of Swift中學(xué)習(xí),實(shí)踐

目前正在學(xué)習(xí)swift , 剛剛接觸了解了一部分語(yǔ)法后就因?yàn)樽约涸贠C上使用reactiveOBJC還算熟練,想直接學(xué)會(huì)rxswift和reactiveswift ,中間因?yàn)閤code有時(shí)候索引失效和一些其他原因,想過(guò)放棄學(xué)習(xí),無(wú)意中看到 關(guān)于iOS學(xué)習(xí)進(jìn)階的必讀一些博客總結(jié) 這個(gè)文章時(shí)看到了 100 Days of Swift, 感覺(jué)從一次次項(xiàng)目中,更加能夠堅(jiān)實(shí)我的基礎(chǔ), 所以決定從基礎(chǔ)開(kāi)始,跟著一步步往前走


Day 4

可以先來(lái)說(shuō)一下我的ViewController分層
代碼:

//MARK:-視圖加載

//MARK:-自定義方法

//MARK:-事件

//MARK:-代理方法

//MARK:-數(shù)據(jù)源


//MARK:-生命周期
override func viewDidLoad() {
    super.viewDidLoad()
    
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

//MARK:-懶加載

當(dāng)然在extension 里面實(shí)現(xiàn)delegate


PROJECT 7 - PASSING DATA TO ANOTHER VIEW
傳遞數(shù)據(jù)到另一個(gè)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
實(shí)現(xiàn)一個(gè)向下拖拽的方法,使鍵盤(pán)消失
代碼:

    @IBOutlet weak var MessageTextView: UITextView!

   fileprivate func initEvents(){
        let swipeDownGesture = UISwipeGestureRecognizer(target: self, action:#selector(downGesture(_:)))
        swipeDownGesture.direction = UISwipeGestureRecognizerDirection.down //不設(shè)置是右
        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

主要難點(diǎn)在于添加圖片到textview中
思路:
1.首先要能夠進(jìn)入相冊(cè)(我這里直接使用了相冊(cè), 并沒(méi)有使用camera)
2.選中圖片后獲取到圖片
3.富文本內(nèi)容, 用NSAttributeString承接
4.在接收到圖片以后需要進(jìn)行哪里處理?
先將已有內(nèi)容保存下來(lái),然后用NSAttachment接收到Image ,然后通過(guò)其內(nèi)的方法轉(zhuǎn)為NSAttributeString

需要注意的事項(xiàng)

  1. NSAttachment.bounds可以用來(lái)調(diào)整圖片大小和圖片位置
  2. 在添加完圖片以后需要調(diào)整光標(biāo)位置,并且將view移動(dòng)到光標(biāo)處,并且需要設(shè)置內(nèi)容的字體大?。ㄖ霸O(shè)置的是textFont, NSAttributedText的字體還未設(shè)置)

未解決的問(wèn)題

  • 在textview中 直接在NSAttributerString中追加"\n" 或者"\r\n" 無(wú)法換行,如果設(shè)置圖片的模式是適配textview的寬度,那么就會(huì)導(dǎo)致添加圖片后,光標(biāo)在圖片右邊,而換行后的位置。 目前我還沒(méi)有好的解決方案, 只能先做成在添加完圖片以后,textview失去第一響應(yīng),來(lái)讓用戶自己選擇光標(biāo)位置。如果有什么好的解決方案, 請(qǐng)聯(lián)系我?。?/li>

(學(xué)習(xí)過(guò)程用, 遇到不太會(huì)的知識(shí), 盡量去找文檔, 翻Dash,也許會(huì)比直接baidu現(xiàn)成的代碼更好)
代碼

import UIKit

enum ImageAttachmentMode {
    case Default  //默認(rèn)(不改變大?。?    case FitTextLine  //使尺寸適應(yīng)行高
    case FitTextView  //使尺寸適應(yīng)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 //不設(shè)置是右
        MessageTextView.addGestureRecognizer(swipeDownGesture)
    }
    
    fileprivate func insertPicture(_ image:UIImage,_ model:ImageAttachmentMode = .Default){
        //將現(xiàn)存所有文字轉(zhuǎn)為 NSMutableAttributedString
        let mutableString = NSMutableAttributedString.init()
        mutableString.append(MessageTextView.attributedText)
        //獲取光標(biāo)的位置
        let mutableSelectRange = MessageTextView.selectedRange
        
        //創(chuàng)建附件,來(lái)保存圖片
        let imgAttachment = NSTextAttachment.init()
        
        //用來(lái)保存附件 attachment轉(zhuǎn)化的attributeString
        var imageAttributeString:NSAttributedString
        
        //主要兩個(gè)屬性   一個(gè)image,圖片資源,   一個(gè)bounds 圖片位置
        imgAttachment.image = image
        
        //根據(jù)模式選擇圖片放置的模式
        switch model {
            //適應(yīng)文字大小
        case .FitTextLine:
            imgAttachment.bounds = CGRect.init(x: 0, y: -4, width: (MessageTextView.font?.lineHeight)!, height: (MessageTextView.font?.lineHeight)!)
            //適應(yīng)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))
        
        //記住新的光標(biāo)位置
        let newSelectRange = NSMakeRange(mutableSelectRange.location+1,0)
        
        //賦值到textview
        MessageTextView.attributedText = mutableString
        //刷新光標(biāo)
        MessageTextView.selectedRange = newSelectRange
        //滾動(dòng)到光標(biāo)位置
        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)
        
        //訪問(wèn)相冊(cè)頁(yè)面
        //從Dash文檔上根據(jù)文檔說(shuō)明,步驟進(jìn)行開(kāi)發(fā)
        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:-數(shù)據(jù)源
    
    
    //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

還在學(xué)習(xí)MJRefresh源碼中, 之后補(bǔ)上

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 (沒(méi)有使用segue)

除了project 10 其他內(nèi)容也相對(duì)簡(jiǎn)單,整合在一起記錄。

  • 使用ViewModel的Array 作為tableview的數(shù)據(jù)源
  • 查找tableview的delegate方法, 刪除,移動(dòng),根據(jù)操作修改ViewModel的Array數(shù)據(jù)
  • 從SecondViewController中點(diǎn)擊Done 添加此數(shù)據(jù)到ViewModel的Array中。并且通過(guò)閉包回調(diào)到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
//回調(diào)方法
        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:-數(shù)據(jù)源
    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以后,可以直接使用這個(gè)屬性 
    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
    }
    
}


在實(shí)際項(xiàng)目中實(shí)踐,在書(shū)寫(xiě)記錄中鞏固,每日一記。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • afinalAfinal是一個(gè)android的ioc,orm框架 https://github.com/yangf...
    passiontim閱讀 15,837評(píng)論 2 45
  • 最近在公司做了我們的pc端網(wǎng)站。需求:實(shí)現(xiàn)網(wǎng)頁(yè)的下拉加載頁(yè)面思路: 中包含list,這是一個(gè)list中包含的元素塊...
    薛云龍閱讀 8,689評(píng)論 4 4
  • 反思:每天給自己安排大量的輸入任務(wù),是想增加認(rèn)知,輸入的目的是想證明自己可以學(xué)到多少東西,覺(jué)得自己缺,所以才貪婪。...
    和時(shí)間做朋友閱讀 324評(píng)論 0 0

友情鏈接更多精彩內(nèi)容