Giter VIP home page Giter VIP logo

axkit's Introduction

axkit's People

Contributors

xaoxuu avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

axkit's Issues

0.0.10 更新日志

更改了一些layer相关设置的接口

想要实现圆角阴影效果可以这样:

UIView *view = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];
view.backgroundColor = [UIColor yellowColor];
// 圆角半径30,阴影为向下投射的浮起样式
[view.layer ax_cornerRadius:30 shadow:LayerShadowDownFloat];
[self.view addSubview:view];

想自定义阴影效果可以这样:

[view.layer ax_customShadowWithOpacity:0.2 radius:5 offset:CGSizeMake(0, 4)];
// 或者
CGMutablePathRef squarePath = CGPathCreateMutable();
CGPathAddRect(squarePath, NULL, view.bounds);
[view.layer ax_customShadowWithOpacity:0.2 radius:5 offset:CGSizeMake(0, 4) color:[UIColor blueColor] path:squarePath];
CGPathRelease(squarePath);

将视图转换成图片

UIImage *img = UIImageFromView(self.view);

优化了Error的日志输出版式

使用示例:

NSError *error = [NSError ax_errorWithMaker:^(NSErrorMaker * _Nonnull error) {
    error.domain = @"my domain";
    error.code = 123;
    error.localizedDescription = @"desc123123";
    error.localizedFailureReason = @"reason123123";
    error.localizedRecoverySuggestion = @"suggestion123123";
    [error.localizedRecoveryOptions addObject:@"1. xxx"];
    [error.localizedRecoveryOptions addObject:@"2. xxx"];
}];

AXLogError(error);

qq20170603-001302 2x

当然,只写一个错误描述或者别的什么信息都是可以的:

NSError *error = [NSError ax_errorWithMaker:^(NSErrorMaker * _Nonnull error) {
    error.localizedDescription = @"发生了未知错误";
}];

AXLogError(error);

qq20170603-001404 2x

更方便的布局view

为view增加了快速获取bounds center的方法:

#pragma mark bounds center
@property (nonatomic, readonly, assign) CGPoint boundsCenter;
@property (nonatomic, readonly, assign) CGFloat boundsCenterX;
@property (nonatomic, readonly, assign) CGFloat boundsCenterY;

更容易将某个控件放置到父视图中间

比较两个版本新旧

对比服务器端的版本(remoteVersion)和当前app版本([NSBundle ax_appVersion])

VersionLaterThanVersion(remoteVersion, [NSBundle ax_appVersion], ^(BOOL later) {
    if (later) {
        // @xaoxuu: 有新版本
    } else {
        // @xaoxuu: 有新版本
    }
}, ^(NSError * _Nonnull error) {
    AXLogError(error);
});

版本必须都以"."分隔,并且两个版本的"."的个数相同

增加快速创建纯色图片的方法

目前的方法是:

self.imageView.image = [UIImage ax_imageWithColor:axColor.theme size:self.imageView.frame.size alpha:1];

每次都要输入size和alpha很麻烦。

理想的方法应该是:

self.imageView = [UIImageView ax_imageViewWithColor:axColor.theme];

快速地将控件文本转换成NSLocalizedString

用法示例

// 将self.testView中所有的UILabel中的文字转换支持多语言
[self.testView ax_eachSubview:[UILabel class] action:^(__kindof UIView * _Nonnull subview) {
    UILabel *lb = subview;
    AXLocalizedLabel(lb);
}];
// 将self.testView中所有的UITextField中的文字转换支持多语言
[self.local ax_eachSubview:[UITextField class] action:^(__kindof UIView * _Nonnull subview) {
    UITextField *tf = subview;
    AXLocalizedTextField(tf);
}];
// 将self.testView中所有的UITextView中的文字转换支持多语言
[self.local ax_eachSubview:[UITextView class] action:^(__kindof UIView * _Nonnull subview) {
    UITextView *tv = subview;
    AXLocalizedTextView(tv);
}];

注意:此方法生效的前提是你的Localizable.strings文件中有这些语言的翻译。

接口

/**
 将UILabel中的文字转换成NSLocalizedString

 @param label 目标UILabel
 */
FOUNDATION_EXTERN void AXLocalizedLabel(UILabel *label);

/**
 将UITextView中的文字转换成NSLocalizedString
 
 @param textView 目标UITextView
 */
FOUNDATION_EXTERN void AXLocalizedTextView(UITextView *textView);

/**
 将UITextField中的文字转换成NSLocalizedString
 
 @param textField 目标UITextField
 */
FOUNDATION_EXTERN void AXLocalizedTextField(UITextField *textField);

实现

inline void AXLocalizedLabel(UILabel *label){
    label.text = NSLocalizedString(label.text, nil);
}

inline void AXLocalizedTextView(UITextView *textView){
    textView.text = NSLocalizedString(textView.text, nil);
}

