TextExpander 4.0

TextExpander 4.0

测试已测试
Lang语言 Obj-CObjective C
许可证 商业版
发布最新版本2016年8月

Maintained by Donald Burr.



  • SmileOnMyMac

TextExpander touch SDK

(发布说明在本文档底部。)

Smile 提供TextExpander框架,以便您可以在iOS应用、自定义键盘或扩展中包含TextExpander功能,但需遵守下面的许可协议。

TextExpander touch SDK首页

TextExpander touch首页

填空教程

Google Group tetouch-sdk(用于公告)

TextExpanderDemoApp项目是一个工作示例应用,展示了如何将TextExpander功能添加到您的应用和自定义键盘中。

如何将TextExpander添加到您的iOS应用

从GitHub获取最新的TextExpander touch SDK

  1. 启动终端
  2. 将目录更改为您想下载SDK的目录
  3. 运行此命令
git clone https://github.com/SmileSoftware/TextExpanderTouchSDK

构建示例项目

TextExpanderDemoApp是一个iPhone应用,它展示了如何通过其设置视图获取/更新片段数据,如何在UITextField、UITextView、UISearchBar、UIWebView和一个自定义键盘中使用TextExpander。它包括一个常规的网页视图和一个可编辑内容的网页视图。它不是一个模型iOS应用。它的目的是演示TextExpander功能,以便您可以在上下文中看到它并轻松将其采用到您的应用中。

  1. 从App Store下载 TextExpander
  2. 从第一步打开TextExpanderTouchSDK文件夹
  3. 双击TextExpanderDemoApp.xcodeproj或TextExpanderDemoAppSwift.xcodeproj在Xcode中打开示例项目
  4. 选择Product -> Run来运行示例
  5. 点击“设置”
  6. 启用“使用TextExpander”
  7. 点击“获取片段”以从TextExpander获取片段
  8. 点击在“视图”中放置片段,例如“ddate”或“sig1”

注意:要关闭键盘,请点击文本框左端或右端的空白处。

将TextExpander添加到您的项目

  1. 将TextExpander.framework拖放到您的项目中
  2. 选择您应用的target
  3. 点击“Info”
  4. 滚动到“Linked Frameworks and Libraries”
  5. 将您项目中的TextExpander.framework拖到该列表中
  6. 如果您的项目尚未包含以下框架,请使用+添加它们
  7. AudioToolbox.framework
  8. CoreGraphics.framework
  9. CoreText.framework
  10. Foundation.framework
  11. JavaScriptCore.framework
  12. UIKit框架

将TextExpander添加到您的视图中

TextExpander可与以下视图协同工作

  • UITextView
  • UITextField
  • UISearchBar
  • UIWebView

Objective-C: 1. 将TextExpander头文件导入您的视图控制器头文件中

#import "SMTEDelegateController.h"
2. 在您的视图控制器中添加一个SMTEDelegateController
@property (nonatomic, strong) SMTEDelegateController *textExpander;
3. 在您的视图控制器中viewDidLoad方法中,初始化SMTEDelegateController并将其设置为您的视图的代理
self.textExpander = [[SMTEDelegateController alloc] init];
[self.textView setDelegate:self.textExpander];
[self.textExpander setNextDelegate:self];

Swift: 1. 将TextExpander模块导入您的视图控制器类中

import TextExpander
2. 在您的视图控制器中添加一个SMTEDelegateController
var textExpander: SMTEDelegateController?
3. 在您的视图控制器的viewDidLoad方法中,初始化SMTEDelegateController并将其设置为您的视图的代理
self.textExpander = SMTEDelegateController(); self.textView!.delegate = self.textExpander

禁用TextExpander自定义键盘扩展

TextExpander 3和4附带了自定义键盘,可以在输入时扩展TextExpander缩写。

自定义键盘不支持富文本,并且其界面有限,无法支持填充功能。

如果您的应用实现了SDK,您可能希望禁用TextExpander自定义键盘扩展以获得最佳用户体验。

要禁用TextExpander自定义键盘扩展,您将在Darwin通知“com.smileonmymac.tetouch.keyboard.viewWillAppear”中添加监听器,并在该监听器中调用[SMTEDelegateController setCustomKeyboardExpansionEnabled:NO]。以下是一个示例

    int status = notify_register_dispatch("com.smileonmymac.tetouch.keyboard.viewWillAppear",
                                          &SMAppDelegateCustomKeyboardWillAppearToken,
                                          dispatch_get_main_queue(), ^(int t) {
                                              [SMTEDelegateController setCustomKeyboardExpansionEnabled:NO];
                                          });

还有一个相应的“com.smileonmymac.tetouch.keyboard.viewWillDisappear”通知。注册该通知以重新启用扩展不是必要的。

