Source code

IOS 10 Day By Day: Xcode Source Editor Extensions ios

Share the hottest information

 63.jpg


In Xcode 8.0, Apple has introduced a new MacOS oriented App Extension called Xcode Source Editor. Through this source code editor, we also have the ability to write an Xcode plug-in ourselves. In addition, we no longer need to find various ways to make Alcatraz work properly because of the Xcode upgrade.

brief introduction

Xcode is an IDE that developers love and hate in Apple's development platform. During the use, we found that the number of Xcode plug-ins has always been in short supply. Developers can add some functions as extensions of built-in functions. For example, check spelling or convert all UIColors to use new constants.

Before Xcode 8, Xcode did not have this capability. So Alcatraz fills in the gap. It seems that the Xcode plug-in manager is Alcatraz Later, because of security and stability concerns, we used Xcode 8 for development. We can no longer use Alcatraz. Fortunately, Apple has added a new source code editor to extend the plug-in functions of Xcode.

project

We create an extension to replace ASCII characters as emoticons. For example, "That's a nice thing to say:

 Emojificator.gif

Like I was Day1 Like the iMessage App created in, the various extensions launched by Apple this time are similar to Xcode Extensions, but the biggest advantage of this official Xcdoe plug-in is that it can be launched on the Mac App Store. We can use Extension to extend the whole program. It sounds a bit exaggerated, but it is actually more like a configuration option. Xcode provides a menu option without UI to run a command.

Next, we will create a new MacOS project named Emojificate. Here, we can ignore the files related to Mac app and focus on extension.

We need to create a new target and choose the Xcode Extension. We also need to choose a unique name. The name I use here is Emojificator_Extension.

 Project_Name.png

Xcode creates everything we need.

Info.plist

To change the extension name, we just need to set the key value of the Bundle name to Emojificator.

 MenuItem.png

Like other extensions, we can set some attributes in info.plist. We expand NSExtension. Below, we can define the extension type (Xcode. extension. source editor) and the plug-in class name. The key name is XCSourceEditorExtensionPrincipalClass. You will find that in our project, the class name is SourceEditorExtension. We can also define the commands that users can execute in the extension.

Your extension can also contain a large number of command lines, and we can specify their order in info.plist. In our project, we only have one command line, which is defined in the class of EmojificatorCommand and contains the protocol of XCSourceEditorCommand. If we want to define the name of this class, we need to modify the value of XCSourceEditorCommandClassName.

This class does not limit the number of command lines to run. If you have multiple command lines to execute, they can all be placed in the same class. If there are the same methods, you can also extract them for public use. Generally, we distinguish different commands by identifying them (that is, the value corresponding to the key XCSourceEditorCommandIdentifier).

Finally, let's talk briefly about modifying the name of the command line. In our project, XCSourceEditorCommandClassName corresponds to Emojificate!, By modifying the corresponding key, we can modify the name of the command line.

 Extension_Attributes_Plist.png

SourceEditorExtension.swift
This file must comply with the XCSourceEditorExtension protocol. After we set our plist file, we don't need to do anything. The system has already initialized it for us. If you want to customize initialization, you need to customize initialization in the extensionDidFinishLaunching method.

When Xcode starts, the extension will start. When the command is executed, the extension is only executed. The advantage of doing this is, quick!

Menu items are dynamically loaded and can implement the commandDefinitions: of SourceEditorExtension, but this will overwrite the definitions in Info.plist.

For example, the following code will return the same configuration as the current project.

 var commandDefinitions: [[XCSourceEditorCommandDefinitionKey: AnyObject]] {     // If your extension needs to return a collection of command definitions that differs from those in its Info.plist, implement this optional property getter.     return [[         .classNameKey : "Emojificator_Extension.EmojificateCommand",         .identifierKey : "com.shinobicontrols.Emojificator_Extension.EmojificateCommand",         .nameKey : "Emojificate!"     ]] }

EmojificatorCommand.swift

Usually, Xcode will create a SourceEditorCommand class, but here I rename it EmojificateCommand. To ensure consistency with the system, we must ensure that it complies with XCSourceEditorCommon

Agreement for.

 import Foundation import XcodeKit class EmojificateCommand: NSObject, XCSourceEditorCommand { }

For example, we defined the mapping between a set of expressions and ASCII, and only used the defined expressions.

 let asciiToEmojiMap = [         ":)" : ":)",         ";)" : ";)",         ":(" : ":("]   *Note: Use actual emojis in second column

To replace ASCII characters with Emoji expressions, we need to use two methods

 extension EmojificateCommand {     /// Returns whether the string contains an item that can be converted into emoji     func replaceableItemsExist(in string: String) -> Bool {         for asciiItem in asciiToEmojiMap.keys {             if string.contains(asciiItem) {                 return true             }         }         return false     }     /// Replaces any ASCII items with their emoji counterparts and returns the newly 'emojified' string     func replaceASCIIWithEmoji(in string: String) -> String {         var line = string         for asciiItem in asciiToEmojiMap.keys {             line = line.replacingOccurrences(of: asciiItem, with: asciiToEmojiMap[asciiItem]!)         }         return line     } }

Finally, we implement the 'perform (with: completionHandler:)' method in the. m file to call it when the xcode command line is executed.

 func perform(with invocation: XCSourceEditorCommandInvocation, completionHandler: (Error?) -> Void) {     let lines = invocation.buffer.lines     for (index, line) in lines.enumerated() {        if let line = line as?  String,            replaceableItemsExist(in: line) {            lines[index] = replaceASCIIWithEmoji(in: line)        }     }     // Command must perform completion to signify it has completed     completionHandler(nil) }

In the 'perform (with: completionHandler:)' method, we have an invocation variable. The type is XCSourceEditorCommandInvocation, which is the file content called by the command, such as. swift file, oc header file, or space and other characters. What we need to do is to obtain the data we want in the buffer according to the current row. We can also use 'completeBuffer', which can be a string or an array. If you just modify some characters, Apple recommends using arrays to process them, because Xcode performs better on arrays.

Finally, we call completionHandler (nil) to tell Xcode that the command has been executed.
Xcode Extension runs in a separate process, which is really excellent. This means that the slow execution of the command line will not affect the use of Xcode itself. Another thing worth noting is that Xcode is extremely strict with the time required for the command to run. If it is not completed in a short time, your extension will be called and criticized. At the same time, users can choose to cancel the command.

Run "Emojificate"

What's different from our normal development is that Xcode can test our commands in the test version. The icon color of Xcode in this test version is gray, which helps us distinguish the development content.

 88.png

The following is the effect picture of the execution:

 89.gif

more

This move by Apple will certainly greatly expand the developer ecosystem and improve the efficiency of developers. When executing these commands, only the buffer and sandbox of some files can be modified by default. If you need, you can request higher permissions. As far as I know, Xcode engineers will make this tool more powerful in the future, so if you have some specific goals that cannot be achieved, you can also submit your use cases to Apple.

For details, see WWDC Video Introduction to.

Ji Changxin is responsible for ios learning from beginner to proficient

fabulous ( zero )

This article is written by Ji Changxin Author, article address: https://blog.isoyu.com/archives/1713.html
use Knowledge Sharing Attribution 4.0 International License Agreement. Unless the reprint/source is indicated, they are all original or translated by this website. Please sign your name before reprinting. Last editing time: December 14, 2016 at 12:34 p.m

Popular articles

Post reply

[Required]

I am a human?

Please wait three seconds after submission to avoid unsubmission and repetition