inline void AXLocalizedTextField(UITextField *textField){
    textField.placeholder = NSLocalizedString(textField.placeholder, nil);
    textField.text = NSLocalizedString(textField.text, nil);
}

让代码具有冷却时间

必要性

首先我个人认为设计合理、逻辑严谨的代码是用不到这个机制的,但是我们不能保证我们面对的代码永远都是完美的,所以我就提供了这个冷却机制以延长那些癌症晚期的代码的寿命。

优点:执行代码像放技能一样,可以强行打破死循环、避免死循环、避免过高频率访问某一资源、从一定程度上缓解了内存、CPU压力。

缺点:治标不治本,最好是找出会产生问题的代码,从根源上解决问题。

使用示例

示例1

某种耗时耗能操作,希望在某种条件下触发,但又担心用户频繁触发,就可以这样:

// @xaoxuu: 重新获取数据源并刷新tableView
- (void)reloadDataAndRefreshTableView{
    // 无论如何,2秒内最多只会执行一次此方法。
    [NSBlockOperation ax_delay:0 cooldown:2 token:@"reload data and refresh table view" performInMainQueue:^{
        [self.dataList removeAllObjects];
        [self reloadTableView];
    }];
}
- (IBAction)btn1:(UIButton *)sender {
    [NSBlockOperation ax_delay:0 cooldown:60 token:self performInMainQueue:^{
        // @xaoxuu: 立即在主线程施放大招,冷却时间是60秒。
    }];
}

- (IBAction)btn2:(UIButton *)sender {
    [NSBlockOperation ax_delay:2 cooldown:120 token:self performInBackground:^{
        // @xaoxuu: 延迟2秒后在后台默默施放大招,冷却时间是120秒。
    }];
}
// @xaoxuu: 两者的token相同则共享冷却时间。

示例2

如何强行打破死循环?说实话我是没有遇到这种需求,仅仅是这个机制有这种能力,觉得挺有趣,就尝试一下:

// 自己调用自己,无限循环
- (void)loop{
    AXLogFunc();
    [self loop];
}
// 自己调用自己,但是发现代码在冷却,所以就失效了,一个环节被中断,死循环就被打破了
- (void)loop{
    AXLogFunc();
    [NSBlockOperation ax_delay:0 cooldown:0.0001 token:@"loop" performInMainQueue:^{
        [self loop];
    }];
}

实现原理

给每一个block分配一个dispatch_after的函数,执行的时候开始计时,并且函数标记为disable,计时结束后重新enable。

让每个子视图执行某个方法

目前可以根据子视图的类来只选择某些子视图,代码如下:

[self.topView ax_eachSubview:[UIImageView class] action:^(__kindof UIView * _Nonnull subview) {
        
}];

计划增加一种可以根据tag值或者selected状态来选定特定类型的子视图,如:

[self.view ax_eachSubview:[UIImageView class] tag:1 action:^(__kindof UIView * _Nonnull subview) {
        
}];
    
[self.view ax_eachSubview:[UIButton class] selected:YES action:^(__kindof UIView * _Nonnull subview) {
        
}];

0.0.5 更新日志

NSUserDefaults

增加了ax_cacheObject,与ax_cacheValue功能不同。区别参考系统的setObjectsetValue

增加了ax_removeObjectForKey方法。

NSString

增加了NSStringFromASCIIValue(unsigned char ASCIIValue)函数,快速将ASCII码值转换成OC字符串。

增加了一个快速输出百分比的函数,将浮点型CGFloat数据转换成0%~100%的格式化字符串

NSStringFromPercent(CGFloat x);
// 当传入x为小于或等于0的数时,NSStringFromPercent(x)为@"0%"。
// 当传入x为大于0并且小于1的数如0.3时,NSStringFromPercent(0.3)为@"30%"。
// 当传入x为大于或等于1的数时,NSStringFromPercent(x)为@"100%"。

取值

增加了NSInteger类型和CGFloat类型的取值范围

增加了确保值在某个范围的方法,示例:

// 希望value在0~1之间
CGFloat value = sender.text.floatValue;
CGFloat result = AXFloatInRange(value, AXFloatRangeMake(0, 1));
// 当value取值小于0时,result为0;
// 当value取值大于0小于1时,result为value;
// 当value取值大于1时,result为1;

支持的数据类型有:

  • CGFloat
  • NSInteger
  • NSUInteger

UIViewController

增加了万能控制器跳转方法,传入目标控制器名,跳转到目标控制器
此方法是安全的,会有失败回调

/**
 push view controller

 @param vcName view controller name
 @param animated animated
 */
- (void)ax_pushViewControllerNamed:(NSString *)vcName animated:(BOOL)animated;

/**
 push view controller
 
 @param vcName view controller name
 @param animated animated
 @param completion completion
 */
- (void)ax_pushViewControllerNamed:(NSString *)vcName animated:(BOOL)animated completion:(void (^)(UIViewController *targetVC))completion;