如果您使用Swift编写,您需要使用Objective-C来完成此操作。请在TextExpanderDemoApp.xcodeproj中的SMSwiftWorkarounds.h、SMSwiftWorkarounds.m和TextExpanderDemoAppSwift-Bridging-Header.h中查看如何进行此操作的示例。

将TextExpander添加到您的自定义键盘或其他扩展中

包含您的扩展(“包含应用”)的应用将不得不从TextExpander获取片段数据(请参阅以下“获取/更新片段数据”)。

您的包含应用和您的扩展都必须在其Xcode目标的Info部分中启用App Group功能,并且它们必须共享一个相同名称的应用组。您可以在TextExpanderDemoApp项目和它的自定义键盘中看到这个示例。

  1. 将TextExpander头文件导入您的视图控制器头文件中
    #import "SMTEDelegateController.h"
  2. 将SMTEDelegateController添加到您的视图控制器的子类中
    @property (nonatomic, strong) SMTEDelegateController *textExpander;
  3. 在您的视图控制器的viewDidLoad方法中,初始化SMTEDelegateController并设置其appGroupIdentifier
    self.textExpander = [[SMTEDelegateController alloc] init];
    self.textExpander.appGroupIdentifier = @"";
  4. 按照以下描述,在您的包含应用中实现获取/更新片段数据

TextExpander SDK将调用[NSFileManager containerURLForSecurityApplicationGroupIdentifier:appGroupIdentifier]来获取您的应用组容器,并从:Library/Application Support/TextExpander中的附加路径组件中存储和检索其片段数据,如果需要,创建文件夹。

自定义键盘不会使用视图和代理方法。它将通过以下方式与TextExpander交互

[SMTEDelegateController stringByExpandingAbbreviations:stringToExpand cursorPosition:&cursorPosition options:expansionOptions];

此方法通过在用户使用光标定位扩展片段时返回光标在扩展文本中的索引来扩展上述stringByExpandingAbbreviations:方法。

TextExpanderDemoApp包括一个自定义键盘目标,用作在自定义键盘中支持TextExpander的示例。要将自定义键盘添加到示例应用中

  1. 选择TextExpanderDemoApp目标,然后在它的构建阶段标签中添加DemoAppKeyboard作为目标依赖项
  2. 在TextExpanderDemoApp目标中,设置代码签名权限为TextExpanderDemoApp/TextExpanderDemoApp.Entitlements
  3. 在developer.apple.com上,您需要执行以下操作,但是用我们的示例中的您的ID替换
  4. 创建一个App Group(例如,group.com.smileonmymac.textexpander.demoapp)
  5. 创建一个App ID(例如,com.smileonmymac.TextExpanderDemoApp)
  6. 编辑App ID以添加App Group
  7. 为开发创建一个配置文件,下载它,然后将它拖放到Xcode中
  8. 为键盘创建另一个App ID(例如:com.smileonmymac.TextExpanderDemoApp.DemoAppKeyboard)
  9. 编辑App ID以添加App Group
  10. 为开发创建一个配置文件,下载它,然后将它拖放到Xcode中
  11. 选择TextExpanderDemoApp目标,在其功能选项卡中开启App组,并检查适当的组
  12. 选择DemoAppKeyboard目标,在其功能选项卡中开启App组,并检查适当的组
  13. 选择TextExpanderDemoApp目标,在其构建阶段选项卡中,将DemoAppKeyboard添加到嵌入式应用程序扩展
  14. 在SMFirstViewController、SMSecondViewController、SMThirdViewController和KeyboardViewController中更改appGroupIdentifier设置,以匹配您的设置(搜索并替换@"group.com.smileonmymac.textexpander.demoapp")
  15. 运行演示应用程序,并更新其片段(以便将它们写入应用程序组容器)
  16. 添加您的键盘,并在任何应用程序中进行测试扩展

注意:在TextExpander touch中制作的片段更改不会自动对自定义键盘可用。它从容器应用程序获取片段,该容器应用程序使用以下描述的x-callback-url方法来获取和更新片段数据。

获取/更新片段数据

为了获取/更新片段数据,您的应用程序需要

  1. 提供一个URL方案,通过x-callback-url获取片段

    • 设置SMTEDelegateController的getSnippetsScheme属性
    • 在Xcode中您的应用程序的信息下“URL类型”中添加此方案
    • 在应用程序代理中实现application:openURL:sourceApplication:annotation:application:handleOpenURL:,并使用具有该方案的任何URL调用[SMTEDelegateController handleGetSnippetsURL:error:cancelFlag:](或满足以下注释中描述的条件的URL)
    • 如果cancelFlag返回为true,则用户在TextExpander中关闭了分享片段,并在提示时未允许暂时分享。如果错误不为nil,则发生了错误,您可能需要通知用户。
  2. 在您的应用程序中添加一个用户界面元素,当触摸时,通过调用- [SMTEDelegateController getSnippets]启动获取/更新片段数据

  3. 设置SMTEDelegateController的clientAppName属性,它用于在TextExpander应用程序中显示应用程序的名称,例如,当关闭分享片段以标识请求片段数据的应用程序并提供用户选择打开分享片段或取消的方式时。

