SlideShare a Scribd company logo
1 of 26
Download to read offline
Enhancing Your Workflow with Xcode Source Editor Extensions
By: Jesse Black
Software Engineer
stable|kernel

jesse.black@stablekernel.com
@stablekernel
Hi, I’m Jesse Black.
• Programming for over eight years
• Created a Mac App for my family business
• Worked for 3 years with Gramercy Consultants developing iOS and Android apps
• Working for stable|kernel for the past 3 years developing iOS apps, Android apps
and their supporting APIs
We’re stable|kernel.
stable|kernel is an Atlanta-based mobile development company 

to craft smartly-designed mobile applications that connect brands 

directly with their users. 



Enhancing Your Workflow with Xcode Source Editor Extensions
@stablekernel
Overview
Mac App Extensions
Xcode Source Editor Extensions
Demo: Create Source Editor Extension and debugging it
XC Classes
Example: JSON formatter
Demo: JSON formatter in action
Mac App Extensions
@stablekernel
• Mac App Extensions
• Affect the user experience of other apps
• Need to be lightweight and run fast
• Require user interaction in order to be run
• Distribute via host app
Why use Xcode Source Editor Extensions
@stablekernel
• Less context switching
• It is too fun to customize your workflow
Xcode Source Editor Extensions
@stablekernel
• Differences with general Mac App Extensions
• Extensions are installed by just putting the host application in your
applications folder
• Only works with one type of target application, which is Xcode
• Doesn’t have UI
Xcode Source Editor Extensions
@stablekernel
• Allows you to add custom commands under Xcode’s Editor menu
• Commands can manipulate text and text selections
• Users can put bind keyboard shortcuts to invoke your commands
Limitations to Xcode Source Editor Extensions
@stablekernel
• Can only start with user interaction
• Lack of ability to integrate into the build process and archive process. It
is for modifying source code while it is being edited.
Expectations of Xcode Source Editor Extensions
@stablekernel
• Fast start up
• Fast execution
• Security and Stability
Demo
@stablekernel
Overview
Create Source Editor Extension
How to install
How to debug
How to uninstall
Defining Commands
@stablekernel
• Command Identifier
• Class Name
• Command Name
Commands can be defined in the Extension’s plist or by supplying a
dictionary at runtime. Commands provided at runtime override commands
defined in the plist.
XC Source Editor Extension
@stablekernel
func extensionDidFinishLaunching() {}
var commandDefinitions: [[XCSourceEditorCommandDefinitionKey: Any]] {}
XC Source Editor Command
@stablekernel
func perform(with invocation: XCSourceEditorCommandInvocation,
completionHandler: @escaping (Error?) -> Void ) -> Void {
XC Source Editor Command
@stablekernel
• Modify text, text selection
• Exit early with an error message that is displayed in Xcode
XC Source Editor Command Invocation
@stablekernel
• Encapsulates all details needed to fulfill the user’s request
• contentUTI
• usesTabsForIndentation
• indentationWidth
• tabWidth
• buffer
XC Source Text Buffer
@stablekernel
• completeBuffer
• lines
• selections
• defined in terms of lines and columns
Example: JSON formatter
@stablekernel
• Define minify and prettify commands
• Implement XCSourceEditorCommand’s perform method
• Validate requirements for command
• Get first text selection
• Return error if selected text isn’t valid JSON
• Use JSONSerialization class to format text
• Replace selected text
XCSourceEditorExtension
@stablekernel
var commandDefinitions: [[XCSourceEditorCommandDefinitionKey: Any]] {
return [
[
.classNameKey: "JeSON.SourceEditorCommand",
.identifierKey: JeSONInvocation.Minify.rawValue,
.nameKey: "Minify"
],
[
.classNameKey: "JeSON.SourceEditorCommand",
.identifierKey: JeSONInvocation.Prettify.rawValue,
.nameKey: "Prettify"
],
]
}
XCSourceEditorExtension
@stablekernel
enum JeSONInvocation: String {
case Prettify = "com.jesseblack.HelloWorldProject.JeSON.Prettify"
case Minify = "com.jesseblack.HelloWorldProject.JeSON.Minify"
}
@stablekernel
func textAtSelectionIndex(_ at: Int, buffer: XCSourceTextBuffer) -> String {
let textRange = buffer.selections[at] as! XCSourceTextRange
let selectionLines = buffer.lines.enumerated().filter { (offset, element) -> Bool in
return offset >= textRange.start.line && offset <= textRange.end.line
}.map { return $1 }
return selectionLines.enumerated().reduce("") { (result, enumeration) -> String in
let line = enumeration.element as! String
if enumeration.offset == 0 && enumeration.offset == selectionLines.count - 1 {
let startIndex = line.index(line.startIndex, offsetBy: textRange.start.column)
let endIndex = line.index(line.startIndex, offsetBy: textRange.end.column + 1)
return result + line.substring(with: startIndex..<endIndex)
} else if enumeration.offset == 0 {
let startIndex = line.index(line.startIndex, offsetBy: textRange.start.column)
return result + line.substring(from: startIndex)
} else if enumeration.offset == selectionLines.count - 1 {
let endIndex = line.index(line.startIndex, offsetBy: textRange.end.column + 1)
return result + line.substring(to: endIndex)
}
return result + line
}
}
@stablekernel
func replaceTextAtSelectionIndex(_ at: Int, replacementText: String, buffer: XCSourceTextBuffer)
{
let textRange = buffer.selections[at] as! XCSourceTextRange
let lastLine = buffer.lines[textRange.end.line] as! String
let endIndex = lastLine.index(lastLine.startIndex, offsetBy: textRange.end.column+1)
let suffix = lastLine.substring(from: endIndex)
let firstLine = buffer.lines[textRange.start.line] as! String
let startIndex = firstLine.index(firstLine.startIndex, offsetBy: textRange.start.column)
let prefix = firstLine.substring(to: startIndex)
let range = NSMakeRange(textRange.start.line, textRange.end.line - textRange.start.line + 1)
buffer.lines.removeObjects(in: range)
buffer.lines.insert(prefix+replacementText+suffix, at: textRange.start.line)
let newRange = XCSourceTextRange(start: textRange.start, end: textRange.start)
buffer.selections.setArray([newRange])
}
Performing the command
@stablekernel
func perform(with invocation: XCSourceEditorCommandInvocation, completionHandler: @escaping
(Error?) -> Void ) -> Void {
guard let jeSONInvocation = JeSONInvocation(rawValue: invocation.commandIdentifier) else {
let errorInfo = [NSLocalizedDescriptionKey: "Command not recognized"]
completionHandler(NSError(domain: "", code: 0, userInfo: errorInfo))
return
}
let buffer = invocation.buffer
guard buffer.selections.count == 1 else {
let errorInfo = [NSLocalizedDescriptionKey: "Command only handles 1 selection at a time"]
completionHandler(NSError(domain: "", code: 0, userInfo: errorInfo))
return
}
Performing the command
@stablekernel
// perform continued
let selectedText = textAtSelectionIndex(0, buffer: buffer)
let data = selectedText.data(using: .utf8)
do {
let jsonObject = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions())
switch jeSONInvocation {
case .Minify:
let miniData = try! JSONSerialization.data(withJSONObject: jsonObject, options: JSONSerialization.WritingOptions())
let string = String.init(data: miniData, encoding: .utf8)!
replaceTextAtSelectionIndex(0, replacementText: string, buffer: buffer)
case .Prettify:
let miniData = try! JSONSerialization.data(withJSONObject: jsonObject, options: .prettyPrinted)
let string = String.init(data: miniData, encoding: .utf8)!
replaceTextAtSelectionIndex(0, replacementText: string, buffer: buffer)
}
}
catch {
completionHandler(error)
}
completionHandler(nil)
}
JSON Formatter Demo
@stablekernel
Overview
See all the hard work pay off
Questions?
Business Inquiries:
Sarah Woodward
Director of Business Development
sarah.woodward@stablekernel.com
Jesse Black
Software Engineer
jesse.black@stablekernel.com
blog.stablekernel.com
@JesseBlack82
http://www.slideshare.net/stablekernel
https://github.com/JesseBlack82/HelloExtensions