/**
 push view controller
 
 @param vcName view controller name
 @param animated animated
 @param completion completion
 @param fail error info
 */
- (void)ax_pushViewControllerNamed:(NSString *)vcName animated:(BOOL)animated completion:(void (^)(UIViewController *targetVC))completion fail:(void (^)(NSError *error))fail;

NSError

增加了方便的创建Error实例的构造方法

/**
 创建一个error实例

 @param domain 域
 @param code 错误码
 @param description 描述
 @param reason 原因
 @param suggestion 建议
 @return error实例
 */
+ (instancetype)ax_errorWithDomain:(NSErrorDomain)domain code:(NSInteger)code description:(nullable NSString *)description reason:(NSString *)reason suggestion:(nullable NSString *)suggestion;

AXLog

AXLogError(NSError)增加了一个输出内容,0.0.4版本及其之前只输出error.localizedDescription,0.0.5及之后版本现在还会增加一行信息error.localizedFailureReason

UIBarButtonItem

增加了快速创建自定义BarItem的构造方法

/**
 快速创建一个baritem
 
 @param view 自定义视图
 @param action 响应的事件
 @return baritem实例
 */
+ (instancetype)ax_itemWithCustomView:(UIView *)view action:(void (^)(id sender))action;

0.0.13 更新日志

UIAlertController

删除了两个使用频率低的接口

更改这两个接口使其能够返回实例:

/**
 弹窗(标题+消息+自定义按钮)(如果action为nil,则只有一个确定按钮)
 @param title 标题
 @param message 消息
 @param action 按钮
 @return 返回alert对象
 */
+ (instancetype)ax_showAlertWithTitle:(nullable NSString *)title message:(nullable NSString *)message actions:(void (^ __nullable)(UIAlertController *alert))actions;
/**
 弹窗(标题+消息+自定义按钮)(如果action为nil,则只有一个确定按钮)
 @param title 标题
 @param message 消息
 @param action 按钮
 @return 返回alert对象
 */
+ (instancetype)ax_showActionSheetWithTitle:(nullable NSString *)title message:(nullable NSString *)message actions:(void (^ __nullable)(UIAlertController *alert))actions;

0.0.9 更新日志

快速创建UIActivityIndicatorView

UIActivityIndicatorView *indicator = [UIActivityIndicatorView defaultIndicator];
// @xaoxuu: 显示到self.view中心
indicator.show(self.view);
// @xaoxuu: 隐藏
indicator.hide();

功能简单不需要解释,下面有效果图

UIAlertController++

快速

// @xaoxuu: 一行代码的消息弹窗
[UIAlertController ax_showAlertWithTitle:@"Hello Alert" message:@"这是用一行代码弹出来的只有一个按钮的窗口" action:nil];

// @xaoxuu: 最常用的【取消】+【确定】弹窗
[UIAlertController ax_showAlertWithTitle:@"Hello Alert" message:@"这是用一个方法弹出来的有两个按钮的窗口" ok:^(UIAlertAction * _Nonnull sender) {
    AXLogFormat(@"点击了OK按钮");
}];

效果图:

只有一个按钮 两个按钮
simulator screen shot 29 may 2017 2 32 46 pm simulator screen shot 29 may 2017 2 33 37 pm

方法简单,但功能不受限

[UIAlertController ax_showAlertWithTitle:@"Hello Alert" message:@"这是用一个方法弹出来的完全自定义的系统弹窗" action:^(UIAlertController * _Nonnull alert) {
    // @xaoxuu: 添加取消按钮
    [alert ax_addCancelAction];

    // @xaoxuu: 破坏性按钮(标题为【Confirm】)
    [alert ax_addDestructiveActionWithTitle:nil handler:^(UIAlertAction * _Nonnull sender) {

    }];
    // @xaoxuu: 自定义标题的破坏性按钮
    [alert ax_addDestructiveActionWithTitle:@"删除2" handler:^(UIAlertAction * _Nonnull sender) {

    }];
    // @xaoxuu: 普通按钮(默认标题为【OK】)
    [alert ax_addDefaultActionWithTitle:nil handler:^(UIAlertAction * _Nonnull sender) {

    }];
    // @xaoxuu: 自定义标题的普通按钮
    [alert ax_addDefaultActionWithTitle:@"确定2" handler:^(UIAlertAction * _Nonnull sender) {

    }];

}];
// @xaoxuu: 自定义视图的系统弹窗
[UIAlertController ax_showAlertWithTitle:nil message:@"\n\n\n\n\n\n\n\n\n\n\n" action:^(UIAlertController * _Nonnull alert) {
    UIView *view = [[UIView alloc] initWithFrame:CGRectMake(8, 8, 270-16, 222.3-16)];
    view.backgroundColor = [UIColor md_yellow];
    view.layer.masksToBounds = YES;
    view.layer.cornerRadius = 8;

    [UIActivityIndicatorView defaultIndicator].show(view);

    [alert.view addSubview:view];

}];

