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í)候索引失效和一些其他原因,想過放棄學(xué)習(xí),無(wú)意中看到 關(guān)于iOS學(xué)習(xí)進(jìn)階的必讀一些博客總結(jié) 這個(gè)文章時(shí)看到了 100 Days of Swift, 感覺從一次次項(xiàng)目中,更加能夠堅(jiān)實(shí)我的基礎(chǔ), 所以決定從基礎(chǔ)開始,跟著一步步往前走


Day 4

可以先來(lái)說一下我的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è)向下拖拽的方法,使鍵盤消失
代碼:

    @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è), 并沒有使用camera)
2.選中圖片后獲取到圖片
3.富文本內(nèi)容, 用NSAttributeString承接
4.在接收到圖片以后需要進(jìn)行哪里處理?
先將已有內(nèi)容保存下來(lái),然后用NSAttachment接收到Image ,然后通過其內(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)容的字體大小(之前設(shè)置的是textFont, NSAttributedText的字體還未設(shè)置)

未解決的問題

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

(學(xué)習(xí)過程用, 遇到不太會(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)
        
        //訪問相冊(cè)頁(yè)面
        //從Dash文檔上根據(jù)文檔說明,步驟進(jìn)行開發(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 (沒有使用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中。并且通過閉包回調(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í)踐,在書寫記錄中鞏固,每日一記。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,818評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,185評(píng)論 3 414
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,656評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,647評(píng)論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,446評(píng)論 6 405
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,951評(píng)論 1 321
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,041評(píng)論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,189評(píng)論 0 287
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,718評(píng)論 1 333
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,602評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,800評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,316評(píng)論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,045評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,419評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,671評(píng)論 1 281
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,420評(píng)論 3 390
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,755評(píng)論 2 371

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

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