示例设置

self.textExpander = [[SMTEDelegateController alloc] init];
[self.textView setDelegate:self.textExpander]; // required for expansion
[self.textExpander setNextDelegate:self]; // if you still want to receive iOS delegate messages self.textExpander.getSnippetsScheme = @"supertyper-xc"; // your URL scheme self.textExpander.clientAppName = @"SuperTyper"; // your app's name
请注意,如果您想使用现有的URL方案作为getSnippetsScheme,则可以这样做。回调URL看起来像这样
  • getSnippetsScheme://x-callback-url/TextExpanderSettings[更多内容]

为了区分您的应用程序收到的其他URL调用,检查URL中是否存在x-callback-url主机以及URL路径前缀为/TextExpander,以确定给定的URL是否是针对您URL方案的片段数据回调。

为了提供有关TextExpander数据当前状态的用户信息,您可以使用expansionStatusForceLoad:snippetCount:loadDate:error:获取最后检索的片段设置的修改日期,或找到尚未检索片段设置。

请注意,当启动TextExpander touch时,您的应用程序可能无法卸载。您可能需要在调用[SMTEDelegateController handleGetSnippetsURL:]之前或之后添加代码来检查应用程序的状态,并在必要时恢复它。

使用说明

  • UITextView,UITextField:实例化SMTEDelegateController并将其设置为UITextView或UITextField的代理。如果用户已指定片段的格式,则片段的文本属性会包含if (iOS >= 6.0 && theView/Field.allowsEditingTextAttributes && !SMTEDelegate.expandPlainTextOnly)
  • UIWebView:实例化SMTEDelegateController并将其设置为UIWebView的代理。如果用户已指定片段的格式,则将包括片段的文本属性if (theKeyEvent.target.value is undefined && !SMTEDelegate.expandPlainTextOnly)。也就是说,如果没有在一个<input type="text">或<textarea>中进行输入时,将允许格式设置。
  • UISearchBar:实例化SMTEDelegateController并将其设置为UISearchBar的代理
  • 要向UITextView/Field/SearchBar添加自己的委托,请在对实例调用-[SMTEDelegateController setNextDelegate:]。TextExpander有机会处理委托调用后,您的委托将被调用。在shouldChangeText/CharactersInRange:调用中,您可以通过查看SMTEDelegate.isAttemptingToExpandText来检查TextExpander是否要根据当前插入的字符(复数)扩展片段。返回NO将阻止该片段扩展。
  • 单个SMTEDelegateController可以服务多个UITextView、UITextFields、UIWebView和UISearchBar。如果您为多个视图或字段使用setNextDelegate,请务必测试传递给您的代理的视图或字段,并相应地做出反应。
  • 查看示例应用程序的文件SMFirstViewController.m和SMSecondViewController.m,以查看所有这些示例。

处理属性文本

从iOS 6开始,UITextView和UITextField都实现了属性文本属性。即使您的应用保持视图/字段的文本格式相同,文本扩展器也没有办法知道这一点,因此,为了保留执行扩展时的任何格式,它将片段文本插入到类 NotreAttributedString的副本中,然后调用setAttributedText

但是,setAttributedText:有一些不可取的撤消/重做副作用:-它清除撤消状态(与setText:不同)-在撤消或重做操作期间调用时会导致死机

如果您的UITextView不提供allowsEditingTextAttributes,则文本扩展器将只扩展片段的“纯文本”版本,但如上所述,它使用setAttributedText:保留现有的格式。为了避免调用setAttributedText:,您可以子类化UITextView或UITextField并实现这些两个方法

- (NSAttributedString\*)textExpanderAttributedString;
- (void)textExpanderSetAttributedString: (NSAttributedString\*)newText;

从SDK版本2.0.1开始,如果您的UITextView/Field实现了这些方法,文本扩展器将首选这些方法而不是attributedText/setAttributedText:

在最简单的情况下,如果您的视图具有相同的格式,这些方法可以非常简单

-(NSAttributedString\*)textExpanderAttributedString {
    return self.attributedText;
}
-(void)textExpanderSetAttributedString: (NSAttributedString\*)newText {
    self.text = [newText string];
}