效果图:

自定义按钮 自定义视图
simulator screen shot 29 may 2017 2 36 04 pm simulator screen shot 29 may 2017 2 45 07 pm

hidesBottomBarWhenPushed

hidesBottomBarWhenPushed

push到子控制器的时候隐藏底部tabbar。

此方法原本属于UIViewController,写在要push的viewController里。

如果一个导航控制器想要让所有push的子控制器都隐藏tabbar。

一般的做法是继承,在一个父类- (void)viewDidLoad中加上这么一行代码:

[self hidesBottomBarWhenPushed]; // available(0.0.6)

现在你有了另一种选择,“设置”这个导航控制器,让它push的子控制器都隐藏tabbar。

在导航控制器的- (void)viewDidLoad中加上这么一行代码:

[self ax_hidesBottomBarWhenPushed:YES]; // available(0.0.6)

作者注:

实现这个功能主要技术点是如何取消交换方法。

单纯地取消就是再交换一次,但是实际应用必须判断是否交换过,只有交换过才能再交换一次负负得正,否则会产生错乱。

为了判断是否交换过,我查阅了很多资料,也在很多技术群里询问,没有得到一个优雅的解决方案。只能采取比较笨的方法:就是在交换的时候做一个标记,通过标记值判断该方法指针是否指向原地址。

localize all subviews

之前我们实现了将某个控件的文本转换成支持多语言的文本NSLocalizedString详见 #3

而在0.0.6以后的版本,你可以用一行代码将本页面所有控件所有文本进行转换:

AXLocalizeAllSubviewsInView(self.view); // available(0.0.6)

这个方法建议在项目成型之前使用,避免了频繁更改造成代码混乱,也能够提高开发效率。

缺点是略微影响性能,可以在项目成型到无需大改的阶段之后删掉此代码,手动替换。

// @xaoxuu: 以下这些方法提供更加灵活的实现,可按需使用。
AXLocalizeLabel(self.label);
AXLocalizeTextField(self.textField);
AXLocalizeTextView(self.textView);
AXLocalizeAllLabelsInView(self.view);
AXLocalizeAllTextFieldsInView(self.view);
AXLocalizeAllTextViewsInView(self.view);

其实只要不那么极致要求性能的话,只要别用在tableview的cell里,一直留在项目里也是没有多大影响的。

0.0.6 更新日志

localize all subviews!

之前我们实现了将某个控件的文本转换成支持多语言的文本NSLocalizedString详见 #3

而在0.0.6以后的版本,你可以用一行代码将本页面所有控件所有文本进行转换:

AXLocalizeAllSubviewsInView(self.view); // available(0.0.6)

这个方法建议在项目成型之前使用,避免了频繁更改造成代码混乱,也能够提高开发效率。

缺点是略微影响性能,可以在项目成型�到无需大改的阶段之后删掉此代码,手动替换。

// @xaoxuu: 以下这些方法提供更加灵活的实现,可按需使用。
AXLocalizeLabel(self.label);
AXLocalizeTextField(self.textField);
AXLocalizeTextView(self.textView);
AXLocalizeAllLabelsInView(self.view);
AXLocalizeAllTextFieldsInView(self.view);
AXLocalizeAllTextViewsInView(self.view);

其实只要不那么极致要求性能的话,只要别用在tableview的cell里,一直留在项目里也是没有多大影响的。

修复了弹出键盘时调整输入框frame的bug

计算了被遮挡的高度offset,将view上移offset的高度。而不是上移一个keyboard的高度。

// @xaoxuu: 获取view距离底部的高度
CGFloat superH = self.ax_superview.frame.size.height;
CGFloat superF = self.ax_superview.frame.origin.y;
CGFloat heightToBottom = kScreenH - superF - superH;
// @xaoxuu: 被遮挡的高度
CGFloat offset = keyBoardHeight - heightToBottom;
if (offset < 0) {
    offset = 0;
}

NSStringFrom...

现在也可以快速将BOOL值、float值转换成字符串了。

调整了将int值转换成字符串的函数命名

// available(0.0.6)
FOUNDATION_EXTERN NSString *NSStringFromInt(int x);
// deprecated(0.0.5)
FOUNDATION_EXTERN NSString *NSStringFromInt32(int x);

万能控制器跳转

由于初代版本的疏忽,此功能理应成为UINavigationController的方法,却错误地放在了UIViewController的分类里。0.0.6修复了此bug,同时,为简版省去了animated:参数,默认为YES

现在你可以通过如下方式调用:

简版:

// available(0.0.6)
[self.navigationController ax_pushViewControllerNamed:@"tmpVC"];
// deprecated(0.0.5)
[self ax_pushViewControllerNamed:@"tmpVC" animated:YES];

完整版:

