Swift學習記錄 Day 4

100 Days of Swift中學習疾层,實踐

目前正在學習swift , 剛剛接觸了解了一部分語法后就因為自己在OC上使用reactiveOBJC還算熟練,想直接學會rxswift和reactiveswift 矢渊,中間因為xcode有時候索引失效和一些其他原因,想過放棄學習枉证,無意中看到 關于iOS學習進階的必讀一些博客總結 這個文章時看到了 100 Days of Swift矮男, 感覺從一次次項目中,更加能夠堅實我的基礎室谚, 所以決定從基礎開始昂灵,跟著一步步往前走


Day 4

可以先來說一下我的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:-懶加載

當然在extension 里面實現(xiàn)delegate


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

    @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.富文本內(nèi)容眨补, 用NSAttributeString承接
4.在接收到圖片以后需要進行哪里處理?
先將已有內(nèi)容保存下來倒脓,然后用NSAttachment接收到Image 撑螺,然后通過其內(nèi)的方法轉(zhuǎn)為NSAttributeString

需要注意的事項

  1. NSAttachment.bounds可以用來調(diào)整圖片大小和圖片位置
  2. 在添加完圖片以后需要調(diào)整光標位置,并且將view移動到光標處崎弃,并且需要設置內(nèi)容的字體大懈饰睢(之前設置的是textFont, NSAttributedText的字體還未設置)

未解決的問題

  • 在textview中 直接在NSAttributerString中追加"\n" 或者"\r\n" 無法換行,如果設置圖片的模式是適配textview的寬度饲做,那么就會導致添加圖片后线婚,光標在圖片右邊,而換行后的位置盆均。 目前我還沒有好的解決方案塞弊, 只能先做成在添加完圖片以后,textview失去第一響應泪姨,來讓用戶自己選擇光標位置游沿。如果有什么好的解決方案, 請聯(lián)系我0估诀黍!

(學習過程用, 遇到不太會的知識仗处, 盡量去找文檔眯勾, 翻Dash枣宫,也許會比直接baidu現(xiàn)成的代碼更好)
代碼

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){
        //將現(xiàn)存所有文字轉(zhuǎn)為 NSMutableAttributedString
        let mutableString = NSMutableAttributedString.init()
        mutableString.append(MessageTextView.attributedText)
        //獲取光標的位置
        let mutableSelectRange = MessageTextView.selectedRange
        
        //創(chuàng)建附件吃环,來保存圖片
        let imgAttachment = NSTextAttachment.init()
        
        //用來保存附件 attachment轉(zhuǎn)化的attributeString
        var imageAttributeString:NSAttributedString
        
        //主要兩個屬性   一個image也颤,圖片資源,   一個bounds 圖片位置
        imgAttachment.image = image
        
        //根據(jù)模式選擇圖片放置的模式
        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文檔上根據(jù)文檔說明模叙,步驟進行開發(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

還在學習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 其他內(nèi)容也相對簡單,整合在一起記錄范咨。

  • 使用ViewModel的Array 作為tableview的數(shù)據(jù)源
  • 查找tableview的delegate方法故觅, 刪除,移動渠啊,根據(jù)操作修改ViewModel的Array數(shù)據(jù)
  • 從SecondViewController中點擊Done 添加此數(shù)據(jù)到ViewModel的Array中输吏。并且通過閉包回調(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以后贯溅,可以直接使用這個屬性 
    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
    }
    
}


在實際項目中實踐,在書寫記錄中鞏固躲查,每日一記它浅。

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市镣煮,隨后出現(xiàn)的幾起案子姐霍,更是在濱河造成了極大的恐慌,老刑警劉巖典唇,帶你破解...
    沈念sama閱讀 217,826評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件镊折,死亡現(xiàn)場離奇詭異,居然都是意外死亡介衔,警方通過查閱死者的電腦和手機恨胚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來炎咖,“玉大人赃泡,你說我怎么就攤上這事√磷埃” “怎么了急迂?”我有些...
    開封第一講書人閱讀 164,234評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長蹦肴。 經(jīng)常有香客問我,道長猴娩,這世上最難降的妖魔是什么阴幌? 我笑而不...
    開封第一講書人閱讀 58,562評論 1 293
  • 正文 為了忘掉前任勺阐,我火速辦了婚禮,結果婚禮上矛双,老公的妹妹穿的比我還像新娘渊抽。我一直安慰自己,他們只是感情好议忽,可當我...
    茶點故事閱讀 67,611評論 6 392
  • 文/花漫 我一把揭開白布懒闷。 她就那樣靜靜地躺著,像睡著了一般栈幸。 火紅的嫁衣襯著肌膚如雪愤估。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,482評論 1 302
  • 那天速址,我揣著相機與錄音玩焰,去河邊找鬼。 笑死芍锚,一個胖子當著我的面吹牛昔园,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播并炮,決...
    沈念sama閱讀 40,271評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼默刚,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了逃魄?” 一聲冷哼從身側(cè)響起荤西,我...
    開封第一講書人閱讀 39,166評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎嗅钻,沒想到半個月后皂冰,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,608評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡养篓,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,814評論 3 336
  • 正文 我和宋清朗相戀三年秃流,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片柳弄。...
    茶點故事閱讀 39,926評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡舶胀,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出碧注,到底是詐尸還是另有隱情嚣伐,我是刑警寧澤,帶...
    沈念sama閱讀 35,644評論 5 346
  • 正文 年R本政府宣布萍丐,位于F島的核電站轩端,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏逝变。R本人自食惡果不足惜基茵,卻給世界環(huán)境...
    茶點故事閱讀 41,249評論 3 329
  • 文/蒙蒙 一奋构、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧拱层,春花似錦弥臼、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至烙肺,卻和暖如春纳猪,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背茬高。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評論 1 269
  • 我被黑心中介騙來泰國打工兆旬, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人怎栽。 一個月前我還...
    沈念sama閱讀 48,063評論 3 370
  • 正文 我出身青樓丽猬,卻偏偏與公主長得像,于是被迫代替她去往敵國和親熏瞄。 傳聞我的和親對象是個殘疾皇子脚祟,可洞房花燭夜當晚...
    茶點故事閱讀 44,871評論 2 354

推薦閱讀更多精彩內(nèi)容

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