More Related Content

What's hot

Practical tips for building apps with kotlin
Practical tips for building apps with kotlinPractical tips for building apps with kotlin
Practical tips for building apps with kotlinAdit Lal
 
Save time with kotlin in android development
Save time with kotlin in android developmentSave time with kotlin in android development
Save time with kotlin in android developmentAdit Lal
 
Android Architecture Components with Kotlin
Android Architecture Components with KotlinAndroid Architecture Components with Kotlin
Android Architecture Components with KotlinAdit Lal
 
Memory management in Objective C
Memory management in Objective CMemory management in Objective C
Memory management in Objective CNeha Gupta
 
Demystifying Oak Search
Demystifying Oak SearchDemystifying Oak Search
Demystifying Oak SearchJustin Edelson
 
How AngularJS Embraced Traditional Design Patterns
How AngularJS Embraced Traditional Design PatternsHow AngularJS Embraced Traditional Design Patterns
How AngularJS Embraced Traditional Design PatternsRan Mizrahi
 
Scala @ TechMeetup Edinburgh
Scala @ TechMeetup EdinburghScala @ TechMeetup Edinburgh
Scala @ TechMeetup EdinburghStuart Roebuck
 
Workshop 26: React Native - The Native Side
Workshop 26: React Native - The Native SideWorkshop 26: React Native - The Native Side
Workshop 26: React Native - The Native SideVisual Engineering
 
Кирилл Безпалый, .NET Developer, Ciklum
Кирилл Безпалый, .NET Developer, CiklumКирилл Безпалый, .NET Developer, Ciklum
Кирилл Безпалый, .NET Developer, CiklumAlina Vilk
 
Kotlin for Android devs
Kotlin for Android devsKotlin for Android devs
Kotlin for Android devsAdit Lal
 
