JEToolkit 3.5.0

JEToolkit 3.5.0

测试已测试
Lang语言 Obj-CObjective C
许可 MIT
发布最后发布2018年11月

John Estropia维护。



JEToolkit 3.5.0

  • 作者
  • John Rommel Estropia

JEToolkit

Version Platform License

JEToolkit为一组用于iOS开发的省时宝贝。

(我在生产代码中使用这个库,因此此仓库是活跃维护的。)

现在支持Swift 2.0!

  • 为一些在Swift代码中也很有意义的方法/宏(Objective-C)添加了Swift函数版本。
  • 所有内容都已审核nullability(可空、不可空等)。
  • 仅Objective-C项目的项目也将从所有可用功能中受益!

模块摘要

  • JEToolkit/JEToolkit:提供有用的类别、函数和宏,以提供安全性、便捷性和可读性。
  • JEToolkit/JEDebugging:一个性能良好、可配置的调试框架,可以将输出输送到调试控制台、应用程序内控制台视图和/或日志文件。
  • JEToolkit/JESettings:用于封装NSUserDefaults和密钥链访问的类封装器。通过仅声明属性即可访问键值。
  • JEToolkit/JEOrderedDictionary:一个NSMutableDictionary子类,可以记住插入键的顺序。如果您想维护按时间顺序或键的固定顺序的信息,这很有用。
  • JEToolkit/JEWeakCache:一个线程安全的缓存机制,类似于 NSCache。不同之处在于 JEWeakCache 只保留对象的弱引用,即它只保留那些没有任何其他引用的对象的引用。

可以独立使用每个子模块(通过 cocoapods)或将所有内容作为一个整体包链接!

JEToolkit/JEToolkit

JEToolkit 模块包含一些一旦开始使用,编程中就离不开的工具。它们非常有用!

更安全地处理 NSNotification(Objective-C 和 Swift)

厌烦了在 dealloc 中编写对应的 [NSNotificationCenter removeObserver:self] 吗?现在您可以为 NSNotificationCenter 添加观察者,这些观察者会在析构时自动注销。以下是一个使用示例

// Obj-C
[self registerForNotificationsWithName:UIApplicationDidEnterBackgroundNotification
      targetBlock:^(NSNotification *note) {
          // do something...
}];
// Swift
self.registerForNotificationsWithName(UIApplicationDidEnterBackgroundNotification) { (note) in
    // do something...
}

还有其他可以让您传递其他参数(如 objecttargetQueue)的变体!

为类别添加属性(仅限 Objective-C)

Objective-C 通常不允许在类别中声明 @properties。通过声明适当的访问器(getter)和设置器(setter)方法,JESynthesize() 宏让您可以精确地做到这一点,具体取决于您设置的数据类型和访问修饰符(如 assignstrong 等)。作为关联对象的扩展,JESynthesize 也支持 weak (!!)。

  • 提供类别中属性的声明的一行代码
  • 支持所有访问修饰符(包括 assignstrong 等),包括 weak
  • 因为方法是在编译时生成的,所以您可以完全不声明任何 @property's。
  • 编译时错误检查,以防止访问修饰符和数据类型不匹配(例如,不允许对 CGRect 类型设置 strong
// Obj-C
@implementation // ...

JESynthesize(assign, CGRect, frame, setFrame);
JESynthesize(strong, NSString *, name, setName);
JESynthesize(copy, void(^)(void), completion, setCompletion);
JESynthesize(unsafe_unretained, id, unsafeObject, setUnsafeObject);
JESynthesize(weak, id<UITableViewDelegate>, delegate, setDelegate);
JESynthesize(strong, NSString *, readonlyID, changeReadonlyID);

// ...

断言本地化字符串(Objective-C 和 Swift)

JEL10n()函数是NSLocalizedString()的替代品,它会在运行时断言在.strings文件中存在一个本地化(l10n)字符串。

// Obj-C
label.text = JEL10n(@"myviewcontroller.label.title"); // load from Localizable.strings
label.text = JEL10nFromTable(@"CustomStrings", @"myviewcontroller.label.title"); // load from CustomStrings.strings
// Swift
label.text = JEL10n("myviewcontroller.label.title") // load from Localizable.strings
label.text = JEL10nFromTable("CustomStrings", "myviewcontroller.label.title") // load from CustomStrings.strings

在Objective-C中KVC键的编译时检查

JEKeypath(...)宏在编译时返回并检查KVC(或KVO)键路径的存在。对于KVC运算符,您还可以使用JEKeypathOperator(...)变体。如果键路径不存在,编译将失败。

// Obj-C
[obj setValue:@"John" forKey:JEKeypath(Person *, name)];
[obj setValue:@"John" forKey:JEKeypath(typeof(self), name)]; // typeof() operator
[obj setValue:@"John" forKey:JEKeypath(Person *, friend.name)]; // dot notation
NSArray *names = [friends valueForKeypath:JEKeypathOperator(unionOfObjects, Person *, name)];

重构属性名称再也不可怕了!

优雅地处理弱-强块捕获(Objective-C仅限)

厌倦了写weakSelfstrongSelfweakSomethingstrongSomething等等?使用JEScopeWeak()JEScopeStrong(),你可以这样做

// Obj-C
typeof(self) __weak weakSelf = self;
[request downloadSomethingWithCompletion:^{
    typeof(self) __strong strongSelf = weakSelf;
    [strongSelf doSomethingElse];
}];

变成这样

// Obj-C
JEScopeWeak(self);
[request downloadSomethingWithCompletion:^{
    JEScopeStrong(self);
    [self doSomethingElse];
}];

打破保留循环,不使代码杂乱无章!

为scrollviews自动处理键盘事件(Objective-C和Swift)

UIScrollView类别允许自动处理键盘事件,包括自动滚动到子视图的firstResponder。您只需以这种方式设置scrollViews(或更常见地,表格视图):

// Obj-C
- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    [self.scrollView addKeyboardObserver];
}
- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    [self.scrollView removeKeyboardObserver];
}
// Swift
override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)
    self.scrollView.addKeyboardObserver()
}
override func viewWillDisappea(animated: Bool) {
    super.viewWillDisappear(animated)
    self.scrollView.removeKeyboardObserver()
}