(注意:为了避免在执行片段扩展撤消时使用setAttributedText:时锁定,文本扩展器使用dispatch_async(dispatch_get_main_queue(), ^{ blah setAttributedText: changedText });

支持填充片段

上述说明支持正常片段,其中用户键入的缩写字符立即扩展到片段内容。TEtouch 2.0及以上版本还支持填充片段。填充允许用户设置一个更长的片段,其中嵌入一个或多个变量字段,可以是文本字段、条件包含部分和弹出菜单以选择所选选项。

填充过程涉及到使用x-callback URLs(感谢Agile Tortoise的Greg Pierce!)切换到TextExpander touch应用程序,在那里用户填写字段值,然后切换回您的应用程序,在那里完成文本将被插入。

要支持填充片段,您的应用程序需要

  1. 提供一个通过x-callback-url完成填充片段的URL方案。(如果为nil将避免填充过程,片段中的%fill%宏将被(field名称)替换)
    1. 设置SMTEDelegateController的fillCompletionScheme属性(可能和getSnippetsScheme一样)
    2. 将方案添加到Xcode中您的应用程序的“Info”标签下的“URL类型”(如果没有使用现有的URL方案--参见以下说明)
    3. 在您的应用程序代理中实现application:openURL:sourceApplication:annotation:application:handleOpenURL:,并通过SMTEDelegateController的handleFillCompletionURL:方法调用任何具有该方案的URL(或符合以下备注中描述的条件的URL)
  2. 实现SMTEFillDelegate协议以允许SDK将第一个响应者状态返回给正确的文本项,以便通过设置SMTEDelegateController的fillDelegate属性为您的SMTEFillDelegate实现对象来插入完成的填充片段

继续上述示例设置

self.textExpander = [[SMTEDelegateController alloc] init];
[self.textView setDelegate:self.textExpander];  // required for expansion
[self.textExpander setNextDelegate:self]; // if you still want to receive iOS delegate messages
self.textExpander.getSnippetsScheme = @"supertyper-xc"; // required to fetch snippets
self.textExpander.clientAppName = @"SuperTyper"; // required to fetch snippets
self.textExpander.fillCompletionScheme = @"supertyper-xc"; // to handle fill-in callback

注意,如果您想使用现有的URL方案作为填充完成方案,您完全可以这样做。回调URL看起来像这样

  • fillCompletionScheme://x-callback-url/SMTEfilled?textID=[文本区域ID]&loc=[文本中的偏移]&format=[1|0]
  • 上述示例可能包含:&cursorPos=[调整计数]&selLen=[如果不为空则选择范围]
  • fillCompletionScheme://x-callback-url/SMTEfillcanceled?textID=[文本区域ID]&loc=[文本中的偏移]
  • fillCompletionScheme://x-callback-url/SMTEerror?textID=[文本区域ID]&loc=[文本中的偏移]&error-Code=NN&errorMessage=bad+thing+happened

因此,您可以轻松地检查URL中是否存在x-callback-url作为URL主机和/SMTE作为URL路径的前缀,以确定给定的URL是否是针对您的URL方案的填充回调。

SMTEFillDelegate协议的主要目的是在填充过程中,TEtouch应用被激活。由于您的应用暂时失去焦点,iOS可能会卸载您的应用,因此为了在您的应用中正确位置插入填充的片段文本,您必须重新激活文本区域并告诉TE的SDK。SDK将在片段激活的偏移处插入填充文本。

在大多数情况下,iOS不会在用户填写字段所花费的短时间内卸载您的应用,因此您的SMTEFillDelegate的实现makeIdentifiedTextObjectFirstResponder:fillWasCanceled:cursorPosition:通常情况下,您的应用未卸载的情况下可能不需要做任何工作(不仅仅是返回适当的价值)。

如果您的应用确实被卸载,您应保存用户在触发填充片段时正在输入的文本。您的应用可能已经这样做了,但可选的prepareForFillSwitch:方法在打开TEtouch的URL之前提供保存应用状态的机会,或者返回NO以在最后时刻终止该过程。

对于UITextView、UITextField和UISearchBar,SMTEFillDelegate方法很简单。您可以创建一些标识对象的名称,例如"mainTextArea"。当您的应用重新聚焦并且填充的片段文本准备插入时,您只需要提供适当的UIKit对象,并在makeIdentifiedTextObjectFirstResponder:fillWasCanceled:cursorPosition的实现中使其成为第一个响应者即可。

然而,对于UIWebView,事情要复杂一些,因为UIWebView对象本身不足以指定插入的位置。在这种情况下,使用NSDictionary,因此它可以包含UIWebView以及触发填充片段的HTML元素的ID或名称。

示例应用程序包含两个不同的SMTEFillDelegate实现,并演示了如何确定应该将填充完成回调URL传递给哪个SMTEDelegateController实例。

测试备注

  • 如果您在Mac OS X上使用TextExpander,您可能需要在iPhone模拟器上进行测试时将其禁用,特别是如果您使用自己的片段,因为模拟器中的缩写可能与Mac OS X上的缩写冲突。
  • 如果您正在iOS/iPhone模拟器上运行,可以在模拟器未运行时,将GitHub上的"Simulator"文件夹中的.zip文件解压缩到您的[主目录]/Library/Developer/CoreSimulator/Devices//data/Containers/Bundle/Application文件夹中,然后TEtouch应用应出现在您的模拟器中。这允许您在模拟器中创建片段并测试填充片段。
  • 您可以通过使用以下这样的URL调用handleFillCompletionURL:方法,在SDK中启用一些诊断/调试日志:[任何方案]://x-callback-url/SMTEsetlog?log=[关闭|开启|详细] 该日志设置在您的应用启动时重置为关闭(当SDK库加载时)。
  • 如果启用了扩展功能,您可以通过输入“虚拟”片段缩写“SmileTE.status”来查看已加载的片段数据的摘要(如果有)。

支持

Smile不提供对TextExpander框架的支持承诺。如果您有任何问题,请通过电子邮件[email protected]提出。在时间和资源允许的情况下,我们将尽力回答这些问题。当然,如果您愿意在您的应用程序中添加TextExpander支持,这对我们来说是最好的利益,我们将尽力支持您。

在此仅公告的Google Group中了解TextExpander框架的新版本:[a href="https://groups.google.com/forum/#!forum/tetouch-sdk">https://groups.google.com/forum/#!forum/tetouch-sdk

许可协议

TextExpander框架归SmileOnMyMac, LLC dba Smile版权所有 © 2009-2016,按原样提供并且不提供保修。SmileOnMyMac, LLC放弃所有明示或暗示的保证,包括但不限于适销性和适用于任何目的的保证。SmileOnMyMac不对直接、间接、偶然、特殊、示范性或后果性的损害承担任何责任,即使被告知可能存在此类损害的风险。

在此特此授予免费使用、复制和分发此库的许可,但受以下限制

  1. 不得误传此库的来源
  2. 使用此库的应用程序必须在其功能集或产品描述中注明“支持TextExpander touch片段扩展”
  3. 使用此库的应用程序必须在关于框和许可协议中的上述段落中注明“包含TextExpander框架,版权所有 © 2009-2016 SmileOnMyMac, LLC dba Smile。TextExpander是Smile的注册商标”。如果对特定应用程序更合适,可以通过链接到应用开发者网站上发布的许可协议文本。

如果您的应用程序在上述限制方面有特殊需求,请通过电子邮件以具体建议为佳,通过电子邮件提出[email protected]。或许我们可以找到一个双方都满意的解决方案。

默认缩写和片段

aaddr: 123 Market Street San Francisco, CA

ddate: (天:(无前导零)) (月:(名称)) (年:(4位数))

sig1: Cheers,

Jane Smith 首席副总裁 Acme, Inc.

sig2: Yours sincerely,

Jane Smith PTA主席 苹果谷小学

sig3: (格式化文本示例) Cheers, Jane Smith 首席副总裁 Acme, Inc.

sms1: 我要迟到。很快就到。

sms2: 交通状况糟糕。我会迟到。抱歉。

sms3: 我完全忘了我们的约会。我们可以重新安排吗?

ttel 415-555-1212

tyvm: 非常感谢您!

dnthx: (填写示例) 亲爱的 %filltext:name=姓名:宽度:25%,

感谢您慷慨捐赠了 %filltext:name=金额:宽度:4% 美元。我们非常感谢您的帮助,并将使用这笔资金用于 %fillpopup:name=弹出窗口 4:默认值=我们的教育项目:我们的医疗诊所:一般目的%。

由于我们是非营利组织,您的捐赠 %filltext:name=金额:宽度:4% 应该可抵扣税款。

感谢您,

发行说明

4.0 (2016-08-12)

  • 更新以处理在macOS的TextExpander 6和iOS的TextExpander 4中引入的新HTML片段类型
  • 添加了Swift演示应用程序
    • Swift演示应用程序不是为了展示Swift最佳实践;我们欢迎拉取请求以改善它
    • 我们遇到的唯一难题是 expansionStatusForceLoad 函数不返回布尔值而是抛出异常;请参阅演示应用了解如何处理这个问题。
  • TextExpander.framework 现在是胖二进制文件,并且包括了模拟器需要的 Bitcode 以及 i386 和 x86_64 架构。
    • 注意:较老的链接器会从包含 i386 或 x86_64 架构的胖二进制框架中移除 Bitcode;请使用 Xcode 7.3.1 或 Xcode 8。

3.5.4 (2015-09-09)

  • 使用 Xcode 7 GM 版本构建,并包含了 Bitcode。
  • 另外还提供了 TextExpander.framework.fat,其中包含模拟器的 x86 架构。
  • 非常重要!您必须将 tetouch、tetouch-xc 和 tetouch-settings 添加到您的应用的 Info.plist 中的 LSApplicationQueriesSchemes,这样 SDK 才能报告 TextExpander 是否存在,并能够更新片段。

3.5.3 (2015-08-28)

  • 更新调用可以在初始化时挂起,现在使用不会挂起的调用。
  • 已将 tetouch、tetouch-xc 和 tetouch-settings 添加到演示应用的 LSApplicationQueriesSchemes 中。

3.5 (2015-05-23)

  • 片段现在可以执行 JavaScript,因此必须链接 JavaScriptCore.framework。
  • 库应该产生更少的日志消息,尤其是当用户从不检索片段的情况下。

3.0.5 (2014-12-09)

  • 解决了偏移问题,而没有重新引入关于标记文本的问题。
  • 更新模拟器包以与 TextExpander 3.2.2 匹配(等待审查)。

3.0.4 (2014-10-29)

  • 修复了在将纯文本片段扩展到属性文本对象时可能的偏移问题(如果缩写位于文本末尾,缩写的末尾可能会附加到文本上,例如 October 29, 2014ddat)。

3.0.3 (2014-09-25)

  • 修复了在 iOS 8 上启用撤消支持的情况下,在 UITextField 中输入缩写时可能发生的崩溃。

3.0.2 (2014-09-18)

  • 发布构建(与意外作为调试构建执行的 3.0.1 版本相比)。

3.0.1 (2014-09-16)

  • 修复了在 UITextField 中通过标记文本输入缩写时可能发生的崩溃。
  • 修复了在 TextView 中通过标记文本扩展缩写后可能留下额外字符的情况。

3.0 (2014-09-04)

  • 添加了对通过 TextExpander 3 自定义键盘禁用扩展的支持,以避免与 SDK 实现的应用冲突。
  • 添加了从应用组存储和检索片段的支持,以支持自定义键盘和扩展。
  • 添加了 -[SMTEDelegateController stringByExpandingAbbreviations:cursorPosition:options:] 以允许自定义键盘支持在扩展缩写时进行光标定位。
  • 添加了 +[SMTEDelegateController expansionEnabled] 来查询当前扩展状态。
  • 将自定义键盘添加到 TextExpanderDemoApp 作为示例。
  • 消除了我们用于 RTF 支持的 Omni 框架子集的命名空间冲突。
  • 包括如何将自定义键盘示例添加到 TextExpanderDemoApp 的说明。
  • 将模拟器版本更新到 3.0b7,以与公共测试版匹配。
  • 修复了 stringByExpandingAbbreviations 返回最长的缩写而不是第一个的问题。

2.3.1 (2013-12-21)

  • 修复了在加载时如果找到任何格式化的片段,iOS 5 中可能发生的崩溃。
  • 如果触发条件是 textThingShouldBeginEditing:webViewDidFinishLoad:,则将片段加载移动到异步队列(对于有多个兆字节的设置的用戶,加载可能需要几秒钟)。
  • 添加了 expansionStatusForceLoad:snippetCount:loadDate:error: 来告诉片段状态和/或强制加载片段。
  • 修复了包含 '/' 或 '.' 字符的缩写不会在 UIWebView 中扩展的bug。
  • 不再错误地提供“设置表示片段从未导入”的日志消息。
  • 如果没有设置 getSnippetsScheme,则不会进行 x-callback-url openURL 调用(TEtouch 2.3.1 更好地处理了无效的 URL)。

2.3 (2013-11-25)

  • 添加 x-callback-url 以获取和更新片段数据。
  • 删除了使用提醒来存储和检索片段数据的方法。
  • 改进了处理通过输入法/标记文本输入的缩写支持。
  • 如果键入 "SmileTE.status",它将像片段一样扩展,显示是否已加载共享片段以及可能的消息。
  • 从 pre-2.3 SDK 切换的步骤。
    1. 从您的项目中移除EventKit框架(除非您用它来做TextExpander以外的其他用途)
    2. 从您的Info.plist中移除或编辑NSRemindersUsageDescription
    3. 移除对-[SMTEDelegateController willEnterForeground]的调用
    4. 如果您已实现了填充功能,请用clientAppName替换fillForAppName
    5. 请移除任何检查访问Reminders的代码,除非您的应用程序使用Reminders进行其他用途
    6. 按照上面“获取/更新片段数据”部分的说明进行操作

2.2.1 (2013-09-27)

  • 解决在测试iPhone 5S时发现的arm64上的崩溃问题

2.2 (2013-09-25)

  • 尊重设置修改日期,因此减少重新加载,并且在扩展填充片段时从不重新加载
  • 在UIWebView消耗纯文本片段中的HTML标签时,正确定位
  • 仅在iOS 6代码在iOS 7上运行时运行与行结束相关的解决方案,因为这些问题在运行iOS 7代码时似乎已得到解决
  • 与TextExpander touch 2.2同时工作,解决了在运行非公历日历时共享片段的潜在问题
  • 不再将SGDeviceHelper包含在SDK中,这样也避免了命名空间冲突
  • 更新示例应用程序中提醒检查机制

2.1 (2013-09-10)

  • 使用EventKit将片段存储在完成的提醒中
  • 您的应用程序现在必须链接到EventKit
  • 添加了+ [SMTEDelegateController setAllowRemindersAccessRequest:],以便您可以选择允许或不允许TextExpander请求提醒访问
  • 由于现在行为不同,更新了+ [SMTEDelegateController snippetsAreShared]的描述
  • 修复了在iOS 7上运行时的多个WebKit相关问题
  • 将非扩展字符输入更新为使用[UITextInput replaceRange:withText:]而不是setText或setAttributedText,以避免干扰撤消堆栈
  • 向示例项目中添加了一些与提醒相关的代码
  • 向示例项目中添加了对UITextView绘制更新问题的解决方案

2.0.1 (2013-05-31)

  • 修复了2.0版本中存在的问题,其中在初始SDK片段加载时将忽略大小写设置为开时被忽略。片段只能以大小写敏感的方式扩展,直到切换到TEtouch并更新共享片段,从而重新加载片段并启用正确的大小写不敏感。
  • 修复了嵌入在其他片段中的填充片段无法工作的问题。
  • 修复了在UITextView中扩展时允许EditingTextAttributes==YES导致的崩溃,这是由于[UITextView.text length]比UITextView.attributedText的长度更长
  • 如果您的UITextView或UITextField实现了这两个方法:-(NSAttributedString*)textExpanderAttributedString; -(void)textExpanderSetAttributedString: (NSAttributedString*)newText; TextExpander会优先使用这些方法而不是attributedText/setAttributedText。
  • 在2.0.1之前的TEtouch版本会在TEtouch应用程序每次失去焦点时重新编写共享片段。这意味着willEnterForeground在填充片段应用切换期间重新获得焦点时重新加载片段。2.0.1使此过程更有效。

2.0 (2013-05-15)

  • 如果客户端应用程序实现了SMTEFillDelegate协议并提供URL方案,则添加对填充片段的支持。
  • 添加了对格式化文本片段的支持。
  • 添加了expandPlainTextOnly,默认情况下为NO,并在扩展/委托方法中受到尊重
  • 添加了- (NSAttributedString*)iểmelserByExpandingAbbreviations:(NSAttributedString*)inString;
  • 光标位置宏(%)现在在UITextField和HTML中工作(以前只在UITextView中工作。在UISearchBar中不可能工作。)
  • 添加了对选择范围宏的支持(即 "%|选择此文本%\ ")
  • 修复了在扩展后光标会跳转到UITextField开头的问题
  • 修复了在剪贴板的选择范围或前一次扩展后立即扩展的问题
  • stringByExpandingAbbreviations:现在返回一个自动释放的字符串(以前返回一个保留的字符串)
  • 修复了snippetsAreShared可能会错误地返回YES的问题,即使TEtouch已经被安装但从未启动
  • 示例项目包括两个不同的填充支持实现
  • 示例项目包括一个用于iPad's UITextView的简单输入辅助视图,以显示如何以SDK理解的方式插入文本
  • 需要iOS 5.1或更高版本/Xcode 4.3或更高版本(使用iOS 3.1/Xcode 3.2.3的SDK版本1.2.3)

1.2.3 (2012-10-14)

  • 在UIWebViews中添加了对contentEditable / designMode的支持
  • UITextView的代理方法可以在iOS 6的UITextView中处理已设置的字符串
  • UITextField的代理方法可以在iOS 6的UITextField中处理已设置的字符串
  • 增加只读属性isAttemptingToExpandText,可以在nextDelegate中进行测试
  • 增加stringByExpandingAbbreviations方法以支持自定义扩展
  • 更改:UITextView / UITextField的代理方法可以处理pre-iOS 6 UITextViews的NSAttributedStrings,但只有当UITextView / UITextField子类实现了textExpanderAttributedString和setTextExpanderAttributedString:时才有效,这确保TextExpander不会尝试调用可能是UITextView / UITextField类私有方法的attributedString 或 setAttributedString:
  • 移除对armv6的支持(如果需要继续提供armv6支持,请使用1.2.2 SDK)

1.2.2 (2012-09-13)

  • 增加armv7s架构以支持iPhone 5

1.2.1 (2012-08-28)

  • 修复了当在UISearchBar中首次输入的字母是一个缩写时,段落数据没有展开的问题。(感谢Tim Ekl。)

1.2 (2012-06-30)

  • UITextView的代理方法可以处理NSAttributedStrings,使得TextExpander能与EGOTextView一起工作
  • 增加了对旧式时区格式化的支持:%z和%Z
  • 将TextExpander作为通用框架重新打包,简化构建过程
  • 在Read Me文件中更新了公司名称,因为我们已经以Smile名义经营一段时间了

1.1.7 (2011-01-25)

  • 向SMTEDelegateController增加了一个类方法来禁用扩展:+[SMTEDelegateController setExpansionEnabled:]
  • 修复了当在Web表单字段中使用时,会禁用提交按钮的问题

1.1.6 (2010-08-07)

  • 增加了对多任务应用程序的支持,以便通知TextExpander touch当应用回到前台时[SMTEDelegateController willEnterForeground:]
  • 增加对UISearchBar中TextExpander touch功能的支持;参见"tetest"示例应用
  • 修复了字符间隔和明确支持%date:%之间的日期格式问题
  • 仅在实际启用的情况下禁用和重新启用滚动。(感谢Kent Sutherland。)
  • 修复了复制/粘贴问题,它导致了UITextFields的回退处理错误。(感谢David Reed。)

注意:Xcode 3.2.3附带的iPhone模拟器与以前版本有不同的ABI。它必须链接到Simulator4文件夹中的libteEngine.a。我们已从此次构建中移除Simulator文件夹以避免混淆。我们已经确认苹果公司,ABI更改仅影响模拟器,并且为iOS 3编译的静态库当链接到iOS 4目标时将正常运行。

1.1.5 (2010-05-27)

  • 为UIWebView中TextExpander touch功能增加初步支持;参见"tetest"示例应用;欢迎反馈
  • 向SMTEDelegateController中添加resetKeyLog方法,以便在需要时清除键盘日志
  • 增加对iPhone OS 4(beta)模拟器目标的构建支持
  • 修正了方法转发到nextDelegate的问题,例如,对UITableViewCell内部的UITextField代理发送textFieldDidBeginFirstResponder:时得到正确处理
  • 当在UITextField上轻触清除按钮时清除键盘日志(以便立即输入的缩写正常展开)

1.1.4 (2010-03-23)

  • SMTEDelegateController不再保留nextDelegate
  • nextDelegate现在接收并响应shouldChange...代理方法,它们反映了TextExpander即将执行的操作(以前没有发送消息)
  • 增加可选的(默认启用)撤消支持
  • 将SMTEDelegateController.h头文件更新以显示nextDelegate和提供UndoSupport属性
  • 增加+[SMTEDelegateController isTextExpanderTouchInstalled],当TextExpander touch在设备上安装时返回YES
  • 增加+[SMTEDelegateController snippetsAreShared],当在TextExpander touch中启用"Share Snippets"时返回YES
  • 移除了对AddressBook框架的依赖(为了与TextExpander 1.0保持兼容性)
  • 将iPad目标添加到示例项目中
  • 从teTouchSDK文件夹中移除.svn文件夹

1.1.3 (2010-02-08)

  • 修复了当%|是第一个字符时的崩溃问题
  • 修复了当粘贴的文字长度小于替换长度时的崩溃问题
  • 与粘贴一样支持粘贴后替换功能

1.1.2 (2009-11-06)

  • 增加对绝对光标定位(%|)的支持
  • 修复了当大量内容被粘贴到TextExpander代理UITextViews时崩溃的问题
  • 修复关闭立即展开功能后的后续扩展问题(当没有任何片段匹配时,空间不会被恢复到键日志中)
  • 修复了%的转义问题(%%没有像预期那样展开为%)

1.1.1.1 (2009-10-13)

  • 修复处理了可选的UITextViewDelegate方法未调用的情况(如在开发者对UITextView进行子类化而没有调用这些方法的情况下)
  • 关于与AddressBook和AudioToolkit框架链接,上述已添加第12步

1.1.1 (2009-10-05)

  • 尊重“播放声音”首选项
  • 关于使用TextExpander引擎链接,在上述已添加第11步说明

1.1 (2009-09-10)

  • 在有可用的情况下,优先使用UIPasteboard读取片段数据(TextExpander touch 1.1将在此处而不是在地址簿中写入片段数据)
  • 从TextExpander touch 1.1版起,尊重“忽略大小写”和“立即展开”首选项
  • 注意:请务必进行清洁构建,并使用已更新的库
  • 注意:此库将与TextExpander 1.0.1 / Address Book一起工作。它将更适合1.1 / UIPasteboard。

1.0.2 (2009-08-31)

  • 补丁更新——1.0.1版本的zip文件是错误的

1.0.1 (2009-08-30)

  • 更新了teTouchSDK示例,以便使用构建设置条件,因此您无需手动重命名libteEngine.a库
  • 更新了libteEngine,以便SMTEDelegateController符合UIScrollView协议(并将委托方法调用传递给nextDelegate)
  • 更新了libteEngine,以便如果下一个委托响应某个方法,SMTEDelegateController将调用下一个委托(尝试对未来证明委托协议)
  • 修复了如果一个用户粘贴了已定义的缩写它将工作的错误(到1.0版本为止,它要么崩溃要么替换光标定位错误;此修复将在TextExpander touch 1.1中提供;您可以提前获得它)

1.0 (2009-08-24)

  • 首次公开发布。

[^1]:该框架未签名。当您构建与该框架链接的应用程序时,它将继承您的签名。