Workshop 23: ReactJS, React & Redux testing
Workshop 23: ReactJS, React & Redux testingWorkshop 23: ReactJS, React & Redux testing
Workshop 23: ReactJS, React & Redux testingVisual Engineering
 
JavaCro 2014 Scala and Java EE 7 Development Experiences
JavaCro 2014 Scala and Java EE 7 Development ExperiencesJavaCro 2014 Scala and Java EE 7 Development Experiences
JavaCro 2014 Scala and Java EE 7 Development ExperiencesPeter Pilgrim
 

What's hot (20)

Practical tips for building apps with kotlin
Practical tips for building apps with kotlinPractical tips for building apps with kotlin
Practical tips for building apps with kotlin
 
Save time with kotlin in android development
Save time with kotlin in android developmentSave time with kotlin in android development
Save time with kotlin in android development
 
Android Architecture Components with Kotlin
Android Architecture Components with KotlinAndroid Architecture Components with Kotlin
Android Architecture Components with Kotlin
 
Memory management in Objective C
Memory management in Objective CMemory management in Objective C
Memory management in Objective C
 
Demystifying Oak Search
Demystifying Oak SearchDemystifying Oak Search
Demystifying Oak Search
 
How AngularJS Embraced Traditional Design Patterns
How AngularJS Embraced Traditional Design PatternsHow AngularJS Embraced Traditional Design Patterns
How AngularJS Embraced Traditional Design Patterns
 
Scala @ TechMeetup Edinburgh
Scala @ TechMeetup EdinburghScala @ TechMeetup Edinburgh
Scala @ TechMeetup Edinburgh
 
C#2
C#2C#2
C#2
 
Objective C Memory Management
Objective C Memory ManagementObjective C Memory Management
Objective C Memory Management
 
Angular2
Angular2Angular2
Angular2
 
Workshop 26: React Native - The Native Side
Workshop 26: React Native - The Native SideWorkshop 26: React Native - The Native Side
Workshop 26: React Native - The Native Side
 
EMF Tips n Tricks
EMF Tips n TricksEMF Tips n Tricks
EMF Tips n Tricks
 
Кирилл Безпалый, .NET Developer, Ciklum
Кирилл Безпалый, .NET Developer, CiklumКирилл Безпалый, .NET Developer, Ciklum
Кирилл Безпалый, .NET Developer, Ciklum
 
Kotlin for Android devs
Kotlin for Android devsKotlin for Android devs
Kotlin for Android devs
 
Workshop 23: ReactJS, React & Redux testing
Workshop 23: ReactJS, React & Redux testingWorkshop 23: ReactJS, React & Redux testing
Workshop 23: ReactJS, React & Redux testing
 
jdbc
jdbcjdbc
jdbc
 
JavaCro 2014 Scala and Java EE 7 Development Experiences
JavaCro 2014 Scala and Java EE 7 Development ExperiencesJavaCro 2014 Scala and Java EE 7 Development Experiences
JavaCro 2014 Scala and Java EE 7 Development Experiences
 
Ios - Introduction to memory management
Ios - Introduction to memory managementIos - Introduction to memory management
Ios - Introduction to memory management
 
55 New Features in Java 7
55 New Features in Java 755 New Features in Java 7
55 New Features in Java 7
 
Workshop 17: EmberJS parte II
Workshop 17: EmberJS parte IIWorkshop 17: EmberJS parte II
Workshop 17: EmberJS parte II
 

Viewers also liked

How to create a jQuery Modal Window
How to create a jQuery Modal WindowHow to create a jQuery Modal Window
How to create a jQuery Modal WindowLikno Software
 
Purchasing power parity a unit root, cointegration and var analysis in emergi...
Purchasing power parity a unit root, cointegration and var analysis in emergi...Purchasing power parity a unit root, cointegration and var analysis in emergi...
Purchasing power parity a unit root, cointegration and var analysis in emergi...Giwrgos Loukopoulos
 
A Hypervisor IPS based on Hardware Assisted Virtualization Technology
A Hypervisor IPS based on Hardware Assisted Virtualization TechnologyA Hypervisor IPS based on Hardware Assisted Virtualization Technology
A Hypervisor IPS based on Hardware Assisted Virtualization TechnologyFFRI, Inc.
 
EQUITY MARKET INTEGRATION IN SELECTED MARKETS: EVIDENCE FROM UNIT ROOT AND CO...
EQUITY MARKET INTEGRATION IN SELECTED MARKETS: EVIDENCE FROM UNIT ROOT AND CO...EQUITY MARKET INTEGRATION IN SELECTED MARKETS: EVIDENCE FROM UNIT ROOT AND CO...
EQUITY MARKET INTEGRATION IN SELECTED MARKETS: EVIDENCE FROM UNIT ROOT AND CO...akjsk10
 
Representational State Transfer (REST)
Representational State Transfer (REST)Representational State Transfer (REST)
Representational State Transfer (REST)Abhay Ananda Shukla
 
1.Buffer Overflows
1.Buffer Overflows1.Buffer Overflows
1.Buffer Overflowsphanleson
 