还有更多!

  • NSCache类似于NSDictionary的索引支持
  • NSDateNSNumberNSStringNSDate的实用工具,用于在已知数据类型之间转换
  • NSURL API用于获取和设置扩展属性
  • UIColor从RGB或hex值创建
  • UILabelUITextView实用工具,用于计算显示字符串的大小和高度
  • UITableViewUICollectionView实用工具,用于类型安全地分列单元格
  • 以及,仍然还有很多!

JEToolkit/JEDebugging

JEDebugging 模块是一个日志框架,将有助于您和您的团队(包括服务器人员以及测试人员!)

主要特性

  • 提供清晰、易读的日志。日志消息具有缩进并带有特定日志级别的标记。此代码
// Obj-C
JELog(@"This is a sample log");
JELogNotice(@"This is a notice-level log");
JELogAlert(@"This is an alert-level log");
JEAssert(100 > 900, @"This is an assert failure log");
// Swift
JELog("This is a sample log")
JELogNotice("This is a notice-level log")
JELogAlert("This is an alert-level log")
JEAssert(100 > 900, "This is an assert failure log")

将以这种方式打印出来
Console screenshot

  • 更丰富的 debugDescription 为常见的 NSFoundation 对象。例如,使用 lldb 的 po 命令检查字典时,也会显示键和值的类型(注意,NSNumber 显示存储值的实际数据类型)
    Console screenshot
  • 令人惊叹的 JEDump(...) 宏可以让你检查和记录抛给它的任何内容:整数、C 数组、结构体、对象、块等。查看 JEToolkitTests 单元测试或 JEToolkitDemo 项目以查看更多示例输出和示例用法。
  • 所有日志都是线程安全的。
  • 可选将日志保存到文件。日志文件按日期分开,并提供 API 以枚举日志的 NSDataNSURL
  • 可选在应用程序内部显示轻量级、内联 HUD 控制台。
    Inline HUD screenshot
    默认情况下,在发布模式下不会创建此视图。您可以使用可拖动按钮展开/折叠 HUD,并且可以调整视图的大小。HUD 也始终位于所有其他视图/窗口的顶部,即使在打开模态视图或创建自己的窗口时也是如此。还有一个按钮可以通过 UIActivityViewController 发送日志文件(Air-Drop 真是个好东西!),以及一个按钮清除所有显示的日志。
  • 为控制台日志记录器、文件日志记录器和 HUD 日志记录器提供可配置的设置。

JEToolkit/JESettings

