Kuidas luua ühiskasutatavat tekstiredaktorit Swifti abil?

Foto autor Rawpixel saidil Unsplash

Tekstiredaktorid on tänapäeval üha populaarsemad, olgu need siis manustatud veebisaidi kommentaaride vormi või kasutatavad märkmikuna. Valida on paljude erinevate toimetajate vahel. Selles postituses ei kavatse me mitte ainult õppida iOS-is ilusa tekstiredaktori mobiilirakenduse ehitamist, vaid ka seda, kuidas võimaldada Pusheri abil reaalajas märkmeteemalist koostööd teha.

Pange siiski tähele, et rakenduse lihtsuse huvides ei hõlma artikkel samaaegseid muudatusi. Seetõttu saab ainult üks inimene korraga redigeerida, teised vaatavad.

Rakendus töötab, kui mõni tekst sisestatakse, sündmuse käivitades. See sündmus saadetakse Pusherile, seejärel võtab selle vastu kaastöötaja seade ja seda värskendatakse automaatselt.

Selle õpetuse järgimiseks on vaja järgmist:

  1. Cocoapods: installige, käivitage gem install cocoapods oma arvutisse
  2. X-kood
  3. Pusher-rakendus: siin saate luua tasuta konto ja rakenduse
  4. Mõned Swifti keele teadmised
  5. Node.js

Lõpetuseks on selle õpetuse järgimiseks vaja põhiteadmisi Swifti ja Node.js kohta.

Alustage meie iOS-i rakendusega Xcodes

Käivitage Xcode ja looge uus projekt. Ma kutsun oma Collabo. Pärast seadistusviisardi jälgimist sulgege avatud tööalaga Xcode ja seejärel cd projekti juure ja käivitage käsk pod init. See peaks teile genereerima Podfile'i. Podfile'i sisu muutmine:

# Tühistage järgmine rida projekti globaalse platvormi määratlemiseks
    platvorm: ios, '9.0'
    sihtrühm 'textcollabo' tegema
      # Kommenteerige järgmist rida, kui te ei kasuta Swifti ega soovi dünaamilisi raamistikke kasutada
      use_frameworks!
      # Kaunad anonchat
      kamin 'Alamofire'
      kaust 'PusherSwift'
    lõpp

Nüüd käivitage käsu pod install, et Cocoapods paketihaldur saaks vajalikud sõltuvused sisse tõmmata. Kui see on valmis, sulgege Xcode (kui see on avatud) ja avage seejärel projekti kausta juuris asuv .xcworkspace-fail.

Vaadete kujundamine meie iOS-i rakendusele

Loome oma iOS-i rakendusele mõned vaated. Need on selgroog, kuhu me kogu loogika külge paneme. Kasutage Xcode'i storyboardi abil oma vaateid pisut nagu allolevad ekraanipildid.

See on LaunchScreen.storyboard fail. Olen lihtsalt kavandanud midagi lihtsat, millel pole üldse funktsioone.

Järgmine storyboard, mille kujundame, on Main.storyboard. Nagu nimest järeldada võib, on see peamine. Siin on meil kõik olulised vaated, mis on loogikaga seotud.

Siin on meil kolm vaadet.

Esimene vaade on loodud välja nägema täpselt nagu käivituskuva, välja arvatud nupp, mille oleme teise vaate avamiseks linginud.

Teine vaade on navigeerimiskontroller. See on ühendatud kolmanda vaatega, mis on ViewController. Oleme oma navigeerimiskontrollerile juurekontrolliks määranud kolmanda vaate.

Kolmandas vaates on redigeeritav UITextView, mis paigutatakse vaatesse. Seal on ka silt, mis peaks olema märgiloendur. Selles kohas suurendame tähemärki, kui kasutaja tekstivaatesse teksti tipib.

IOS-i ühisteksti redaktorirakenduse kodeerimine

Nüüd, kui oleme rakenduse laadimiseks vajalikud vaated edukalt loonud, peame järgmise asjana alustama rakenduse loogika kodeerimist.