// available(0.0.6)
[self.navigationController ax_pushViewControllerNamed:@"tmpVC" animated:YES completion:^(UIViewController * _Nonnull targetVC) {
    // push completed call back
    targetVC.title = @"tmp";
} fail:^(NSError * _Nonnull error) {
    // push failed call back
    AXLogError(error);
}];

// deprecated(0.0.5)
[self ax_pushViewControllerNamed:@"tmpVC" animated:YES completion:^(UIViewController * _Nonnull targetVC) {
    // push completed call back
    targetVC.title = @"tmp";
} fail:^(NSError * _Nonnull error) {
    // push failed call back
    AXLogError(error);
}];

hidesBottomBarWhenPushed

push到子控制器的时候隐藏底部tabbar。

此方法本来属于UIViewController,写在要push的viewController里。

如果一个导航控制器想要让所有push的子控制器都隐藏tabbar。

一般的做法是继承,在一个父类- (void)viewDidLoad中加上这么一行代码:

[self hidesBottomBarWhenPushed]; // available(0.0.6)

现在你有了另一种选择,“设置”这个导航控制器,让它push的子控制器都隐藏tabbar。

在导航控制器的- (void)viewDidLoad中加上这么一行代码:

[self ax_hidesBottomBarWhenPushed:YES]; // available(0.0.6)

作者注:

实现这个功能主要技术点是如何取消交换方法。

单纯地取消就是再交换一次,但是实际应用必须判断是否交换过,只有交换过才能再交换一次负负得正,否则会产生错乱。

为了判断是否交换过,我查阅了很多资料,也在很多技术群里询问,没有得到一个优雅的解决方案。只能采取比较笨的方法:就是在交换的时候做一个标记,通过标记值判断该方法指针是否指向原地址。

更多方式选出子视图

之前我们只有一个方法来让某个view的每一个具有某些特征的子视图去执行一段代码,即:

// 以class来选定某些子视图,例如所有的button、所有的label等
// 让所有的按钮的标题为蓝色
[self.view ax_eachSubview:[UIButton class] action:^(__kindof UIView * _Nonnull subview) {
    UIButton *btn = subview;
    [btn setTitleColor:[UIColor md_blue] forState:UIControlStateNormal]; 
}];

现在你不仅可以通过类来选定,还可以通过tag值tag值区间

// 打印出所有tag为100的子视图
[self.view ax_eachSubviewWithTag:100 action:^(__kindof UIView * _Nonnull subview) {
    AXLogOBJ(subview);
}];
// 打印出所有tag值在0~100的子视图
[self.view ax_eachSubviewWithTags:AXIntegerRangeMake(0, 100) action:^(__kindof UIView * _Nonnull subview) {
    AXLogOBJ(subview);
}];

对于常用控件,可以更方便地选取:

// 让所有的按钮的标题为蓝色
[self.view ax_eachButtonInvokeAction:^(__kindof UIButton * _Nonnull button) {
    [button setTitleColor:[UIColor md_blue] forState:UIControlStateNormal];
}];

支持的控件有:UIButton、UILabel、UITextField、UITextView、UIImageView

自己重写的基于这些控件的子控件也可以被选取出来。

UIViewFromNibNamed

在开发中我经常需要写这一段代码:

UIView *tmpView = [[NSBundle mainBundle] loadNibNamed:@"tmpView" owner:nil options:nil].firstObject;

于是就有了UIViewFromNibNamed函数:

UIView *tmpView = UIViewFromNibNamed(@"tmpView"); // available(0.0.6)

kScreenBounds

我们经常把这几个宏作为开发必备的宏:

// available(0.0.6)
#define kScreenBounds [UIScreen mainScreen].bounds
// available(0.0.1)
#define kScreenW [UIScreen mainScreen].bounds.size.width
#define kScreenH [UIScreen mainScreen].bounds.size.height
#define kScreenCenterX (0.5 * kScreenW)
#define kScreenCenterY (0.5 * kScreenH)

给UIImageView先填充个颜色

在开发初期,美工的UI素材还没有做好,我们的ImageView不给图的时候一般都是空白,不利于测试。

自己去找的话,,,我真的没有时间。

但是写个工具的时间还是有的:

// 填充随机色
[self.imageView ax_fillWithRandomColor]; // available(0.0.6)

当然,你想填充指定的颜色也是可以的:

// 填充颜色
[self.imageView ax_fillWithColor:[UIColor md_green]]; // available(0.0.6)

隐藏导航栏返回按钮标题

接口:

@interface UINavigationItem (AXExtension)

/**
 隐藏返回按钮的标题
 */
- (void)ax_hideBackBarButtonTitle;

/**
 隐藏返回按钮(同时也不能右划返回)
 */
- (void)ax_hideBackBarButton;

@end

实现:

@implementation UINavigationItem (AXExtension)

/**
 隐藏返回按钮的标题
 */
- (void)ax_hideBackBarButtonTitle{
    self.backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:nil action:nil];
}