JESettings 模块提供了管理 NSUserDefaults 和密钥链数据的酷基类,以及对象模型。要创建此类模型,请从 JEUserDefaultsJEKeychain 继承,并将要管理的数据声明为动态属性(Objective-C 中的 @dynamic,Swift 中的 @NSManaged

// Obj-C
// .h
@interface MyUserDefaults: JEUserDefaults
    @property (nonatomic, strong) NSString *myString;
    @property (nonatomic, assign) NSInteger myNumber;
@end
// .m
@implementation MyUserDefaults
    @dynamic myString;
    @dynamic myNumber;
@end
// Swift
class MyUserDefaults: JEUserDefaults {
    @NSManaged var myString: String?
    @NSManaged var myNumber: Int
}

一旦设置了模型类,就可以立即开始使用。以下代码

// Obj-C
MyUserDefaults *defaults = [MyUserDefaults new];
defaults.myString = @"sample string";
defaults.myNumber = 42;
// Swift
let defaults = MyUserDefaults()
defaults.myString = "sample string"
defaults.myNumber = 42

将这些值保存到 NSUserDefaults

"MyUserDefaults.myString" = "sample string"
"MyUserDefaults.myNumber" = 42

这不是很酷吗?

主要功能

  • 支持以下类型的所有动态属性
    • Objective-C
      • 所有原始整型(《short`,《int`,《NSInteger`,《NSUInteger`,《long long int`,《unsigned long long int`等)
      • 所有原始布尔类型(《bool`,《BOOL`)
      • 所有原始浮点类型(《float`,《double`,《CGFloat`)
      • NSString *
      • NSNumber *
      • NSDate *
      • NSData *
      • NSURL *
      • NSUUID *
      • id<NSCoding>(基本上,任何遵从NSCoding协议的实体)
      • SEL
      • CGPoint
      • CGSize
      • CGRect
      • CGAffineTransform
      • CGVector
      • UIEdgeInsets
      • UIOffset
      • NSRange
    • Swift
      • 支持上述Objective-C的所有类型
      • 所有可桥接到NSString的字符串类型(《NSString?,《String》,《String?)
      • 所有可桥接到NSNumber的数字类型(《NSNumber?,《Int》,《Int32》,《UInt8》,《Double》,《CGFloat》等)
  • 默认情况下,JEUserDefaults使用格式为"<class name>.<property name>"的字符串键,但您也可以通过重写-[JEUserDefaults userDefaultsKeyForProperty:]来配置自己的格式。
  • JEUserDefaults实例以单身形式创建,每个类和suiteName独特。有关详情,请参阅-[JEUserDefaults init]-[JEUserDefaults initWithSuiteName:]的头文件文档。
  • 通过使用proxyForDefaultValues方法获取代理实例,JEUserDefaults还允许您为在NSUserDefaults中不存在的键设置默认值。
// Obj-C
MyUserDefaults *defaults = [MyUserDefaults new];

MyUserDefaults *fallback = [defaults proxyForDefaultValues];
fallback.myString = @"sample string";

defaults.myString = nil;

NSString *value = defaults.myString; // value is now "sample string"
// Swift
let defaults = MyUserDefaults()

let fallback = defaults.proxyForDefaultValues()
fallback.myString = "sample string"

defaults.myString = nil

let value = defaults.myString // value is now "sample string"

内部操作仅为-[NSUserDefaults registerUserDefaults:]保存默认值;()

  • 默认情况下,JEKeychain使用应用程序包标识符作为kSecAttrService,但您可以向-[JEKeychain initWithService:accessGroup:]传递首选服务名称。
  • 默认情况下,JEKeychain使用属性名称作为kSecAttrAccount,您也可以通过重写-[JEKeychain keychainAccountForProperty:]来配置自己的格式。
  • JEKeychain允许通过重写-[JEKeychain keychainAccessForProperty:]为每个属性设置访问模式(例如JEKeychainAccessAfterFirstUnlock等)。
  • 如果项目包含JEDebugging模块,则使用lldb's po命令打印JEUserDefaultsJEKeychain实例将打印所有保存的键和值。

安装

  • 需要iOS 7 SDK及其以上版本
  • 需要ARC

通过CocoaPods安装

在您的Podfile中添加以下内容

pod 'JEToolkit'

然后运行 pod install

通过Carthage安装

在你的 Cartfile 中添加:

github "JohnEstropia/JEToolkit"

然后运行 carthage update

手动安装

建议以Git子模块的方式手动安装。

git submodule add https://github.com/JohnEstropia/JEToolkit.git <destination directory>

你也可以将仓库独立地克隆到app的.xcodeproj目录下,然后拖动并放置JEToolkit.xcodeproj到你的app项目中。

贡献?

欢迎报告任何问题或提出建议!也欢迎用日语联系!

许可协议

JEToolkit采用MIT许可协议发布。有关更多信息,请参见LICENSE文件。