Xcode este IDE-ul principal (Integrated Development Environment) folosit de mii și mii de dezvoltatori în fiecare zi. Este un instrument minunat, dar uneori doriți să personalizați unele dintre caracteristicile și comportamentele sale pentru a se potrivi mai bine fluxului dvs. de lucru.
Până la Xcode 7, a fost posibil să se injecteze codul în Xcode la timpul de execuție pentru a crea pluginuri. Pluginurile pot fi trimise și distribuite printr-o aplicație excelentă numită Alcatraz. Acest lucru nu mai este posibil în Xcode 8.
Xcode 8 validează fiecare bibliotecă și pachet pentru a împiedica executarea codului rău intenționat fără permisiunea dvs. Când începe Xcode, pluginurile deja instalate cu Alcatraz nu mai sunt încărcate. Nu totul este pierdut totuși, Apple a anunțat, de asemenea, la WWDC posibilitatea de a se dezvolta Extensii ale editorului de surse Xcode astfel încât toată lumea să poată extinde funcțiile de editare a surselor existente. Să aruncăm o privire asupra a ceea ce putem obține cu astfel de extensii.
Extensiile editorului de surse Xcode 8 reprezintă un prim pas în direcția cea bună. Dacă ați lucrat cu Xcode pentru o vreme, s-ar fi putut afla într-o situație în care ați dorit ca o anumită sarcină să poată fi automatizată în cadrul Xcode. Extensiile editorului sursă permit aplicațiilor terță parte să modifice un fișier sursă, ceea ce este exact ceea ce aveți nevoie pentru a vă accelera fluxul de lucru.
În acest moment, extensiile pot interacționa numai cu codul sursă. Aceasta înseamnă că nu orice plugin disponibil prin Alcatraz poate fi înlocuit de o extensie a editorului sursă. Dar cine știe ce va aduce viitorul.
Este important să înțelegeți că fiecare extensie trebuie să fie inclusă într-o aplicație macOS. Ați putea, de exemplu, să adăugați preferințe și explicații privind extensia în aplicația macOS și să o distribuiți prin Mac App Store. De asemenea, rețineți că fiecare extensie rulează într-o proces separat. În cazul în care extensia se blochează, nu se va prăbuși Xcode. În schimb, acesta va afișa un mesaj care arată că extensia nu și-a putut finaliza activitatea.
În plus, extensii nu aveți o interfață de utilizator și pot modifica codul numai atunci când utilizatorul invocă comanda. Ele nu pot, de exemplu, să ruleze în fundal.
Vă recomandăm să vizionați sesiunea WWDC 2016 despre extensiile editorului sursă. Nu numai că explică cum să începeți dezvoltarea extensiilor editorului sursă Xcode, ci și sfaturi și comenzi rapide pentru a accelera dezvoltarea.
În acest tutorial, vom dezvolta o extensie care curăță sintaxa de închidere din Swift. Xcode completează o sintaxă de închidere cu parantezele, dar acestea pot fi omise pentru scurtă durată. Aceasta este o sarcină care poate fi ușor automatizată prin împachetarea acesteia într-o extensie a editorului sursă.
Explicația mai scurtă a ceea ce vom dezvolta este o extensie care transformă orice închidere la o sintaxă mai simplă și mai curată. Uitați-vă la exemplul de mai jos.
// înainte de session.dataTask (cu: url) (date, răspuns, eroare) în // După session.dataTask (cu: url) date, răspuns, eroare
Este de la sine înțeles că acest tutorial necesită Xcode 8. Puteți să-l descărcați de pe site-ul dezvoltatorului Apple. Se execută atât pe OS X 10.11, cât și pe MacOS 10.12.
Creaza un nou OS X proiect de tip Cererea de cacao și dați-i numele CleanClosureSyntax. Asigurați-vă că ați setat limba proiectului Rapid. Vom folosi noul Swift 3 sintaxă din acest tutorial.
Vom lăsa acum aplicația macOS goală și ne putem concentra asupra creării extensiei editorului sursă Xcode. De la Fişier meniu, alegeți Nou> Țintă ... . În bara laterală din stânga, alegeți OS X și selectați Xcode Source Editor Extension din listă.
Clic Următor → și stabilit numele produsului la Mai curat. O nouă țintă va fi creată pentru dvs. Clic Activati dacă Xcode vă întreabă dacă nou-creat Sistem ar trebui activat.
Să analizăm mai întâi ce a creat Xcode pentru noi. Extindeți Mai curat pentru a vedea conținutul acestuia.
Nu vom modifica SourceEditorExtension.swift în acest tutorial, dar poate fi folosit pentru a vă personaliza în continuare extensia. extensionDidFinishLaunching ()
metoda este apelată de îndată ce extensia este lansată, astfel încât să puteți efectua orice inițializare dacă este necesar. commandDefinitions
Imagerul de proprietate poate fi folosit dacă doriți să afișați dinamic sau să ascundeți anumite comenzi.
SourceEditorCommand.swift este auzul prelungirii. Acest fișier este locul unde veți implementa logica extensiei. efectua (cu: completionHandler :)
este apelată când utilizatorul lansează extensia. XCSourceEditorCommandInvocation
obiect conține a tampon
proprietate, care este folosit pentru a accesa codul sursă în fișierul selectat în prezent. Operatorul de completare trebuie apelat cu valoare zero
dacă totul a mers bine, altfel o treceți NSError
instanță.
Acum că proiectul conține toate țintele necesare, suntem gata să începem să scriem extensia. Pentru a recupera, dorim să scoatem parantezele de la orice închidere dintr-un fișier Swift. Acest lucru se poate face în trei etape:
Să începem.
Putem folosi un regex (expresie regulată) pentru a analiza fiecare linie de cod și a vedea dacă acesta conține o închidere. Puteți consulta tutorialul lui Akiel despre expresiile Swift și regulile dacă doriți să aflați mai multe despre expresiile regulate. Puteți utiliza RegExr pentru a testa expresiile dvs. regulate. Uitați-vă la următorul ecran pentru a vedea cum am testat regex-ul meu.
Deschis SourceEditorCommand.swift și modificați efectua (cu: completionHandler :)
metoda de a arata astfel:
func exec (cu invocare: XCSourceEditorCommandInvocation, completionHandler: (NSError?) -> Void) -> Void var updatedLineIndexes = [Int] () // 1. Cauta linii care contin o sintaxa de inchidere pentru lineIndex in 0 ... < invocation.buffer.lines.count let line = invocation.buffer.lines[lineIndex] as! NSString do let regex = try RegularExpression(pattern: "\\.*\\(.+\\).+in", options: .caseInsensitive) let range = NSRange(0… < line.length) let results = regex.matches(in: line as String, options: .reportProgress, range: range) // 2. When a closure is found, clean up its syntax _ = results.map result in let cleanLine = line.remove(characters: ["(", ")"], in: result.range) updatedLineIndexes.append(lineIndex) invocation.buffer.lines[lineIndex] = cleanLine catch completionHandler(error as NSError) // 3. If at least a line was changed, create an array of changes and pass it to the buffer selections if !updatedLineIndexes.isEmpty let updatedSelections: [XCSourceTextRange] = updatedLineIndexes.map lineIndex in let lineSelection = XCSourceTextRange() lineSelection.start = XCSourceTextPosition(line: lineIndex, column: 0) lineSelection.end = XCSourceTextPosition(line: lineIndex, column: 0) return lineSelection invocation.buffer.selections.setArray(updatedSelections) completionHandler(nil)
Mai întâi creează și o serie de Int
valori care vor conține indici de linie ai liniilor modificate. Acest lucru se datorează faptului că nu dorim să înlocuim toate liniile. Vrem să înlocuim doar liniile pe care le modificăm.
Ne enumerăm în toate liniile invocation.buffer
obiect și încercăm să găsim un meci pentru Expresie uzuala
obiect. Dacă am elimina caracterele care au ieșit din regex, ar fi după cum urmează:
. * (. +). + În
Acest regex se potrivește atunci când un șir are următoarele caracteristici:
), care este urmat de 0 sau mai multe caractere, cu excepția unui nou caracter de linie (\ n
).(
) trebuie să fie găsită din nou, urmată de 0 sau mai multe caractere. Această parte trebuie să conțină parametrii închiderii.)
), urmat de 0 sau mai multe caractere, care sunt tipurile opționale de returnare.în
cuvântul cheie ar trebui să fie găsit.În cazul în care Expresie uzuala
obiectul nu reușește să găsească o potrivire (de exemplu, dacă regexul nu este valid), sunăm completionHandler
cu eroarea ca parametru. Dacă un șir care corespunde tuturor acestor condiții este găsit pe o linie, am localizat corect o închidere.
Când se găsește o potrivire, vom apela o metodă utilitară NSString
care elimină parantezele. De asemenea, trebuie să trecem în intervalul meciului pentru a evita eliminarea altor paranteze în afara închiderii.
Ultima parte a codului verifică dacă cel puțin o linie a fost modificată. Dacă este adevărat, sunăm setArray ()
pentru a înlocui noile linii și indiciile corecte. Operatorul de completare este numit cu valoarea zero
astfel încât Xcode știe că totul a mers bine.
Trebuie să implementăm în continuare elimina (caractere: interval :)
metoda pe NSString
. Să adăugăm această extensie în partea de sus a fișierului.
extensie NSString // Eliminați caracterele date în intervalul func remove (caractere: [Caracter], în intervalul: NSRange) -> NSString var cleanString = auto pentru char în caractere cleanString = cleanString.replacingOccurrences (of: String ), cu: "", opțiuni: .caseInsensitiveSearch, interval: interval) retur curatString
Această metodă solicită replacingOccurrences (de: cu: gama :)
pe NSString
pentru fiecare personaj pe care dorim să îl eliminăm.
Xcode 8 vine cu o soluție excelentă pentru testarea extensiilor. Mai întâi, dacă alergi OS X 10.11 El Capitan, deschis Terminal, executați următoarea comandă și reporniți computerul Mac.
sudo / usr / libexec / xpccachectl
După aceasta, construiți și executați extensia dvs. selectând schema corespunzătoare. Când se întreabă ce aplicație să ruleze, căutați Xcode și asigurați-vă că ați selectat beta versiunea Xcode 8. O nouă versiune Xcode va fi lansată cu pictograma aplicației gri, astfel încât să puteți recunoaște în ce instanță de Xcode testați extensia.
În noua instanță Xcode, creați un proiect nou sau deschideți unul existent și mergeți la Editor> Curățire închidere> Comandă editor sursă. Asigurați-vă că aveți cel puțin o închidere în fișierul Swift focalizat în prezent pentru a vedea rezultatul. După cum puteți vedea în următoarea animație, extensia noastră funcționează.
Source Command Editor este numele implicit pentru o comandă. Puteți să o modificați în Info.plist fișierul extensiei. Deschideți-l și schimbați șirul Sintaxă curată.
De asemenea, putem atribui o scurtătură pentru a invoca automat Sintaxă curată comanda. Deschideți codurile Xcode Preferințe și selectați Legarea cheilor tab. Caută Sintaxă curată și va apărea comanda. Faceți clic în partea dreaptă a acesteia și apăsați pe scurt comanda rapidă pe care doriți să o utilizați, de exemplu, Command-Alt-Shift-+. Acum puteți să reveniți la fișierul sursă și să apăsați comanda rapidă pentru ao invoca direct.
Xcode 8 și extensiile editorului sursă sunt încă în versiune beta la momentul redactării. Următoarele sfaturi vă pot ajuta să depanați anumite probleme cu care vă confruntați.
Dacă extensia dvs. nu este selectabilă în instanța de testare Xcode, uitați-o com.apple.dt.Xcode.AttachToXPCService procesați și executați din nou extensia.
Numai înlocuiți înapoi liniile pe care le modificați în tampon. Aceasta face ca extensia să funcționeze mai repede și va avea mai puține șanse să fie ucisă de Xcode. Aceasta din urmă se poate întâmpla dacă Xcode consideră că o comandă a extensiei dvs. durează prea mult.
Dacă doriți să afișați mai multe comenzi, atribuiți fiecărei comenzi un alt identificator și utilizați commandIdentifier
proprietate pe XCSourceEditorCommandInvocation
obiect pentru a recunoaște care dintre utilizatori a declanșat.
Crearea extensiei editorului sursă Xcode este foarte ușoară. Dacă vă puteți îmbunătăți fluxul de lucru și vă puteți grăbi dezvoltarea, creând o extensie a editorului sursă, continuați și faceți-o să se întâmple. Apple a introdus un nou mod pentru dezvoltatori de a distribui plugin-uri semnate prin Mac App Store, astfel încât să vă puteți elibera munca și să urmăriți alți dezvoltatori să beneficieze de ea.
Puteți găsi codul sursă al exemplului acestui tutorial pe GitHub.