Creational pattern
Creational patternCreational pattern
Creational patternHimanshu
 
Intrinsic Encounter - Cognitive Load Theory
Intrinsic Encounter - Cognitive Load TheoryIntrinsic Encounter - Cognitive Load Theory
Intrinsic Encounter - Cognitive Load TheoryDylan Grace
 
Web design trends for 2010
Web design trends for 2010Web design trends for 2010
Web design trends for 2010Tijs Vrolix
 
Minimize Cognitive Load + Maximize Conversions : 10 Tips
Minimize Cognitive Load + Maximize Conversions : 10 TipsMinimize Cognitive Load + Maximize Conversions : 10 Tips
Minimize Cognitive Load + Maximize Conversions : 10 TipsLucid Smart Pill
 
Buffer overflow and other software vulnerabilities: theory and practice of pr...
Buffer overflow and other software vulnerabilities: theory and practice of pr...Buffer overflow and other software vulnerabilities: theory and practice of pr...
Buffer overflow and other software vulnerabilities: theory and practice of pr...Roman Oliynykov
 
Representational State Transfer (REST)
Representational State Transfer (REST)Representational State Transfer (REST)
Representational State Transfer (REST)David Krmpotic
 
Hardware support for efficient virtualization
Hardware support for efficient virtualizationHardware support for efficient virtualization
Hardware support for efficient virtualizationLennox Wu
 
Xcode, Basics and Beyond
Xcode, Basics and BeyondXcode, Basics and Beyond
Xcode, Basics and Beyondrsebbe
 
Load-testing 101 for Startups with Artillery.io
Load-testing 101 for Startups with Artillery.ioLoad-testing 101 for Startups with Artillery.io
Load-testing 101 for Startups with Artillery.ioHassy Veldstra
 
How to Run a 1,000,000 VU Load Test using Apache JMeter and BlazeMeter
How to Run a 1,000,000 VU Load Test using Apache JMeter and BlazeMeterHow to Run a 1,000,000 VU Load Test using Apache JMeter and BlazeMeter
How to Run a 1,000,000 VU Load Test using Apache JMeter and BlazeMeterAlon Girmonsky
 

Viewers also liked (20)

How to create a jQuery Modal Window
How to create a jQuery Modal WindowHow to create a jQuery Modal Window
How to create a jQuery Modal Window
 
Design patterns
Design patternsDesign patterns
Design patterns
 
Lampiran unit root test
Lampiran unit root testLampiran unit root test
Lampiran unit root test
 
Purchasing power parity a unit root, cointegration and var analysis in emergi...
Purchasing power parity a unit root, cointegration and var analysis in emergi...Purchasing power parity a unit root, cointegration and var analysis in emergi...
Purchasing power parity a unit root, cointegration and var analysis in emergi...
 
A Hypervisor IPS based on Hardware Assisted Virtualization Technology
A Hypervisor IPS based on Hardware Assisted Virtualization TechnologyA Hypervisor IPS based on Hardware Assisted Virtualization Technology
A Hypervisor IPS based on Hardware Assisted Virtualization Technology
 
EQUITY MARKET INTEGRATION IN SELECTED MARKETS: EVIDENCE FROM UNIT ROOT AND CO...
EQUITY MARKET INTEGRATION IN SELECTED MARKETS: EVIDENCE FROM UNIT ROOT AND CO...EQUITY MARKET INTEGRATION IN SELECTED MARKETS: EVIDENCE FROM UNIT ROOT AND CO...
EQUITY MARKET INTEGRATION IN SELECTED MARKETS: EVIDENCE FROM UNIT ROOT AND CO...
 
Representational State Transfer (REST)
Representational State Transfer (REST)Representational State Transfer (REST)
Representational State Transfer (REST)
 
1.Buffer Overflows
1.Buffer Overflows1.Buffer Overflows
1.Buffer Overflows
 
Creational pattern
Creational patternCreational pattern
Creational pattern
 
Intrinsic Encounter - Cognitive Load Theory
Intrinsic Encounter - Cognitive Load TheoryIntrinsic Encounter - Cognitive Load Theory
Intrinsic Encounter - Cognitive Load Theory
 
Web design trends for 2010
Web design trends for 2010Web design trends for 2010
Web design trends for 2010
 
Minimize Cognitive Load + Maximize Conversions : 10 Tips
Minimize Cognitive Load + Maximize Conversions : 10 TipsMinimize Cognitive Load + Maximize Conversions : 10 Tips
Minimize Cognitive Load + Maximize Conversions : 10 Tips
 
Buffer overflow and other software vulnerabilities: theory and practice of pr...
Buffer overflow and other software vulnerabilities: theory and practice of pr...Buffer overflow and other software vulnerabilities: theory and practice of pr...
Buffer overflow and other software vulnerabilities: theory and practice of pr...
 
Representational State Transfer (REST)
Representational State Transfer (REST)Representational State Transfer (REST)
Representational State Transfer (REST)
 
Lecture 13
Lecture 13Lecture 13
Lecture 13
 
Buffer overflow
Buffer overflowBuffer overflow
Buffer overflow
 