/**
 隐藏返回按钮(同时也不能右划返回)
 */
- (void)ax_hideBackBarButton{
    self.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:nil action:nil];
}


@end

更灵活的popViewController

有时候想pop到从RootVC开始数的第二个VC怎么办?虽然实现并不复杂,但是这些可自动化的工作能封装起来用着自然舒服很多。
于是我封装了两个更灵活的pop方法:

/**
 pop到指定viewController

 @param index 从rootVC开始向后数的index,rootVC为0
 */
- (void)ax_popToViewControllerWithIndexFromRoot:(NSUInteger)index;

/**
 pop到指定viewController

 @param index 从当前viewController开始向前数的index,当前VC为0
 */
- (void)ax_popToViewControllerWithIndexFromSelf:(NSUInteger)index;

使用示例:
我在一个view里放置了两列按钮,一列是从RootVC开始数index,另一列是反向从当前VC开始数index。

- (IBAction)popFromRoot:(UIButton *)sender {
    [self.controller.navigationController ax_popToViewControllerWithIndexFromRoot:sender.titleLabel.text.integerValue];
    // 传入参数为几,就pop到从rootVC开始向下数的第几层VC。
}
- (IBAction)popFromSelf:(UIButton *)sender {
    [self.controller.navigationController ax_popToViewControllerWithIndexFromSelf:sender.titleLabel.text.integerValue];
    // 传入参数为几,就向前pop几层。
}

0.0.8 更新日志

NSString+

字符串其实可以干更多事

  • 转URL
  • 判断是不是URL
  • 转Image
- (nullable NSURL *)absoluteURL;

- (BOOL)isURLString;

- (nullable UIImage *)image;

例如我们获取到一个"URLString",用来显示用户头像

NSString *tmp = @"https://xaoxuu.com/images/avatar.png";
// 需要用到URL的话,就是tmp.absoluteURL
// 需要判断它是不是合法的URL就
if (tmp.isURLString) {
  // 是URL
} else {
  // 不是URL
}

例如资源图片名为"test.png"

// 有一个ImageView名为imgv
imgv.image = @"test".image;

做了一点简单的封装,让代码更简单

隐藏系统自带的NavigationBar/TabBar分割线?

两个类都添加了一个移除分割线的方法:

/**
 移除系统自带的分割线
 */
- (void)ax_hideSeparator;

注意:分割线不是一开始就有的,因此建议都写在- viewDidLayoutSubviews中。

使用示例:

- (void)viewDidLayoutSubviews{
    [super viewDidLayoutSubviews];
    [self.tabBar ax_hideSeparator];
}

判断颜色是深色还是浅色?

/**
 粗略判断颜色是不是浅色调

 @return 是不是浅色
 */
- (BOOL)isLightColor;

例如判断背景颜色是浅色的话,文字颜色设为主题色,如果背景颜色是深色的话,文字颜色为白色:

// 假设view上面有一个label
if (view.backgroundColor.isLightColor) {
    label.textColor = axColor.theme;
} else {
    label.textColor = axColor.white;
}

0.0.14 更新日志

#if DEBUG的简单封装

函数很简单,能够提供一点便利,毕竟函数的调用比写宏更加快捷而且不易出错。

声明:

/**
 只在debug模式下运行的函数
 
 @param debug debug操作
 */
FOUNDATION_EXTERN void ax_debug_only(void (^debug)());

实现:

inline void ax_debug_only(void (^debug)()){
#ifdef DEBUG
    if (debug) {
        debug();
    }
#endif
}

0.0.11 更新日志

移除所有偏好设置

移除standardUserDefaults所有偏好设置

[NSUserDefaults ax_removeDefaultPersistentDomain];

声明:

/**
 移除默认的[NSUserDefaults standardUserDefaults]的所有配置
 */
+ (void)ax_removeDefaultPersistentDomain;

获取启动图片

// 启动图片
UIImage *img = [NSBundle ax_appLaunchImage];

声明:

/**
 启动图片路径

 @return 启动图片路径
 */
+ (NSString *)ax_appLaunchImagePath;

/**
 启动图片

 @return 启动图片
 */
+ (UIImage *)ax_appLaunchImage;

UITextField placeholder颜色

使用示例:

// 将textField的placeholder颜色设为主题色
textField.placeholderColor = axColor.theme;

获取一个类的所有子类

声明:

FOUNDATION_EXTERN NSArray *NSClassGetAllSubclasses(Class cls);

示例:

NSArray *arr = NSClassGetAllSubclasses([UIColor class]);
AXLogOBJ(arr);

// LOG信息如下:
2017-06-30 10:42:42.380764+0800 AXKitDemo[5400:2416565] 
➤ func:-[DebugVC viewDidLoad] line:22
💬[
NSColor,
UICIColor,
UIDisplayP3Color,
UICGColor,
UICachedDevicePatternColor,
UIDeviceWhiteColor,
UICachedDeviceWhiteColor,
UIDeviceRGBColor,
UICachedDeviceRGBColor,
UIPlaceholderColor
]

