Xcode中调试位置移动

Xcode/iPhone Simulator可以通过使用GPX来模拟当前位置,有时需要测试位置变动时可以使用这个特性来提高生产效率

关于gpx1.0的标准这里(http://www.topografix.com/gpx_manual.asp)有一篇文档。

实际应用当中可以通过使用google earch配合一些工具来生成gpx。

首先在http://www.google.com/earth/index.html下载 Google Earth

1 移动到想要添加路径点的地方

2 在菜单中点击 添加/路径 或者从工具栏按对应的图标

3 把弹出的窗口放到一边,在地图上用鼠标点想要的路径点

4 添写名称点确认

5 在侧栏中右键选择创建好的路径,点“将位置另存为”, 然后保存为kml

到此便完成了kml的创建

http://www.gpsvisualizer.com 提供了这一个功能

打开网站后会看到 “Upload a GPS file”

1 点边上上传控件选取gpx文件

2 在Choose an output format 中选则”GPX file”

3 点Go!

4 转换好的GPX会在网站上显示出来,把它粘贴到一个gpx文件中

xcode貌似对生的GPX格式不支持, 只需要一点修改就可以使用了

1 把trk, name, trkseg这三个标签干掉

2 把trkpt整体替换成wpt

这样这个文件就可以使用了

大概是这个样子

<?xml version=“1.0”?>

<gpx creator=“GPS Visualizer http://www.gpsvisualizer.com/ version=“1.0” xmlns=http://www.topografix.com/GPX/1/0 xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance xsi:schemaLocation=http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd>

    <wpt lat=“39.984440439” lon=“116.309970222”></wpt>

    <wpt lat=“39.986689168” lon=“116.353745154”></wpt>

</gpx>


然后把这个gpx文件添加到Xcode工程中,在target中钩掉所有target, 因为这个文件不需要打包到最终的产品中.

这时就可以模拟位置了,点工具栏中的工程名,选’Edit Schema’在Options标签中选 ‘Allow Location Simulation’ 在Default Location中先刚才加上的的gpx文件名就可以,也可以选None,在程序调试期间选底部的定位图标来选gpx文件。

写了一个简陋的Demo https://github.com/stcui/GPXDemo

(CoreData) 如何高效地导入数据

Efficiently Importing Data

这篇文章讲述了如何更有效率地导入数据到Core Data应用并将数据转换为managed objects以持久化。并讨论了一些应该遵从的Cocoa基本模式,和一些专用于Core Data中的模式

Cocoa Fundamentals

一般说来,当你使用Core Data来导入数据文件时一定要记住一个在Cocoa 应用开发中需要应用的很重要的“一般规则”。如果你导入文件必须以某种方式解析时,这一般需要使用大量的临时文件。这会导致大量的内存占用甚至引起内存分页。就像没有使用Core Data的应用时会做的一样,你可以使用本地的自动释放池block来控制在内存存在对象数量。关于更多的Core Data与内存管理的交互参见 “Reducing Memory Overhead.”

你同时应该减少不必要的重复工作。在创建一个包含一个变量的predicate中有一个微妙的例子。如果像下面这样创建predicate里,你不仅仅是在每一个多循环都创建了一个predicate, 还同时在做解析。

// Loop over employeeIDs.
for (NSString *anID in employeeIDs) {
    NSString *predicateString = [NSString stringWithFormat:@"employeeID == %@", anID];
    NSPredicate *predicate = [NSPredicate predicateWithFormat:predicateString];

为了从一个格式化的字符串中创建一个predicate, 框架必须解析这个字符串并创建一predicate的实例和一堆表达式对象。如果能使用同一个predicate对象,如果你是在重复使用同一种格式的predicate,只是在每次循环中改变表达式中的常量,你可以创建一个predicate的实例,然后每次再替换里面的常量 (参见 “Creating Predicates”),这样会更有效率. 这种技术如下面的代码所示。

NSString *predicateString = [NSString stringWithFormat @"employeeID == $EMPLOYEE_ID"];
NSPredicate *predicate = [NSPredicate predicateWithFormat:predicateString];
for (NSString *anID in employeeIDs) {
    NSDictionary *variables = @{ @"EMPLOYEE_ID" : anID };
    NSPredicate *localPredicate = [predicate predicateWithSubstitutionVariables:variables];

Reducing Peak Memory Footprint

如果你需要导入大量的数据到Core Data应用中, 你应该批量导入这些数据并在批次间清理Core Data栈以保证降低应用的内存使用峰值。相关的案例与技术参见 “Core Data Performance” (特别是 “Reducing Memory Overhead”) 与 “Object Lifetime Management,” 方便起见这里总结了这些这些技术。

Importing in batches

首先,应该为导入创建多个分开的托管对象上Contexts,然后设置它们的undo manager为nil。 (Contexts 的创建并不是很耗资源,所以如果你缓存了 persistent store coordinator 你可以为了不同的工作集或特殊的操作使用不过的Contexts。)

NSManagedObjectContext *importContext = [[NSManagedObjectContext alloc] init];
NSPersistentStoreCoordinator *coordinator = <#Get the coordinator#>;
[importContext setPersistentStoreCoordinator:coordinator];
[importContext setUndoManager:nil];

(如你以有一个创建好的 Core Data 栈, 你可以从另外一个托管对象的context中获取 persistent store coordinator .) 设置undo manager 为 nil 意味着:

  1. 你不会把努力浪费在记录对不需要撤销的动作上(如插入);

  2. Undo manager 不会强引用被改变的对象以阻止他们被释放  (参见 “Change and Undo Management”).

你应该在分批导入数据差创建相应的托管对象 (最优的批次大小取决于每条记录的多大和你相要保持多低的内存占用). 在一个自动释放块中进行每一个批次的处理; 在每一个批量操之后你需要保存context (调用 save:). (直到保存前,context会对每一个未保存的改变保持强引用完成插入操作.)

Dealing with strong reference cycles

相互有引用的托管对象几互每次都会导致不可恢复的强引用环. 如果在导入中你在对象中创建了引用关系,你需要打破这个环来让对象在不再使用时得以析构。为了完成这个目标, you can either turn the objects into faults, or reset the whole context. 完整的讨论, 参见 “Breaking Relationship Strong Reference Cycles.”

Implementing Find-or-Create Efficiently

在导入数据中一个常用的技术是使用“查找或新增”模式, 来判断一个对象是否己经存在,如果没有则创建它。

为了一堆离散的值,在需要寻找己有对象(己经持久化)时你可能会遇到很多种情况. 一个简单的方法是创建一个循环, 然后对每一个值执行一次查询来判断是否己经存在一个匹配的对象. 这个模式不是很好。如果你分析使用这种模式的应用,你会发现每一次查询是在循环中最耗时的操作之一(相对于仅仅枚举集合中的每一个对象). 甚至这个模式会将问题的时间复杂度由 O(n) 变为 O(n^2)。

在可能的情况下有一个很高效的方法,一次性地创建所有托管对象,然后再修复对象间的关系。比如你导入的数据中不存在任何重复的数据(比如说你的初始集为空),你可以直接创建对应的托管对象而不用进行查询,或者你导入一个“展平”的数据,它们之音没有任何关联. 你可以先创建所有对应的托管对象,然后在保存前用一个大的 IN predicate来干掉重复的对象.

如果说你因为要导入一堆使用属相来相互关联的数据,在使用“查找或创建”模式时,你可以能过减少查询次数来优化查找己有对象的方式。完成这种方法取决于过程中有多少参考数据必须使用。如果你导入100个潜在的新对象,但在数据库中只有2000条数据,从数据库中取出所有的数据并缓存起来不会太蛋疼(特别是这些数据会反复用到)。但是如果你有 100,000 条数据在库中,把它们在内存中缓存起来就糟心了。

你可以在每个查询中组合使用IN predicate 和排序来减少 Core Data 的工作量. 举个例子,说你希望获先取得一个雇员ID(string类型)的列表, 然后再创建所有不在库中的雇员,or example, you want to take a list of employee IDs (as strings) and create Employee records for all those not already in the database. 考虑这段代码,雇员是一个有着 name 属性的实体, 一个 listOfIDsAsString 是一张雇员 ID 的表, 这里面的雇员如果没在库中的话你想把他们加入库中。

第一步,对相关的对象分离ID并排序

// get the names to parse in sorted order
NSArray *employeeIDs = [[listOfIDsAsString componentsSeparatedByString:@"\n"]
        sortedArrayUsingSelector: @selector(compare:)];

下一步,用 IN 名字字符串数 创建一个 predicate, 附带上一个排序描述来保证结果与名字的顺序一致. (IN 与 SQL中 IN 的操作一样, 都是判断左边的值一定会在右边的集合中出现.)

// Create the fetch request to get all Employees matching the IDs.
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:
        [NSEntityDescription entityForName:@"Employee" inManagedObjectContext:aMOC]];
[fetchRequest setPredicate: [NSPredicate predicateWithFormat:@"(employeeID IN %@)", employeeIDs]];
// make sure the results are sorted as well
[fetchRequest setSortDescriptors:
        @[[[NSSortDescriptor alloc] initWithKey: @"employeeID" ascending:YES]]];

最后执行查询.

NSError *error;
NSArray *employeesMatchingNames = [aMOC executeFetchRequest:fetchRequest error:&error];

你会得到两个排序好的数组,一个里面有通查询的雇员ID,一个里面有对应的托管对象. 为了处理它们,可以用以下步聚遍历这两个数组:

  1. 取下一个 ID 和 雇员. 如果 ID 与  雇员 ID 不匹配, 创建一个与这个ID对应的新雇员。

  2. 取下一个雇员: 如果这个雇员的ID与刚才取到的ID匹配, 取下一个 ID 和 雇员.

不管你有多少个 ID 要处理, 你只需要一次查询,然后处理结果集即可。

下面的代码完整展示了上一段的例子。

// Get the names to parse in sorted order.
NSArray *employeeIDs = [[listOfIDsAsString componentsSeparatedByString:@"\n"]
        sortedArrayUsingSelector: @selector(compare:)];
// create the fetch request to get all Employees matching the IDs
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:
        [NSEntityDescription entityForName:@"Employee" inManagedObjectContext:aMOC]];
[fetchRequest setPredicate: [NSPredicate predicateWithFormat: @"(employeeID IN %@)", employeeIDs]];
// Make sure the results are sorted as well.
[fetchRequest setSortDescriptors:
    @[ [[NSSortDescriptor alloc] initWithKey: @"employeeID" ascending:YES] ]];
// Execute the fetch.
NSError *error;
NSArray *employeesMatchingNames = [aMOC executeFetchRequest:fetchRequest error:&error];

 

http://developer.apple.com/library/mac/#documentation/cocoa/conceptual/coredata/Articles/cdImporting.html#//apple_ref/doc/uid/TP40003174-SW4

查看剩余内存

#import <mach/mach.h>
#import <mach/mach_host.h>

void print_free_memory ()
{
mach_port_t host_port;
mach_msg_type_number_t host_size;
vm_size_t pagesize;

host_port = mach_host_self();
host_size = sizeof(vm_statistics_data_t) / sizeof(integer_t);
host_page_size(host_port, &pagesize);

vm_statistics_data_t vm_stat;

if (host_statistics(host_port, HOST_VM_INFO, (host_info_t)&vm_stat, &host_size) != KERN_SUCCESS)
NSLog(@"Failed to fetch vm statistics");

/* Stats in bytes */
natural_t mem_used = (vm_stat.active_count +
vm_stat.inactive_count +
vm_stat.wire_count) * pagesize;
natural_t mem_free = vm_stat.free_count * pagesize;
natural_t mem_total = mem_used + mem_free;
NSLog(@"used: %u free: %u total: %u", mem_used, mem_free, mem_total);
}

http://stackoverflow.com/questions/10648902/how-to-get-available-memory-in-ios

关于自定义 UITableViewCell

自定义UITableViewCell的方法有很多 发现一些人都会遇到自己定义的cell里面图片错乱的问题 这个问题往往是因为没有实现prepareForReuse这个方法导致的.

UITableViewCell在向下滚动时复用, 得用的cell就是滑出去的那些, 而滑出去的cell里显示的信息就在这里出现了 解决的方法就是在UITableViewCell的子类里实现perpareForReuse方法, 把内容清空掉

比如

- (void)prepareForReuse
{
    [super prepareForReuse];
    self.myImageView.image = nil;
}

iOS 首屏的图标圆角究竟是多少

在图标的设计中会在ps上画出一个Demo来查看最终的效果,这里就需要自己绘制一个圆角的蒙板或者用其它方法来完成这一效果,这个圆角的半径究竟是多少呢?

在早期的iPhone/iPod中图标尺寸为57×57圆角半径为10px
之后的版本中的图标尺寸就是按照这个比例来缩放的
如果是114×114的图标圆角半径为 114*(10/57) = 20

其它的一些例子:
Icon512.png – 512px – 89.8245614035098
Icon.png – 57px – 10
Icon@2x.png – 114px – 20
Icon-72.png – 72px – 12.6315789473686
Icon-72@2x.png – 144px – 25.2631578947371
Icon-Small.png – 29px – 5.08771929824567
Icon-Small@2x.png – 58px – 10.1754385964913

TTModelViewController

TTModelViewController提供了一个机制来使View的展现与Model同步

TTModelViewController中设置了一系列标志位来存储Model与View的当前状态,通过UpdateViewState来更新View的内容

isModelXXXisInvalid的标记在相应操作生效后置1然后在调用回调后置0

isModelDidRefreshInvatrd  刷新后置1,执行完回调后置0
isModelWillLoadInvalid 在模型开始加载后置1
isModelDidLoadInvalid
isModelDidLoadFirstTimeInvalid
isModelDidShowFirstTimeInvalid
isViewInvalid
isViewSuspended 在ModelDidBeginUpdate和ModelDidEndUpdates中间为YES
isUpdatingView  updateView方法开始置1结束置0
isShowingEmpty
isShowingLoading
isShowingModel  己加载|!shouldLoad
isShowingError

私有方法:

resetViewStates:
判断几种视图的展示状态(加载中、展示模型、出错、空模型),如果开启则关闭.

updateViewStates
根据flag来更新视图的状态
在refresh中置isViewInvalid和isModelDidRefreshInvalid为NO

刷新的策略
从未加载过的Model使用内存+磁盘+网络缓存
加载过的Model使用网络缓存
判断为需要加载更多的使用内存+磁盘+网络缓存
其他的置isModelDidLoadInvalid为YES,如果View didAppear 则更新View([self updateView])

工作流程
在View加载前后设置 _isViewAppearing和_hasViewAppeared
viewWillAppear中在标记位设置后调用[self updateView]和父类viewWillAppear

– (void)updateView
在View无效的情况下如果View没有休眠也没有在更新中(isUpdatingView)则执行以下代码
设置isUpdatingView为YES
实例化Model
实例化View
[self updateViewStates]
如果当前控制器有冻结状态并且isShowingModel置YES则从_frozenState中恢复并结释放_frozenState
标记isViewInvalid和isUpdatingView为NO
[self reloadIfNeeded]

TTViewController会在viewWillAppear和viewDidAppear中暂停网络连接队列

从Three20中学到的一些方法

获取UIView的 Controller
使用 [UIResponder nextResponder]方法

http://developer.apple.com/library/mac/#qa/qa1490/_index.html
64位桌面程序个iOS程序的链接器中有一个Bug会使链接器中的-ObjC标识不起做用,Three20中使用了一个宏来结决这个问题
#define TT_FIX_CATEGORY_BUG(name) @interface TT_FIX_CATEGORY_BUG_##name @end \
@implementation TT_FIX_CATEGORY_BUG_##name @end
这里定义了一个类的实现来防止编译器忽略掉Catelog和不包含类的文件

Three20 UINavigator

Three20 UINavigator

TTGlobalNavigatorMetrics
屏幕方向 大小 导航大小 键盘大小 状态栏大小 工具栏大小


TTURLObject @protocol
NSString *URLValue
– (NSString*)URLValueWithName:(NSString*)name;


TTBaseNavigationController

– (void)pushViewController: (UIViewController*)controller
animatedWithTransition: (UIViewAnimationTransition)transition;
动画推入新的界面

– (UIViewController*)popViewControllerAnimatedWithTransition:(UIViewAnimationTransition)transition;
动画推出当前界面


TTNavigatorRootContainer 定义了导航对象的根控制器设定与获取控制器的导航对象方法
– (void)navigator:(TTBaseNavigator*)navigator setRootViewController:(UIViewController*)controller;
– (TTBaseNavigator*)getNavigatorForController:(UIViewController*)controller;


TTBaseNavigator
自动持久化ViewController
包含 URLMap,
读写 window, rootContainer
只读 rootViewController, visibleViewController, topViewController
读写 URL 打开或获取当前的URL
读写 persistenceMode 持久化控制器的方法,默认不缓存
persistenceExpirationAge 缓存时间

读写 supportsShakeToReload 是否支持摇晃刷新
读写 opensExternalURLs 是否支持打开外链
读写 isDelayed 是否有任务延迟加载

/**
* Determines the navigator that contains this view.
*
* Traverse the view hierarchy until the root view container is reached. If this root container
* conforms to the TTNavigatorRootContainer protocol, we call getNavigatorForController:
* with the top-most controller that contains this view that /isn’t/ the container.
* If getNavigatorForController: returns a navigator, this navigator is returned.
* Otherwise, the global navigator is returned.
*
* If the given view is not, in fact, a view, which is the case if a UIBarButtonItem is passed,
* returns the global navigator via [TTBaseNavigator globalNavigator].
*
* If you need to use a specific navigator for UIBarButtonItem, handle the button tap
* yourself and use navigatorForView: on an actual view in the controller.
*/
+ (TTBaseNavigator*)navigatorForView:(UIView*)view;
判断包含view的导航
如果在点击TabBarButton后要使用某个Navigator可以用此方法

+ (TTBaseNavigator*)globalNavigator;
+ (void)setGlobalNavigator:(TTBaseNavigator*)navigator;

打开URL
– (UIViewController*)openURLAction:(TTURLAction*)URLAction;
– (UIViewController*)openURLs:(NSString*)URL,…; 打开一系列URL,结果为最后的URL

获取URL对应的Controller
– (UIViewController*)viewControllerForURL:(NSString*)URL;
– (UIViewController*)viewControllerForURL:(NSString*)URL query:(NSDictionary*)query;
– (UIViewController*)viewControllerForURL:(NSString*)URL query:(NSDictionary*)query
pattern:(TTURLPattern**)pattern;

– (void)beginDelay;
初始化控制器可能非常占用耗时和资源,如果在动画的过程中发生会应响用户的体验
通过这个方法可以在让导航器在生成控制器后再动论

– (void)endDelay
– (void)cancelDelay

– (void)persistViewControllers;
持久化所有

– (UIViewController*)restoreViewControllers
恢复控制器

– (void)persistController:(UIViewController*)controller path:(NSMutableArray*)path;

– (void)removeAllViewControllers;
去除并释放

对象与URL的映射
– (NSString*)pathForObject:(id)object;
– (id)objectForPath:(NSString*)path;
– (void)resetDefaults; 清空持久化的数据

Three20 Core

TTGlobalCore

TTGlobalCore对Foundation Framework的扩展

创建不retain对象的集合 (通过对CFArray对象的retain, release赋以函数形式实现)
TTCreateNonRetainingArray()
TTCreateNonRetainingDictionary()

判断对象是否为集合
TTIsArrayWithItems(id object)
TTIsSetWithItems(id object)

判断字符串
TTIsStringWithAnyText(id object)

交换objc方法 (objc runtime)
TTSwapMethods(Class cls, SEL originalSel, SEL newSel)


TTGlobalCoreLocal
包含了与本地化相关的代码
TTCurrentLocal()
从standard user defaults中获取”AppleLanguages”(NSArray)中第一个的值,如果为空则调用[NSLocal currentLocal]

TTLocalizedString(NSString* key, NSString* comment)
从Three20.bundle中[bundle localizedStringForKey:key value:key table:nil]

TTDescriptionForError
如果error.domain为NSURLErrorDomain{本地化 NSURLErrorTimedOut, NSURLErrorNotConnectedToInternet 这两项错误,其它的显示为”Connection Error”的本地话字符串}

TTFormatInteger(NSInteger num)
以逗号分隔形式格式化整数


TTGlobalCorePaths
包函URL判断与设置默认Bundle及从默认bundle中取出资源的代码
TTIsBundleURL(NSString* URL) URL是否以”bundle://”开头
TTIsDocumentsURL(NSString* URL) URL是否以”document://”开头
TTSetDefaultBundle(NSBundle* bundle)
NSBundle* TTGetDefaultBundle()
NSString* TTPathForBundleResource(NSString* relativePath); 生成bundle的Resource目录中指定文件名的完整目录

NSString* TTPathForDocumentsResource(NSString* relativePath); 生成Documents目录中指定文件名的完整目录


TTGlobalCoreRects
包函与距形CGRect相关的函数
CGRect TTRectContract(CGRect rect, CGFloat dx, CGFloat dy)
CGRect TTRectShift(CGRect rect, CGFloat dx, CGFloat dy)
CGRect TTRectInset(CGRect rect, UIEdgeInsets insets)


NSArrayAdditions
两组遍历每个数组元素使其执行指定的方法
第一组 先复制自身再对复本执行方法,可能对数级元素进行修改
– (void)perform:(SEL)selector;
– (void)perform:(SEL)selector withObject:(id)p1;
– (void)perform:(SEL)selector withObject:(id)p1 withObject:(id)p2;
– (void)perform:(SEL)selector withObject:(id)p1 withObject:(id)p2 withObject:(id)p3;
第二组 不复制自身,禁止修改数据元素
– (void)makeObjectsPerformSelector:(SEL)selector withObject:(id)p1 withObject:(id)p2;
– (void)makeObjectsPerformSelector: (SEL)selector
withObject: (id)p1
withObject: (id)p2
withObject: (id)p3;
查找方法
– (id)objectWithValue:(id)value forKey:(id)key;
– (id)objectWithClass:(Class)cls;
– (BOOL)containsObject:(id)object withSelector:(SEL)selector;


NSDataAdditions
两个Hash方法
– (NSString*)md5Hash
– (NSString*)sha1Hash


NSMutableArray
添加非空字串
– (void)addNonEmptyString:(NSString*)string


NSMutableDictionary
– (void)setNonEmptyString:(NSString*)string forKey:(id)key
为key添加非空字串值,不判断key是否为非空


NSObjectAdditions
对performSelector的扩展,允许最多带7个参数
– (id)performSelector:(SEL)selector withObject:(id)p1 withObject:(id)p2 withObject:(id)p3;
– (id)performSelector:(SEL)selector withObject:(id)p1 withObject:(id)p2 withObject:(id)p3
withObject:(id)p4;
– (id)performSelector:(SEL)selector withObject:(id)p1 withObject:(id)p2 withObject:(id)p3
withObject:(id)p4 withObject:(id)p5;
– (id)performSelector:(SEL)selector withObject:(id)p1 withObject:(id)p2 withObject:(id)p3
withObject:(id)p4 withObject:(id)p5 withObject:(id)p6;
– (id)performSelector:(SEL)selector withObject:(id)p1 withObject:(id)p2 withObject:(id)p3
withObject:(id)p4 withObject:(id)p5 withObject:(id)p6 withObject:(id)p7;


NSStringAdditions
字串的判断
– (BOOL)isWhitespaceAndNewlines;
– (NSDictionary*)queryContentsUsingEncoding:(NSStringEncoding)encoding;
将URL查询字串转为字典,每个key对应一个数组,以应对有多个(相同的key)=value对,无value时value=[NSNull null]
– (NSString*)stringByAddingQueryDictionary:(NSDictionary*)query
在当前字串后添加query,过程中会对query的值做URL Encoding
– (NSString*)stringByRemovingHTMLTags;
– (NSComparisonResult)versionStringCompare:(NSString *)other;
* 示例 (?? 代表不确定):
* “3.0” = “3.0”
* “3.0a2” = “3.0a2”
* “3.0” > “2.5”
* “3.1” > “3.0”
* “3.0a1” < "3.0" * "3.0a1" < "3.0a4" * "3.0a2" < "3.0a19" <-- 不按字典顺序,按数字顺序, 只能用'a' * "3.0a" < "3.0a1" * "3.02" < "3.03" * "3.0.2" < "3.0.3" * "3.00" ?? "3.0" * "3.02" ?? "3.0.3" * "3.02" ?? "3.0.2" - (NSString*)md5Hash - (NSString*)sha1Hash

TTExtensionLoader
添加扩展方法:为TTExtentionLoader浅耕加Catelog
为方法名命为- (BOOL)loadExtensionNamed

+ (void)loadAllExtensions;
调用的唯一方法

+ (NSDictionary*)availableExtensions;

+ (NSDictionary*)loadedExtensions;
+ (NSDictionary*)failedExtensions;


TTEntityTables
XML entity Table ?


TTMarkupStripper
去标签