Hardware support for efficient virtualization
Hardware support for efficient virtualizationHardware support for efficient virtualization
Hardware support for efficient virtualization
 
Xcode, Basics and Beyond
Xcode, Basics and BeyondXcode, Basics and Beyond
Xcode, Basics and Beyond
 
Load-testing 101 for Startups with Artillery.io
Load-testing 101 for Startups with Artillery.ioLoad-testing 101 for Startups with Artillery.io
Load-testing 101 for Startups with Artillery.io
 
How to Run a 1,000,000 VU Load Test using Apache JMeter and BlazeMeter
How to Run a 1,000,000 VU Load Test using Apache JMeter and BlazeMeterHow to Run a 1,000,000 VU Load Test using Apache JMeter and BlazeMeter
How to Run a 1,000,000 VU Load Test using Apache JMeter and BlazeMeter
 

Similar to Connect.Tech- Enhancing Your Workflow With Xcode Source Editor Extensions

What’s new in .NET
What’s new in .NETWhat’s new in .NET
What’s new in .NETDoommaker
 
Striking a Balance With UI Tests - ConnectTech
Striking a Balance With UI Tests - ConnectTechStriking a Balance With UI Tests - ConnectTech
Striking a Balance With UI Tests - ConnectTechstable|kernel
 
Presentation 5th
Presentation 5thPresentation 5th
Presentation 5thConnex
 
Introduction to Elixir
Introduction to ElixirIntroduction to Elixir
Introduction to ElixirDiacode
 
C sharp 8.0 new features
C sharp 8.0 new featuresC sharp 8.0 new features
C sharp 8.0 new featuresMSDEVMTL
 
C sharp 8.0 new features
C sharp 8.0 new featuresC sharp 8.0 new features
C sharp 8.0 new featuresMiguel Bernard
 
What's new in c# 8.0
What's new in c# 8.0What's new in c# 8.0
What's new in c# 8.0Moaid Hathot
 
Building Kafka Connectors with Kotlin: A Step-by-Step Guide to Creation and D...
Building Kafka Connectors with Kotlin: A Step-by-Step Guide to Creation and D...Building Kafka Connectors with Kotlin: A Step-by-Step Guide to Creation and D...
Building Kafka Connectors with Kotlin: A Step-by-Step Guide to Creation and D...HostedbyConfluent
 
Kotlin coroutines and spring framework
Kotlin coroutines and spring frameworkKotlin coroutines and spring framework
Kotlin coroutines and spring frameworkSunghyouk Bae
 
Whats new in .NET for 2019
Whats new in .NET for 2019Whats new in .NET for 2019
Whats new in .NET for 2019Rory Preddy
 
VUB Brussels Lecture 2019: Advanced Reflection: MetaLinks
VUB Brussels Lecture 2019: Advanced Reflection: MetaLinksVUB Brussels Lecture 2019: Advanced Reflection: MetaLinks
VUB Brussels Lecture 2019: Advanced Reflection: MetaLinksMarcus Denker
 
Intro To C++ - Class #18: Vectors & Arrays
Intro To C++ - Class #18: Vectors & ArraysIntro To C++ - Class #18: Vectors & Arrays
Intro To C++ - Class #18: Vectors & ArraysBlue Elephant Consulting
 
Esoft Metro Campus - Certificate in c / c++ programming
Esoft Metro Campus - Certificate in c / c++ programmingEsoft Metro Campus - Certificate in c / c++ programming
Esoft Metro Campus - Certificate in c / c++ programmingRasan Samarasinghe
 

Similar to Connect.Tech- Enhancing Your Workflow With Xcode Source Editor Extensions (20)

What’s new in .NET
What’s new in .NETWhat’s new in .NET
What’s new in .NET
 
Striking a Balance With UI Tests - ConnectTech
Striking a Balance With UI Tests - ConnectTechStriking a Balance With UI Tests - ConnectTech
Striking a Balance With UI Tests - ConnectTech
 
Presentation 5th
Presentation 5thPresentation 5th
Presentation 5th
 
Introduction to Elixir
Introduction to ElixirIntroduction to Elixir
Introduction to Elixir
 
C sharp 8.0 new features
C sharp 8.0 new featuresC sharp 8.0 new features
C sharp 8.0 new features
 
C sharp 8.0 new features
C sharp 8.0 new featuresC sharp 8.0 new features
C sharp 8.0 new features
 
What's new in c# 8.0
What's new in c# 8.0What's new in c# 8.0
What's new in c# 8.0
 
C++ Functions
C++ FunctionsC++ Functions
C++ Functions
 
Building Kafka Connectors with Kotlin: A Step-by-Step Guide to Creation and D...
Building Kafka Connectors with Kotlin: A Step-by-Step Guide to Creation and D...Building Kafka Connectors with Kotlin: A Step-by-Step Guide to Creation and D...
Building Kafka Connectors with Kotlin: A Step-by-Step Guide to Creation and D...
 
Kotlin coroutines and spring framework
Kotlin coroutines and spring frameworkKotlin coroutines and spring framework
Kotlin coroutines and spring framework
 