Looge uus kakaoklassi fail ja pange sellele nimeks TextEditorViewController ning linkige see faili Main.storyboard kolmanda vaatega. TextViewController peaks vastu võtma ka UITextViewDelegate. Nüüd saate Ctrl + lohistada UITextView ja ka Ctrl + lohistada faili Main.storyboard UILabel klassi TextEditorViewController.

Samuti peaksite impordima teegid PusherSwift ja AlamoFire TextViewControllerisse. Pärast töö lõppu peaks teil olema midagi lähedast:

import UIKit
    impordi PusherSwift
    import Alamofire
    klass TextEditorViewController: UIViewController, UITextViewDelegate {
        @IBOutlet nõrk var textView: UITextView!
        @IBOutlet nõrgad var märgidLabel: UILabel!
    }

Nüüd peame lisama mõned omadused, mida vajame millalgi hiljem kontrolleris.

import UIKit
    impordi PusherSwift
    import Alamofire
    klass TextEditorViewController: UIViewController, UITextViewDelegate {
        staatiline lase API_ENDPOINT = "http: // localhost: 4000";
        @IBOutlet nõrk var textView: UITextView!
        @IBOutlet nõrgad var märgidLabel: UILabel!
        var tõukur: tõukur!
        var chillPill = tõsi
        var placeHolderText = "Alusta tippimist ..."
        var randomUuid: String = ""
    }

Nüüd jaotame loogika kolmeks osaks:

  1. Vaadake ja klaviatuuri sündmusi
  2. UITextViewDelegate meetodid
  3. Pusheri sündmuste käsitlemine.

Vaadake ja klaviatuuri sündmusi

Avage TextEditorViewController ja värskendage seda järgmiste meetoditega:

alistada funktsiooni viewDidLoad () {
        super.viewDidLoad ()

        // Teavituse päästik
        NotificationCenter.default.addObserver (isevalija: #selector (keyboardWillShow), nimi: NSNotification.Name.UIKeyboardWillShow, objekt: null)
        NotificationCenter.default.addObserver (isevalija: #selector (keyboardWillHide), nimi: NSNotification.Name.UIKeyboardWillHide, objekt: null)

        // Žestituvastus
        view.addGestureRecognizer (UITapGestureRecognizer (sihtmärk: ise, tegevus: #selector (koputatudAwayFunction (_ :)))))

        // Seadke kontroller textView delegaadiks
        textView.delegate = ise

        // Seadistage seadme ID
        randomUuid = UIDevice.current.identifierForVendor! .uuidString

        // Kuulake muudatusi Pusherist
        listenForChanges ()
    }

    alistada func viewWillAppear (_ animeeritud: Bool) {
        super.viewWillAppear (animeeritud)

        kui self.textView.text == "" {
            self.textView.text = placeHolderText
            self.textView.textColor = UIColor.lightGray
        }
    }

    func keyboardWillShow (teatis: NSNotification) {
        kui lasta keyboardSize = (teatis.userInfo? [UIKeyboardFrameBeginUserInfoKey] kui? NSValue) ?. cgRectValue {
            kui self.charactersLabel.frame.origin.y == 1.0 {
                self.charactersLabel.frame.origin.y - = keyboardSize.height
            }
        }
    }

    func keyboardWillHide (teatis: NSNotification) {
        kui lasta keyboardSize = (teatis.userInfo? [UIKeyboardFrameBeginUserInfoKey] kui? NSValue) ?. cgRectValue {
            kui self.view.frame.origin.y! = 1,0 {
                self.charactersLabel.frame.origin.y + = keyboardSize.height
            }
        }
    }

Meetodis viewDidLoad registreerisime klaviatuuri funktsioonid, et nad reageeriksid klaviatuuri sündmustele. Lisasime ka žestituvastuse, mis loobub klaviatuurist, kui koputate väljaspool UITextView. Ja me seadsime textView delegaadi kontrollerile endale. Lõpuks kutsusime funktsiooni uute värskenduste kuulamiseks (loome selle hiljem).

Meetodi viewWillAppear puhul häkkisime UITextView lihtsalt kohahoidjateksti saamiseks, kuna vaikimisi UITextView seda funktsiooni ei ole. Huvitav miks, Apple ...

Funktsioonides keyboardWillShow ja keyboardWillHide panime märkide loendussildi klaviatuuri abil üles tõusma ja koos sellega laskuma. See takistab klaviatuuril silti katmast, kui see on aktiivne.

UITextViewDelegate meetodid

Värskendage TextEditorViewControlleri järgmiselt:

func textViewDidChange (_ textView: UITextView) {
        characterLabel.text = String (formaat: "% i märgid", textView.text.characters.count)
        kui textView.text.characters.count> = 2 {
            sendToPusher (tekst: textView.text)
        }
    }
    func textViewShouldBeginEditing (_ textView: UITextView) -> Bool {
        self.textView.textColor = UIColor.black
        kui self.textView.text == placeHolderText {
            self.textView.text = ""
        }
        tagasta tõsi
    }
    func textViewDidEndEditing (_ textView: UITextView) {
        kui textView.text == "" {
            self.textView.text = placeHolderText
            self.textView.textColor = UIColor.lightGray
        }
    }
    func tappedAwayFunction (_ saatja: UITapGestureRecognizer) {
        textView.resignFirstResponder ()
    }

Meetod textViewDidChange värskendab lihtsalt tähemärkide arvu silti ja saadab muudatused ka Pusherisse, kasutades meie taustaprogrammi API-d (mille me loome minutiga).

TextViewShouldBeginEditing on hangitud UITextViewDelegate'ist ja see käivitatakse siis, kui tekstivaadet hakatakse redigeerima. Siin mängime põhimõtteliselt kohahoidjaga ringi, nagu ka meetodil textViewDidEndEditing.

Lõpuks määratleme funktsioonis tappedAwayFunction eelmises jaotises registreeritud žesti sündmuse tagasihelistamise. Meetodi puhul jätame klaviatuuri põhimõtteliselt rahuldamata.

Pusheri sündmuste käsitlemine

Uuendage kontrollerit järgmiste meetoditega:

func sendToPusher (tekst: string) {
        las params: Parameters = ["tekst": tekst, "pärit": randomUuid]
        Alamofire.request (TextEditorViewController.API_ENDPOINT + "/ update_text", meetod: .post, parameetrid: params) .validate (). ResponseJSON {response in
            vaheta vastust.tulemus {
            juhtum. edu:
                print ("õnnestus")
            juhtum. rike (lase viga):
                print (viga)
            }
        }
    }
    func listenForChanges () {
        tõukur = tõukur (võti: "PUSHER_KEY", valikud: PusherClientOptions (
            host: .cluster ("PUSHER_CLUSTER")
        ))
        lase kanal = pusher.subscribe ("koostöö")
        lase _ = channel.bind (eventName: "text_update", tagasihelistamine: {(andmed: kas?) -> Void in
            kui las andmed = andmed kui? [String: AnyObject] {
                lase fromDeviceId = data ["deviceId"] as! Keel
                kui fromDeviceId! = ise.randomUuid {
                    lase tekst = andmed ["tekst"] kui! Keel
                    self.textView.text = tekst
                    self.charactersLabel.text = String (formaat: "% i märgid", text.characters.count)
                }
            }
        })
        pusher.connect ()
    }

SendToPusheri meetodi puhul saadame kasulikku koormust oma taustarakendusse AlamoFire abil, mis omakorda saadab selle Pusherile.

Seejärel kuulame kuulamismeetodil listenForChanges teksti muudatusi ja kui neid on, rakendame muudatused tekstivaates.

Ärge unustage asendada võtit ja klastrit tegeliku väärtusega, mille olete oma Pusheri armatuurlaualt saanud.

Kui olete õpetust tähelepanelikult jälginud, peaks teie TextEditorViewController välja nägema umbes selline:

import UIKit
    impordi PusherSwift
    import Alamofire
    klass TextEditorViewController: UIViewController, UITextViewDelegate {
        staatiline lase API_ENDPOINT = "http: // localhost: 4000";
        @IBOutlet nõrk var textView: UITextView!
        @IBOutlet nõrgad var märgidLabel: UILabel!
        var tõukur: tõukur!
        var chillPill = tõsi
        var placeHolderText = "Alusta tippimist ..."
        var randomUuid: String = ""
        alistada funktsiooni viewDidLoad () {
            super.viewDidLoad ()
            // Teavituse päästik
            NotificationCenter.default.addObserver (isevalija: #selector (keyboardWillShow), nimi: NSNotification.Name.UIKeyboardWillShow, objekt: null)
            NotificationCenter.default.addObserver (isevalija: #selector (keyboardWillHide), nimi: NSNotification.Name.UIKeyboardWillHide, objekt: null)
            // Žestituvastus
            view.addGestureRecognizer (UITapGestureRecognizer (sihtmärk: ise, tegevus: #selector (koputatudAwayFunction (_ :)))))
            // Seadke kontroller textView delegaadiks
            textView.delegate = ise
            // Seadistage seadme ID
            randomUuid = UIDevice.current.identifierForVendor! .uuidString
            // Kuulake muudatusi Pusherist
            listenForChanges ()
        }
        alistada func viewWillAppear (_ animeeritud: Bool) {
            super.viewWillAppear (animeeritud)
            kui self.textView.text == "" {
                self.textView.text = placeHolderText
                self.textView.textColor = UIColor.lightGray
            }
        }
        func keyboardWillShow (teatis: NSNotification) {
            kui lasta keyboardSize = (teatis.userInfo? [UIKeyboardFrameBeginUserInfoKey] kui? NSValue) ?. cgRectValue {
                kui self.charactersLabel.frame.origin.y == 1.0 {
                    self.charactersLabel.frame.origin.y - = keyboardSize.height
                }
            }
        }
        func keyboardWillHide (teatis: NSNotification) {
            kui lasta keyboardSize = (teatis.userInfo? [UIKeyboardFrameBeginUserInfoKey] kui? NSValue) ?. cgRectValue {
                kui self.view.frame.origin.y! = 1,0 {
                    self.charactersLabel.frame.origin.y + = keyboardSize.height
                }
            }
        }
        func textViewDidChange (_ textView: UITextView) {
            characterLabel.text = String (formaat: "% i märgid", textView.text.characters.count)
            kui textView.text.characters.count> = 2 {
                sendToPusher (tekst: textView.text)
            }
        }
        func textViewShouldBeginEditing (_ textView: UITextView) -> Bool {
            self.textView.textColor = UIColor.black
            kui self.textView.text == placeHolderText {
                self.textView.text = ""
            }
            tagasta tõsi
        }
        func textViewDidEndEditing (_ textView: UITextView) {
            kui textView.text == "" {
                self.textView.text = placeHolderText
                self.textView.textColor = UIColor.lightGray
            }
        }
        func tappedAwayFunction (_ saatja: UITapGestureRecognizer) {
            textView.resignFirstResponder ()
        }
        func sendToPusher (tekst: string) {
            las params: Parameters = ["tekst": tekst, "pärit": randomUuid]
            Alamofire.request (TextEditorViewController.API_ENDPOINT + "/ update_text", meetod: .post, parameetrid: params) .validate (). ResponseJSON {response in
                vaheta vastust.tulemus {
                juhtum. edu:
                    print ("õnnestus")
                juhtum. rike (lase viga):
                    print (viga)
                }
            }
        }
        func listenForChanges () {
            tõukur = tõukur (võti: "PUSHER_KEY", valikud: PusherClientOptions (
                host: .cluster ("PUSHER_CLUSTER")
            ))
            lase kanal = pusher.subscribe ("koostöö")
            lase _ = channel.bind (eventName: "text_update", tagasihelistamine: {(andmed: kas?) -> Void in
                kui las andmed = andmed kui? [String: AnyObject] {
                    lase fromDeviceId = data ["deviceId"] as! Keel
                    kui fromDeviceId! = ise.randomUuid {
                        lase tekst = andmed ["tekst"] kui! Keel
                        self.textView.text = tekst
                        self.charactersLabel.text = String (formaat: "% i märgid", text.characters.count)
                    }
                }
            })
            pusher.connect ()
        }
    }

Tore! Nüüd peame tegema rakenduse taustprogrammi.

Rakenduse backend Node loomine

Nüüd, kui Swifti osa on tehtud, saame keskenduda rakenduse taustaprogrammi Node.js loomisele. Kasutame Expressi, et saaksime kiiresti midagi käima saada.

Looge veebirakenduse jaoks kataloog ja looge siis mõned uued failid.

Fail index.js:

lase tee = nõua ('tee');
    las Pusher = nõuda ('tõukur');
    las väljendada = nõuda ('väljendama');
    lase bodyParser = nõuda ('body-parser');
    lase rakendusel = väljendada ();
    lase tõukur = new Pusher (nõua ('./ config.js'));
    app.use (bodyParser.json ());
    app.use (bodyParser.urlencoded ({laiendatud: vale}));
    app.post ('/ update_text', funktsioon (req, res) {
      var payload = {tekst: req.body.text, deviceId: req.body.from}
      pusher.trigger ('koostöö', 'teksti_uuendus', kasulik koormus)
      res.json ({edu: 200})
    });
    app.use (funktsioon (req, res, next) {
        var err = uus viga ('ei leitud');
        err.status = 404;
        järgmine (viga);
    });
    moodul.exports = rakendus;
    app.listen (4000, funktsioon () {
      console.log ('Rakenduste kuulamine pordil 4000!');
    });

Ülaltoodud JS-failis kasutame Expressi abil lihtsa rakenduse loomist. Teekonnal / update_text saame lihtsalt koormat ja edastame selle Pusherile. Midagi keerulist seal pole.

Looge ka fail pack.json:

{
      "main": "index.js",
      "sõltuvused": {
        "keha parser": "^ 1.17.2",
        "ekspress": "^ 4.15.3",
        "tee": "^ 0.12,7",
        "tõukur": "^ 1.5.1"
      }
    }

Failis package.json määratleme kõik NPM-i sõltuvused.

Viimane loodav fail on config.js-fail. Siin määratleme meie Pusher-rakenduse konfiguratsiooniväärtused:

moodul.exports = {
      appId: 'PUSHER_ID',
      võti: 'PUSHER_KEY',
      saladus: 'PUSHER_SECRET',
      klaster: 'PUSHER_CLUSTER',
      krüptitud: tõsi
    };
Ärge unustage asendada võtit ja klastrit tegeliku väärtusega, mille olete oma Pusheri armatuurlaualt saanud.

Nüüd käivitage kataloogis npm install ja seejärel npm index.js, kui npm installimine on lõppenud. Peaksite nägema pordil 4000 kuulatavat rakendust! sõnum.

Rakenduse testimine

Kui teie kohalik sõlme veebiserver on käivitatud, peate tegema mõned muudatused, et teie rakendus saaks kohaliku veebiserveriga rääkida. Tehke failis info.plist järgmised muudatused:

Selle muudatusega saate oma rakenduse luua ja käivitada ning see räägib otse teie kohaliku veebirakendusega.

Järeldus

Selles artiklis oleme arutanud, kuidas luua Pusheri abil iOS-i reaalajas ühisteksti redaktor. Loodetavasti olete õpiku järgimisest midagi või kaks õppinud. Harjutamiseks saate olekuid laiendada, et toetada rohkem esinemisjuhte.

See postitus avaldati esmakordselt ajakirjas Pusher.