一些实用的Category(自用(不断更新

有个问题...
写的时候我设置了诸如<a href="#string_vre">以及<a id="string_vre">的锚点...但是点击没有反应....大家有没有解决的办法???


索引

NSString
<a href="#string_vre">· 匹配正则表达式</a>
NSNumber
<a href="#number_format">· 返回有千分位符号的格式字符串</a>
NSDictionary
<a href="#dictionary_font_color">· 获取字体颜色属性字典(富文本结合使用)</a>
NSAttributedString
<a href="#attrbute_string_font_color">· 获取由两种字体颜色组成的富文本</a>
UIColor
<a href="#color_hex">· 设置颜色(以0x123456格式输入)</a>
UIView
<a href="#view_corner">· 设置圆角</a>
<a href="#view_alert">· 添加/移去一个警示标语</a>
<a href="#view_shadow">· 给View的四周设置阴影</a>
UIButton
<a href="#button_timer">· 添加一个倒数计时器</a>
UIScrollView
<a href="#scrollview_offset">· 设置自动偏移量</a>
UIBarButtonItem
<a href="#bar_button_item_back">· 返回按键[new]</a>


NSString

<a id="string_vre">· 匹配正则表达式(对用户输入信息进行正则匹配</a>

.h
typedef NS_ENUM(NSUInteger, VREType) {
    VRETypeUsername = 0, // 用户名
    VRETypeIDCard,  // 身份证号码
    VRETypeBankCard,  // 银行卡号码
    VRETypePhoneNumber,  // 电话号码
    VRETypePassword, // 密码
    VRETypeAddressName,  // 姓名
    VRETypePostalcode,  // 邮箱
    VRETypeAddress,  // 地址
    VRETypeVerifyCode  // 验证码
};
- (BOOL)isValidateRegularExpressionWithType:(VREType)type;
.m
- (BOOL)isValidateRegularExpressionWithType:(VREType)type {
    
    static NSDictionary *verDict;
    if (!verDict) {
        verDict = @{@(VRETypeUsername) : @"^.{1,20}$",
                 @(VRETypeIDCard) : @"^.{18}$",
                 @(VRETypeBankCard) : @"(\\d|\\s){16,22}",
                 @(VRETypePhoneNumber) : @"\\d{11}",
                 @(VRETypePassword) : @"^([a-zA-Z]+|\\d+){8,16}$",
                 @(VRETypeAddressName) : @"^.{1,20}$",
                 @(VRETypePostalcode) : @"\\d{6}",
                 @(VRETypeAddress) : @"^.{0,128}$",
                 @(VRETypeVerifyCode) : @"^[A-Za-z0-9]{4}$"};
    }
    
    if (!verDict[@(type)]) {
        NSLog(@"正则表达式不存在");
        return NO;
    }
    
    NSPredicate * predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", verDict[@(type)]];
    return [predicate evaluateWithObject:self];
}

NSNumber

<a id="number_format">· 返回一个NSString类型的具有千分位逗号的数字</a>

.h
- (NSString *)formaterWithDecimalStyle;
.m
- (NSString *)formaterWithDecimalStyle {
    
    NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
    formatter.numberStyle = NSNumberFormatterDecimalStyle;
    return [formatter stringFromNumber:self];
}

NSDictionary

<a id="dictionary_font_color">· 获得一个存放字体和颜色属性的字典(和富文本搭配使用</a>

.h
+ (instancetype)attrDictWithFont:(UIFont *)font color:(UIColor *)color;
+ (instancetype)attrDictWithFont:(UIFont *)font color:(UIColor *)color {
    NSMutableDictionary *mDict = [[NSMutableDictionary alloc] init];
    if (font) {
        [mDict setObject:font forKey:NSFontAttributeName];
    }
    if (color) {
        [mDict setObject:color forKey:NSForegroundColorAttributeName];
    }
    return mDict;
}

NSAttributedString

<a id="attrbute_string_font_color">· 获得一个富文本,可以由两种字体和颜色组成(两种比较常用</a>

.h
+ (instancetype)attributedStringWithString:(NSString *)string attributes:(nullable NSDictionary<NSString *, id> *)attr subStr:(NSString *)subStr subStrAttributes:(nullable NSDictionary<NSString *, id> *)subStrAttr;
+ (instancetype)attributedStringWithString:(NSString *)string attributes:(nullable NSDictionary<NSString *, id> *)attr subStr:(NSString *)subStr subStrAttributes:(nullable NSDictionary<NSString *, id> *)subStrAttr {
    
    NSMutableAttributedString *attrStr = [[NSMutableAttributedString alloc] init];
    [attrStr appendAttributedString:[[NSAttributedString alloc] initWithString:string attributes:attr]];
    if (subStr) {
        [attrStr appendAttributedString:[[NSAttributedString alloc] initWithString:subStr attributes:subStrAttr]];
    }
    return attrStr;
}

UIColor

<a id="color_hex">· 设置颜色(16位颜色值转换RGB</a>

.h
+ (UIColor *)colorWithHex:(NSInteger)hexValue;
+ (UIColor *)colorWithHex:(NSInteger)hexValue alpha:(CGFloat)alphaValue;
.m
+ (UIColor *)colorWithHex:(NSInteger)hexValue {
     return [self colorWithHex:hexValue alpha:1.0];
}

+ (UIColor *)colorWithHex:(NSInteger)hexValue alpha:(CGFloat)alphaValue {
    return [self colorWithRed:((float)((hexValue & 0xFF0000) >> 16)) / 255.0
                           green:((float)((hexValue & 0xFF00) >> 8)) / 255.0
                            blue:((float)(hexValue & 0xFF)) / 255.0 alpha:alphaValue];
}

UIView

<a id="view_corner">· 对View设置圆角(在layoutSubviews里面进行调用 (适合少数量View的圆角设置</a>

.h
- (void)makeCornerWithRadius:(float)radius;
.m
- (void)makeCornerWithRadius:(float)radius {
    self.layer.cornerRadius = self.frame.size.width * radius;
    self.layer.masksToBounds = YES;   
}

<a id="view_alert">· 添加/移去一个警示标语(当用户在TextField里面输入了错误信息的时候提示使用</a>

.h
- (void)showRegularExpressionAlertMessage:(NSString *)message;
- (void)removeRegularExpressionAlertMessage;
.m
#define kSubViewTag 1024
- (void)showRegularExpressionAlertMessage:(NSString *)message {
    if ([self viewWithTag:kSubViewTag]) return;
    UILabel *label = [[UILabel alloc] init];
    [self addSubview:label];
    label.text = message;
    label.backgroundColor = [[UIColor redColor] colorWithAlphaComponent:0.2];
    label.textColor = [UIColor redColor];
    label.alpha = 0;
    label.tag = kSubViewTag;
    label.font = [UIFont systemFontOfSize:13];
    label.textAlignment = NSTextAlignmentRight;
    label.frame = CGRectMake(self.frame.size.width, 0, self.frame.size.width, self.frame.size.height);
    [UIView animateWithDuration:0.3 animations:^{
        CGRect frame = label.frame;
        frame.origin.x = 0;
        label.frame = frame;
        label.alpha = 1;
    }];
}

- (void)removeRegularExpressionAlertMessage {
    UIView *view = [self viewWithTag:kSubViewTag];
    if (view) {
        [UIView animateWithDuration:0.5 animations:^{
            CGRect frame = view.frame;
            frame.origin.x = self.frame.size.width;
            view.frame = frame;
            view.alpha = 0;
        } completion:^(BOOL finished) {
            [view removeFromSuperview];
        }];
    }
}

这里是直接盖一层控件上去,也可以直接修改原View的layer,比如一个小红框(需要提示的View拿到了,自然由我们折腾。

<a id="view_shadow">· 给View的四周添加阴影,阴影的效果(这里是画出四个二元曲线</a>

.h
- (void)makeShadow;
.m
- (void)makeShadow {
    self.layer.shadowColor = [UIColor colorWithHex:0x6e6e6e].CGColor;//shadowColor阴影颜色
    self.layer.shadowOffset = CGSizeMake(0,0);//shadowOffset阴影偏移,默认(0, -3),这个跟shadowRadius配合使用
    self.layer.shadowOpacity = 1;//阴影透明度,默认0
    self.layer.shadowRadius = 2;//阴影半径,默认3
    
    //路径阴影
    UIBezierPath *path = [UIBezierPath bezierPath];
    
    float width = self.bounds.size.width;
    float height = self.bounds.size.height;
    float x = self.bounds.origin.x;
    float y = self.bounds.origin.y;
    float addWH = 10;
    
    CGPoint topLeft     = self.bounds.origin;
    CGPoint topRight    = CGPointMake(x+width,y);
    CGPoint bottomRight = CGPointMake(x+width,y+height);
    CGPoint bottomLeft  = CGPointMake(x,y+height);
    
    CGPoint topMiddle    = CGPointMake(x+(width/2),y-addWH);
    CGPoint leftMiddle   = CGPointMake(x-addWH,y+(height/2));
    CGPoint rightMiddle  = CGPointMake(x+width+addWH,y+(height/2));
    CGPoint bottomMiddle = CGPointMake(x+(width/2),y+height+addWH);
    
    [path moveToPoint:topLeft];
    //添加四个二元曲线
    [path addQuadCurveToPoint:topRight
                 controlPoint:topMiddle];
    [path addQuadCurveToPoint:bottomRight
                 controlPoint:rightMiddle];
    [path addQuadCurveToPoint:bottomLeft
                 controlPoint:bottomMiddle];
    [path addQuadCurveToPoint:topLeft
                 controlPoint:leftMiddle];
    //设置阴影路径
    self.layer.shadowPath = path.CGPath;
}

UIButton

<a id="button_timer"> · 一句代码实现初始化一个发送验证码倒计时的Button(在ViewDidLoad里面就可以初始化(在开始的Block里面调用接口UIButton </a>

2016.5.27 update

对计时机制做了优化。
原始的方式是通过内存中存储的count数进行递减。
当app处于后台的时候,程序并没有持续进行,实际的时间差和显示的有出入。
更新使用了本地时间戳来判断,较原先方法更为准确。
同时对移除控件时候做了判断,清除缓存数据。

.h
typedef void(^StartBlock)(void);
typedef void(^CompleteBlock)(void);
- (void)addTimerForVerifyWithInterval:(NSUInteger)interval start:(StartBlock)startBlock complete:(CompleteBlock)completeBlock;
.m
#define kVerifyMsgTake @"获取验证码"
#define kVerifyMsgDidToke @"验证码已发送"
#define kVerifyMsgLoad @"秒后重新获取"

static const char *verifyStartBlockKey    = "verifyStartBlockKey";     // 开始回调
static const char *verifyCompleteBlockKey = "verifyCompleteBlockKey";  // 完成回调
static const char *verifyTimerKey         = "verifyTimerKey";          // 计时器
static const char *verifyStatusKey        = "verifyStatusKey";         // 状态(移除时候判断用
static const char *verifyIntervalKey      = "verifyIntervalKey";       // 总时间
static const char *verifyStartIntervalKey = "verifyStartIntervalKey";  // 开始时间戳

#pragma mark -
- (void)addTimerForVerifyWithInterval:(NSUInteger)interval start:(StartBlock)startBlock complete:(CompleteBlock)completeBlock {
    
    [self setTitle:kVerifyMsgTake forState:UIControlStateNormal];
    
    [self addTarget:self action:@selector(verifyButtonClick:) forControlEvents:UIControlEventTouchUpInside];
    
    if (startBlock) {
        objc_setAssociatedObject(self, verifyStartBlockKey, startBlock, OBJC_ASSOCIATION_COPY_NONATOMIC);
    }
    if (completeBlock) {
        objc_setAssociatedObject(self, verifyCompleteBlockKey, completeBlock, OBJC_ASSOCIATION_COPY_NONATOMIC);
    }
    objc_setAssociatedObject(self, verifyIntervalKey, @(interval), OBJC_ASSOCIATION_ASSIGN);
    objc_setAssociatedObject(self, verifyStatusKey, @(YES), OBJC_ASSOCIATION_ASSIGN);
}

- (void)verifyButtonClick:(UIButton *)button {
    if (!button.enabled) return;
    
    long long startTime = [[NSDate date] timeIntervalSince1970];
    objc_setAssociatedObject(self, verifyStartIntervalKey, @(startTime), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    
    void(^startBlock)(void) = objc_getAssociatedObject(self, verifyStartBlockKey);
    if (startBlock) {
        startBlock();
    }
    
    button.enabled = NO;
    [button setTitle:kVerifyMsgDidToke forState:UIControlStateDisabled];
    
    [self startTimer];
}

- (void)startTimer {
    NSTimer *timer = objc_getAssociatedObject(self, verifyTimerKey);
    if (!timer) {
        timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(reloadTimeStatus) userInfo:nil repeats:YES];
        [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
        objc_setAssociatedObject(self, verifyTimerKey, timer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
}

- (void)stopTimer {
    NSTimer *timer = objc_getAssociatedObject(self, verifyTimerKey);
    if (timer) {
        [timer invalidate];
        timer = nil;
        objc_setAssociatedObject(self, verifyTimerKey, timer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
}

- (void)reloadTimeStatus {
    long long nowTime = [[NSDate date] timeIntervalSince1970];
    long long startTime = [objc_getAssociatedObject(self, verifyStartIntervalKey) longLongValue];
    int totalTime = [objc_getAssociatedObject(self, verifyIntervalKey) intValue];
    
    if (nowTime - startTime >= totalTime) {
        [self stopTimer];
        self.enabled = YES;
        
        void(^completeBlock)(void) = objc_getAssociatedObject(self, verifyCompleteBlockKey);
        
        if (completeBlock) {
            completeBlock();
        }
        return;
    }
    [self setTitle:[NSString stringWithFormat:@"%lld%@", totalTime - (nowTime - startTime), kVerifyMsgLoad] forState:UIControlStateDisabled];
}

- (void)removeFromSuperview {
    if ([objc_getAssociatedObject(self, verifyStatusKey) boolValue]) {
        objc_removeAssociatedObjects(self);
    }
    [super removeFromSuperview];
}

UIScrollView

<a id="scrollview_offset">· 设置ScrollView的偏移(用户输入信息的时候浮动TextField</a>

- (void)moveWithOffset:(CGFloat)offset;
- (void)moveWithOffset:(CGFloat)offset {
    if (self.contentInset.top != offset) {
        [UIView animateWithDuration:0.3 animations:^{
            self.contentInset = UIEdgeInsetsMake(offset, 0, 0, 0);
        }];
    }
}

UIBarButtonItem

<a id="bar_button_item_back">· 导航栏被自定义,或者某个页面需要对导航栏的返回按键单独处理的时候可以使用(单纯为了节约代码)
建议根据需求把图片名字或者Title提出来作为参数。</a>

.h
+ (instancetype)backBarButtonWithTarget:(id)target action:(SEL)action;
.m
+ (instancetype)backBarButtonWithTarget:(id)target action:(SEL)action {

    UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
    [button setImage:[UIImage imageNamed:@"一张返回图片"] forState:UIControlStateNormal];
    button.frame = CGRectMake(0, 0, 30, 30);
    // 控制图片的缩进大小
    [button setImageEdgeInsets:UIEdgeInsetsMake(0, 0, 0, 0)];
    [button addTarget:target action:action forControlEvents:UIControlEventTouchUpInside];
    return [[self alloc] initWithCustomView:button];
}

GitHub传送门:ZExtensions

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,716评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,558评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,431评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,127评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,511评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,692评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,915评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,664评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,412评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,616评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,105评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,424评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,098评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,096评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,869评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,748评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,641评论 2 271

推荐阅读更多精彩内容

  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 11,618评论 4 59
  • 无数V商小白踊跃加入行业,多为一个钱字。门槛低意味着起点低,起点低也就意味着行业从业人员总体实力被拉低。几乎...
    熙熙Breathe阅读 529评论 0 10
  • 《枫林谷的风》 尽管,一季繁华殆尽 在这晚秋的相遇中 再次陪我在秋凉里轻轻相拥 在秋风里看那叶落成诗 ——光 在秋...
    光诗燃梦阅读 954评论 52 65
  • 首先自我介绍,我是NiceDay,一名交互小白,15年来到春暖花开的深圳工作。 公司入职半年有余,手里的项目陆续结...
    NiceDay阅读 652评论 3 5