Whats new in .NET for 2019
Whats new in .NET for 2019Whats new in .NET for 2019
Whats new in .NET for 2019
 
VUB Brussels Lecture 2019: Advanced Reflection: MetaLinks
VUB Brussels Lecture 2019: Advanced Reflection: MetaLinksVUB Brussels Lecture 2019: Advanced Reflection: MetaLinks
VUB Brussels Lecture 2019: Advanced Reflection: MetaLinks
 
Intro To C++ - Class #18: Vectors & Arrays
Intro To C++ - Class #18: Vectors & ArraysIntro To C++ - Class #18: Vectors & Arrays
Intro To C++ - Class #18: Vectors & Arrays
 
Next .NET and C#
Next .NET and C#Next .NET and C#
Next .NET and C#
 
Python_Functions_Unit1.pptx
Python_Functions_Unit1.pptxPython_Functions_Unit1.pptx
Python_Functions_Unit1.pptx
 
Functions
FunctionsFunctions
Functions
 
C
CC
C
 
Esoft Metro Campus - Certificate in c / c++ programming
Esoft Metro Campus - Certificate in c / c++ programmingEsoft Metro Campus - Certificate in c / c++ programming
Esoft Metro Campus - Certificate in c / c++ programming
 
Presentation c++
Presentation c++Presentation c++
Presentation c++
 
C++ basics
C++ basicsC++ basics
C++ basics
 

Recently uploaded

Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Matt Ray
 
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Natan Silnitsky
 
Sending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdfSending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdf31events.com
 
20240415 [Container Plumbing Days] Usernetes Gen2 - Kubernetes in Rootless Do...
20240415 [Container Plumbing Days] Usernetes Gen2 - Kubernetes in Rootless Do...20240415 [Container Plumbing Days] Usernetes Gen2 - Kubernetes in Rootless Do...
20240415 [Container Plumbing Days] Usernetes Gen2 - Kubernetes in Rootless Do...Akihiro Suda
 
UI5ers live - Custom Controls wrapping 3rd-party libs.pptx
UI5ers live - Custom Controls wrapping 3rd-party libs.pptxUI5ers live - Custom Controls wrapping 3rd-party libs.pptx
UI5ers live - Custom Controls wrapping 3rd-party libs.pptxAndreas Kunz
 
Comparing Linux OS Image Update Models - EOSS 2024.pdf
Comparing Linux OS Image Update Models - EOSS 2024.pdfComparing Linux OS Image Update Models - EOSS 2024.pdf
Comparing Linux OS Image Update Models - EOSS 2024.pdfDrew Moseley
 
Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Andreas Granig
 
Simplifying Microservices & Apps - The art of effortless development - Meetup...
Simplifying Microservices & Apps - The art of effortless development - Meetup...Simplifying Microservices & Apps - The art of effortless development - Meetup...
Simplifying Microservices & Apps - The art of effortless development - Meetup...Rob Geurden
 
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...OnePlan Solutions
 
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)jennyeacort
 
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...OnePlan Solutions
 
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfGOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfAlina Yurenko
 
Powering Real-Time Decisions with Continuous Data Streams
Powering Real-Time Decisions with Continuous Data StreamsPowering Real-Time Decisions with Continuous Data Streams
Powering Real-Time Decisions with Continuous Data StreamsSafe Software
 
Cloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEECloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEEVICTOR MAESTRE RAMIREZ
 
Unveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsUnveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsAhmed Mohamed
 
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...Angel Borroy López
 
英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作qr0udbr0
 
How to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationHow to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationBradBedford3
 
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanySuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanyChristoph Pohl
 
MYjobs Presentation Django-based project
MYjobs Presentation Django-based projectMYjobs Presentation Django-based project
MYjobs Presentation Django-based projectAnoyGreter
 

Recently uploaded (20)

Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
Open Source Summit NA 2024: Open Source Cloud Costs - OpenCost's Impact on En...
 
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
Taming Distributed Systems: Key Insights from Wix's Large-Scale Experience - ...
 
Sending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdfSending Calendar Invites on SES and Calendarsnack.pdf
Sending Calendar Invites on SES and Calendarsnack.pdf
 
20240415 [Container Plumbing Days] Usernetes Gen2 - Kubernetes in Rootless Do...
20240415 [Container Plumbing Days] Usernetes Gen2 - Kubernetes in Rootless Do...20240415 [Container Plumbing Days] Usernetes Gen2 - Kubernetes in Rootless Do...
20240415 [Container Plumbing Days] Usernetes Gen2 - Kubernetes in Rootless Do...
 
UI5ers live - Custom Controls wrapping 3rd-party libs.pptx
UI5ers live - Custom Controls wrapping 3rd-party libs.pptxUI5ers live - Custom Controls wrapping 3rd-party libs.pptx
UI5ers live - Custom Controls wrapping 3rd-party libs.pptx
 