NSUserDefaults保存图片

使用示例:

// 保存图片
[NSUserDefaults ax_setImage:newImage forKey:@"AVATAR"];

// 读取图片
[NSUserDefaults ax_readImageForKey:@"AVATAR" completion:^(UIImage * _Nonnull image) {
    // 读取成功
    self.avatar.image = image;
} failure:^(NSError * _Nonnull error) {
    // 读取失败
    AXLogOBJ(error);
}];

UIAlertController创建ActionSheet

使用方法和alertView相同:(详情请见 #21

[UIAlertController ax_showActionSheetWithTitle:@"操作表" message:@"操作表描述" action:^(UIAlertController * _Nonnull alert) {
    [alert ax_addCancelAction];
    [alert ax_addDefaultActionWithTitle:@"确定" handler:^(UIAlertAction * _Nonnull sender) {

    }];
    [alert ax_addDestructiveActionWithTitle:@"删除" handler:^(UIAlertAction * _Nonnull sender) {

    }];
}];

声明:

/**
 弹窗(标题+消息+自定义按钮)(如果action为nil,则只有一个确定按钮)
 
 @param title 标题
 @param message 消息
 @param action action
 */
+ (void)ax_showActionSheetWithTitle:(nullable NSString *)title message:(nullable NSString *)message action:(void (^ __nullable)(UIAlertController *alert))action;


/**
 弹出一个【取消+确定】两个按钮的弹窗(如果action为nil,则只有一个确定按钮)
 
 @param title 标题
 @param message 消息内容
 @param ok 确定按钮事件
 */
+ (void)ax_showActionSheetWithTitle:(nullable NSString *)title message:(nullable NSString *)message ok:(void (^ __nullable)(UIAlertAction *sender))ok;

更改了默认颜色配置方法

示例:(AppDelegate.m)

// @xaoxuu: 配置主题色
[[UIColorManager sharedInstance] configDefaultTheme:^(UIThemeColorModel * _Nonnull color) {
    color.theme = [UIColor md_amber];
    color.accent = [UIColor md_lime];
    color.background = [UIColor whiteColor];
}];
// 更改axColor的颜色将不会自动缓存,需要调用[axColor saveCurrentTheme]进行缓存。
[axColor saveCurrentTheme];

0.0.4 更新日志

注释

补充了部分接口的注释

NSString

NSString分类增加了拼接字符串的快捷方法
用法示例:

NSString *str = @"abc".append(@"d").appendCGFloat(1.2).appendReturn().appendNSInteger(50);
NSLog(@"%@",str);

控制台输出为:

2017-04-14 14:32:53.534 AXKitDemo[17111:290832] abcd1.2
50

接口:

/**
 拼接字符串
 */
- (NSString *(^)(NSString *string))append;

/**
拼接NSInteger
 */
- (NSString *(^)(NSInteger x))appendNSInteger;

/**
 拼接NSUInteger
 */
- (NSString *(^)(NSUInteger x))appendNSUInteger;

/** 
 拼接CGFloat
 */
- (NSString *(^)(CGFloat x))appendCGFloat;

/**
 拼接@"\n"
 */
- (NSString *(^)())appendReturn;

NSTimer

修改了定时器重启方法使之更符合实际功能

// 0.0.3 定时器“恢复”,易产生歧义
- (BOOL)ax_resume;

// 0.0.4 定时器重新开始计时
- (BOOL)ax_restart;

UIBarButtonItem

增加了两个baritem方法

/**
 创建一个baritem

 @param image 图片名
 @param action 响应的事件
 @return baritem实例
 */
+ (instancetype)ax_itemWithImageName:(NSString *)image action:(void (^)(id sender))action;

/**
 快速创建一个baritem

 @param title 标题
 @param action 响应的事件
 @return baritem实例
 */
+ (instancetype)ax_itemWithTitle:(NSString *)title action:(void (^)(id sender))action;

UIColor

更改了获取颜色某个通道的方法

0.0.3 0.0.4
- (CGFloat)getRed; - (CGFloat)redValue;
- (CGFloat)getGreen; - (CGFloat)greenValue;
- (CGFloat)getBlue; - (CGFloat)blueValue;
- (CGFloat)getAlpha; - (CGFloat)alphaValue;

UINavigationController

增加了配置全局hidesBottomBarWhenPushed的方法

需要隐藏时在所属的NavigationController中调用:

// 隐藏
[self ax_hidesBottomBarWhenPushed:YES];
// 不隐藏
[self ax_hidesBottomBarWhenPushed:NO];

接口:

- (void)ax_hidesBottomBarWhenPushed:(BOOL)hide;

UIResponder

增加了获取RootVC的方法

UIViewController、UIView、UIButton等类中均可使用self.rootVC来获取它所在的根控制器

使用示例:

UIViewController *rootVC = self.rootVC;

接口:

- (UIViewController *)rootVC;

0.0.7 更新日志

UIImageViewWithImageNamed

根据图片名快速创建imageview

UIImageViewWithImageNamed(NSString *name);

更灵活的popViewController

有时候你可能会需要pop到上上一层控制器,或者根控制器下的第二个控制器等等,

有了这两个方法,你可以pop到同一NavigationController下的任意一个控制器。

/**
 pop到指定viewController

 @param index 从rootVC开始向后数的index,rootVC为0
 */
- (void)ax_popToViewControllerWithIndexFromRoot:(NSUInteger)index;

/**
 pop到指定viewController

 @param index 从当前viewController开始向前数的index,当前VC为0
 */
- (void)ax_popToViewControllerWithIndexFromSelf:(NSUInteger)index;

详细使用请见 #14

NSUserDefaults+

封装了NSUserDefaults,对读取的值可能为空和不为空的情况分类处理,更安全和方便。例如:

// @xaoxuu: 将用户头像缓存到userdefault
[NSUserDefaults ax_setData:UIImagePNGRepresentation(image) forKey:@"avatar"];
// @xaoxuu: 从userdefault读取图片
[NSUserDefaults ax_readDataForKey:@"avatar" completion:^(NSData * _Nonnull data) {
    // @xaoxuu: 读取到值
    UIImage *image = [UIImage imageWithData:data];
    avatar.image = image;
} fail:^(NSError * _Nonnull error) {
    // @xaoxuu: 读取不到值
    AXLogError(error);
}];

详细使用请见 #13

代码冷却 : cooldown

我个人认为设计合理的代码是用不到这个机制的,

但是不能保证我们永远不需要,所以我就提供了这个冷却机制。

优点:执行代码像放技能一样,可以强行打破死循环、避免死循环、避免过高频率访问某一资源、从一定程度上缓解了内存、CPU压力。

缺点:治标不治本,最好是找出会产生问题的代码,从根源上解决问题。

使用示例:

// @xaoxuu: 重新获取数据源并刷新tableView
- (void)reloadDataSourceAndTableView{
    [NSBlockOperation ax_delay:0 cooldown:2 token:@"reload data source and refresh table view" performInMainQueue:^{
        [self.dataList removeAllObjects];
        [self reloadTableView];
    }];
}

详细使用请见 #15

NSStringFrom...

NSStringFromBool

Convert a boolean value to Objective-C string.

将BOOL值转换成Objective-C字符串

NSString *string = NSStringFromBool(BOOL x);
// x = YES, string = @"1"
// x = NO,  string = @"0"

NSStringFromFloat

Convert a float value to Objective-C string.

将float类型转换成Objective-C字符串

NSString *string = NSStringFromFloat(float x);
// x = 1,    string = @"1"
// x = 3.14, string = @"3.14"

NSStringFromCGFloat

Convert a CGFloat value to Objective-C string.

将CGFloat类型转换成Objective-C字符串

NSString *string = NSStringFromCGFloat(CGFloat x);
// x = 1,    string = @"1"
// x = 3.14, string = @"3.14"

NSStringFromInt / NSInteger / NSUInteger

Convert a int / NSInteger / NSUInteger to Objective-C string.

将int类型、NSInteger类型、NSUInteger类型转换成Objective-C字符串

NSString *string1 = NSStringFromInt(int x);
NSString *string2 = NSStringFromNSInteger(int x);
NSString *string3 = NSStringFromNSUInteger(int x);
// x = 1, string1 = @"1", string2 = @"1", string3 = @"1"

NSStringFromPointer

Convert a pointer to Objective-C string.

将id类型指针地址转换成Objective-C字符串

NSString *string = NSStringFromPointer(id x);
// string may be anything like @"0x10b70a5c0"...

NSStringFromPercent

Convert a percent to Objective-C string.

将百分比数值(float,取值0~1)转换成Objective-C字符串

NSString *string = NSStringFromPercent(id x);
// x < 0 or x = 0, string = @"0%"
// x = 0.123, string = @"12.3%"
// x > 1 or x = 1, string = @"100%"

NSStringFromASCIIValue

Convert a ASCII value to Objective-C string.

将单个ASCII码转换成Objective-C字符串

NSString *string = NSStringFromASCIIValue(id x);
// x = 32, string = @" "
// x = 48, string = @"0"
// x = 65, string = @"A"
// x = 90, string = @"Z"
// x = 97, string = @"a"
// x = 122, string = @"z"

弹出键盘时调整高度的方法"ax_adjustViewFrameWithKeyboard"崩溃

弹出键盘时调整高度,传入的View为self.view时崩溃

[self.tf_desc ax_adjustViewFrameWithKeyboard:self.view];

报错:

 *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UITextField setAx_superview:]: unrecognized selector sent to instance 0x1588d650'

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.