Comparing Linux OS Image Update Models - EOSS 2024.pdf
Comparing Linux OS Image Update Models - EOSS 2024.pdfComparing Linux OS Image Update Models - EOSS 2024.pdf
Comparing Linux OS Image Update Models - EOSS 2024.pdf
 
Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024
 
Simplifying Microservices & Apps - The art of effortless development - Meetup...
Simplifying Microservices & Apps - The art of effortless development - Meetup...Simplifying Microservices & Apps - The art of effortless development - Meetup...
Simplifying Microservices & Apps - The art of effortless development - Meetup...
 
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
Maximizing Efficiency and Profitability with OnePlan’s Professional Service A...
 
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)
Call Us🔝>༒+91-9711147426⇛Call In girls karol bagh (Delhi)
 
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
Tech Tuesday - Mastering Time Management Unlock the Power of OnePlan's Timesh...
 
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdfGOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
GOING AOT WITH GRAALVM – DEVOXX GREECE.pdf
 
Powering Real-Time Decisions with Continuous Data Streams
Powering Real-Time Decisions with Continuous Data StreamsPowering Real-Time Decisions with Continuous Data Streams
Powering Real-Time Decisions with Continuous Data Streams
 
Cloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEECloud Data Center Network Construction - IEEE
Cloud Data Center Network Construction - IEEE
 
Unveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML DiagramsUnveiling Design Patterns: A Visual Guide with UML Diagrams
Unveiling Design Patterns: A Visual Guide with UML Diagrams
 
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
Alfresco TTL#157 - Troubleshooting Made Easy: Deciphering Alfresco mTLS Confi...
 
英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作英国UN学位证,北安普顿大学毕业证书1:1制作
英国UN学位证,北安普顿大学毕业证书1:1制作
 
How to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion ApplicationHow to submit a standout Adobe Champion Application
How to submit a standout Adobe Champion Application
 
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte GermanySuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
SuccessFactors 1H 2024 Release - Sneak-Peek by Deloitte Germany
 
MYjobs Presentation Django-based project
MYjobs Presentation Django-based projectMYjobs Presentation Django-based project
MYjobs Presentation Django-based project
 

Connect.Tech- Enhancing Your Workflow With Xcode Source Editor Extensions

  • 1. Enhancing Your Workflow with Xcode Source Editor Extensions By: Jesse Black Software Engineer stable|kernel
 jesse.black@stablekernel.com
  • 2. @stablekernel Hi, I’m Jesse Black. • Programming for over eight years • Created a Mac App for my family business • Worked for 3 years with Gramercy Consultants developing iOS and Android apps • Working for stable|kernel for the past 3 years developing iOS apps, Android apps and their supporting APIs
  • 3. We’re stable|kernel. stable|kernel is an Atlanta-based mobile development company 
 to craft smartly-designed mobile applications that connect brands 
 directly with their users. 
 

  • 4. Enhancing Your Workflow with Xcode Source Editor Extensions @stablekernel Overview Mac App Extensions Xcode Source Editor Extensions Demo: Create Source Editor Extension and debugging it XC Classes Example: JSON formatter Demo: JSON formatter in action
  • 5. Mac App Extensions @stablekernel • Mac App Extensions • Affect the user experience of other apps • Need to be lightweight and run fast • Require user interaction in order to be run • Distribute via host app
  • 6. Why use Xcode Source Editor Extensions @stablekernel • Less context switching • It is too fun to customize your workflow
  • 7. Xcode Source Editor Extensions @stablekernel • Differences with general Mac App Extensions • Extensions are installed by just putting the host application in your applications folder • Only works with one type of target application, which is Xcode • Doesn’t have UI
  • 8. Xcode Source Editor Extensions @stablekernel • Allows you to add custom commands under Xcode’s Editor menu • Commands can manipulate text and text selections • Users can put bind keyboard shortcuts to invoke your commands
  • 9. Limitations to Xcode Source Editor Extensions @stablekernel • Can only start with user interaction • Lack of ability to integrate into the build process and archive process. It is for modifying source code while it is being edited.
  • 10. Expectations of Xcode Source Editor Extensions @stablekernel • Fast start up • Fast execution • Security and Stability
  • 11. Demo @stablekernel Overview Create Source Editor Extension How to install How to debug How to uninstall
  • 12. Defining Commands @stablekernel • Command Identifier • Class Name • Command Name Commands can be defined in the Extension’s plist or by supplying a dictionary at runtime. Commands provided at runtime override commands defined in the plist.
  • 13. XC Source Editor Extension @stablekernel func extensionDidFinishLaunching() {} var commandDefinitions: [[XCSourceEditorCommandDefinitionKey: Any]] {}
  • 14. XC Source Editor Command @stablekernel func perform(with invocation: XCSourceEditorCommandInvocation, completionHandler: @escaping (Error?) -> Void ) -> Void {
  • 15. XC Source Editor Command @stablekernel • Modify text, text selection • Exit early with an error message that is displayed in Xcode
  • 16. XC Source Editor Command Invocation @stablekernel • Encapsulates all details needed to fulfill the user’s request • contentUTI • usesTabsForIndentation • indentationWidth • tabWidth • buffer
  • 17. XC Source Text Buffer @stablekernel • completeBuffer • lines • selections • defined in terms of lines and columns
  • 18. Example: JSON formatter @stablekernel • Define minify and prettify commands • Implement XCSourceEditorCommand’s perform method • Validate requirements for command • Get first text selection • Return error if selected text isn’t valid JSON • Use JSONSerialization class to format text • Replace selected text
  • 19. XCSourceEditorExtension @stablekernel var commandDefinitions: [[XCSourceEditorCommandDefinitionKey: Any]] { return [ [ .classNameKey: "JeSON.SourceEditorCommand", .identifierKey: JeSONInvocation.Minify.rawValue, .nameKey: "Minify" ], [ .classNameKey: "JeSON.SourceEditorCommand", .identifierKey: JeSONInvocation.Prettify.rawValue, .nameKey: "Prettify" ], ] }
  • 20. XCSourceEditorExtension @stablekernel enum JeSONInvocation: String { case Prettify = "com.jesseblack.HelloWorldProject.JeSON.Prettify" case Minify = "com.jesseblack.HelloWorldProject.JeSON.Minify" }
  • 21. @stablekernel func textAtSelectionIndex(_ at: Int, buffer: XCSourceTextBuffer) -> String { let textRange = buffer.selections[at] as! XCSourceTextRange let selectionLines = buffer.lines.enumerated().filter { (offset, element) -> Bool in return offset >= textRange.start.line && offset <= textRange.end.line }.map { return $1 } return selectionLines.enumerated().reduce("") { (result, enumeration) -> String in let line = enumeration.element as! String if enumeration.offset == 0 && enumeration.offset == selectionLines.count - 1 { let startIndex = line.index(line.startIndex, offsetBy: textRange.start.column) let endIndex = line.index(line.startIndex, offsetBy: textRange.end.column + 1) return result + line.substring(with: startIndex..<endIndex) } else if enumeration.offset == 0 { let startIndex = line.index(line.startIndex, offsetBy: textRange.start.column) return result + line.substring(from: startIndex) } else if enumeration.offset == selectionLines.count - 1 { let endIndex = line.index(line.startIndex, offsetBy: textRange.end.column + 1) return result + line.substring(to: endIndex) } return result + line } }
  • 22. @stablekernel func replaceTextAtSelectionIndex(_ at: Int, replacementText: String, buffer: XCSourceTextBuffer) { let textRange = buffer.selections[at] as! XCSourceTextRange let lastLine = buffer.lines[textRange.end.line] as! String let endIndex = lastLine.index(lastLine.startIndex, offsetBy: textRange.end.column+1) let suffix = lastLine.substring(from: endIndex) let firstLine = buffer.lines[textRange.start.line] as! String let startIndex = firstLine.index(firstLine.startIndex, offsetBy: textRange.start.column) let prefix = firstLine.substring(to: startIndex) let range = NSMakeRange(textRange.start.line, textRange.end.line - textRange.start.line + 1) buffer.lines.removeObjects(in: range) buffer.lines.insert(prefix+replacementText+suffix, at: textRange.start.line) let newRange = XCSourceTextRange(start: textRange.start, end: textRange.start) buffer.selections.setArray([newRange]) }
  • 23. Performing the command @stablekernel func perform(with invocation: XCSourceEditorCommandInvocation, completionHandler: @escaping (Error?) -> Void ) -> Void { guard let jeSONInvocation = JeSONInvocation(rawValue: invocation.commandIdentifier) else { let errorInfo = [NSLocalizedDescriptionKey: "Command not recognized"] completionHandler(NSError(domain: "", code: 0, userInfo: errorInfo)) return } let buffer = invocation.buffer guard buffer.selections.count == 1 else { let errorInfo = [NSLocalizedDescriptionKey: "Command only handles 1 selection at a time"] completionHandler(NSError(domain: "", code: 0, userInfo: errorInfo)) return }
  • 24. Performing the command @stablekernel // perform continued let selectedText = textAtSelectionIndex(0, buffer: buffer) let data = selectedText.data(using: .utf8) do { let jsonObject = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions()) switch jeSONInvocation { case .Minify: let miniData = try! JSONSerialization.data(withJSONObject: jsonObject, options: JSONSerialization.WritingOptions()) let string = String.init(data: miniData, encoding: .utf8)! replaceTextAtSelectionIndex(0, replacementText: string, buffer: buffer) case .Prettify: let miniData = try! JSONSerialization.data(withJSONObject: jsonObject, options: .prettyPrinted) let string = String.init(data: miniData, encoding: .utf8)! replaceTextAtSelectionIndex(0, replacementText: string, buffer: buffer) } } catch { completionHandler(error) } completionHandler(nil) }
  • 26. Questions? Business Inquiries: Sarah Woodward Director of Business Development sarah.woodward@stablekernel.com Jesse Black Software Engineer jesse.black@stablekernel.com blog.stablekernel.com @JesseBlack82 http://www.slideshare.net/stablekernel https://github.com/JesseBlack82/HelloExtensions