iOS開發(fā)那些奇技淫巧和工具類收集

iOS開發(fā)小技巧和常用工具類(平時收集和整理)

前言

作為一個開發(fā)者應該學會去整理收集開發(fā)常用的工具類,這些復用的工具可以在項目開發(fā)中給你很大程度提高你的工作效率。難道你不想早點完成工作,然后出去撩妹、陪女朋友或者回家陪老婆孩子嗎?反正我想早點回家??。

更新

2017-12-12 PM 重新編輯

  1. 使用Pod管理公共類(常用的工具類和分類)傳送門-->
  2. 為后期的組件化學習和項目重構做準備

想學習的小伙伴歡迎一起哈

如果想了解新的內(nèi)容請關注github

由于工作原因(其實是本人比較懶) 文章更新會很慢或者忘記更新,關于更新的說明: 文章中只提供方法名說明在俺的github上可以找到具體實現(xiàn)

小方法小技巧大用處(我的github沒有哦)

建好Base類
BaseViewController

所有的控制器繼承于這個base,在此基類你可以對所有控制器共同的屬性和方法進行控制。比如設置控制器View的背景色,下面是我的base,只供參考

BaseViewController.h

@interface BaseViewController : UIViewController
@property (nonatomic, assign)VCType vcType;
@property (nonatomic, strong)id vcParam;

- (void)push:(NSString *)vcName;
- (void)push:(NSString *)vcName param:(id)param;
- (void)openWeb:(NSString *)urlStr title:(NSString *)title;

@end

BaseViewController.m

- (void)push:(NSString *)vcName{
    Class classVC = NSClassFromString(vcName);
    UIViewController *vc = [classVC new];
    [self.navigationController pushViewController:vc animated:YES];
}
- (void)push:(NSString *)vcName param:(id)param{
    Class classVC = NSClassFromString(vcName);
    BaseViewController *vc = [classVC new];
    vc.vcParam = param;
    [self.navigationController pushViewController:vc animated:YES];
}
- (void)openWeb:(NSString *)urlStr title:(NSString *)title{
    WebViewController *vc = [[WebViewController alloc]init];
    vc.strUrl = urlStr;
    vc.title = title;
    [self.navigationController pushViewController:vc animated:YES];
}
BaseLabel、BaseTextField、BaseTableViewCell和BaseButton等等我就不一一列舉了

在這些基類中可以設置常用的初始化設置,比如我常用的label字體是15號黑色等
分享個親身經(jīng)歷:有一次項目經(jīng)理要求把所有輸入框的光標顏色改為主題色,當時我用的是擴展替換了初始化方法,如果當時我有這個基類就可以一句代碼搞定了?_?

runtime輕松搞定初始化UITabBarController
- (void)initTabBarWithTitles:(NSArray *)titles
                     vcNames:(NSArray *)classes
                      images:(NSArray *)images
              selectedImages:(NSArray *)selectedImages{
    
    NSDictionary *nomalTextDic = @{NSFontAttributeName:[UIFont boldSystemFontOfSize:12.0],
                                   NSForegroundColorAttributeName:UIColorFromRGB(MAIN_GRY_COLOR)};
    
    NSDictionary *higjlightTextDic = @{NSFontAttributeName:[UIFont boldSystemFontOfSize:12.0],
                                       NSForegroundColorAttributeName:UIColorFromRGB(THEME_COLOR)};
    
    NSMutableArray *vcArray = [NSMutableArray array];
    
    for (int i = 0;i < titles.count ; i ++) {
        UITabBarItem *first_item = [[UITabBarItem alloc]initWithTitle:titles[i] image:[UIImage imageWithFileName:images[i]] selectedImage:[[UIImage imageWithFileName:selectedImages[i]]imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]];
        first_item.imageInsets = UIEdgeInsetsMake(0, 0, 0, 0);
        [first_item setTitleTextAttributes:nomalTextDic forState:UIControlStateNormal];
        [first_item setTitleTextAttributes:higjlightTextDic forState:UIControlStateSelected];
        first_item.tag = VCType_First + i;
        Class classVC = NSClassFromString(classes[i]);
        BaseViewController *vc = [classVC new];
        vc.tabBarItem = first_item;
        [vcArray addObject:vc];
    }
    self.viewControllers = vcArray;
    
}
推薦ReactiveCocoa
準備工作
在這里我只介紹一個我經(jīng)常用到的小方法:由于現(xiàn)在做的項目很多頁面需要打開系統(tǒng)相冊和相機所以簡單封裝了一個打開系統(tǒng)相機和相冊的方法

VDImagePicker.h

@interface VDImagePicker : UIImagePickerController
+ (void)pickImageWithController:(id)vc sourceType:(UIImagePickerControllerSourceType)sourceType callback:(void(^)(UIImage *image))callback;

@end

VDImagePicker.m

#import "VDImagePicker.h"
#import <ReactiveCocoa/ReactiveCocoa.h>

@interface VDImagePicker ()
@property (nonatomic, copy)void (^callback)(UIImage *image);

@end

@implementation VDImagePicker

+ (void)pickImageWithController:(id)vc sourceType:(UIImagePickerControllerSourceType)sourceType callback:(void (^)(UIImage *))callback{
    if (sourceType == UIImagePickerControllerSourceTypeCamera&&![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
        VDLog(@"該設備不支持相機調(diào)用哦!?_?");
        return;
    }
    VDImagePicker *imagePicker = [[VDImagePicker alloc]init];
    imagePicker.callback = callback;
    [[vc rac_signalForSelector:@selector(imagePickerController:didFinishPickingImage:editingInfo:) fromProtocol:@protocol(UIImagePickerControllerDelegate)] subscribeNext:^(id x) {
        if (imagePicker.callback) {
            imagePicker.callback([x objectAtIndex:1]);
        }
        [imagePicker dismissViewControllerAnimated:YES completion:^{
            imagePicker.callback = nil;
            [imagePicker removeFromParentViewController];
        }];
    }];
    imagePicker.allowsEditing = YES;
    imagePicker.delegate = vc;
    imagePicker.sourceType = sourceType;
    [vc presentViewController:imagePicker animated:YES completion:nil];
}

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}
@end

一個方法搞定訪問相機和相冊是不是很爽O(∩_∩)O~,不過一般是配合acitonSheet使用,自己寫個兼容iOS8.0的UIAlertController的擴展方法配合使用吧!


↑↑↑↑↑↑ 上面的內(nèi)容我的github沒有哦
↓↓↓↓↓↓ 下面的內(nèi)容都在我的github


一、常用的宏定義

善于利用宏在開發(fā)中過程中會減少很多工作量比如定義開發(fā)過程中的常用尺寸,這樣在后續(xù)開發(fā)中不用為了改一個相同尺寸而滿世界的去找這個尺寸在哪用到了。宏定義用的很廣泛,例如屏幕的寬高,網(wǎng)絡請求的baseUrl等等
下面是自己整理的一些示例:

#if TARGET_IPHONE_SIMULATOR//模擬器
#define PHONE_MARK  0
#elif TARGET_OS_IPHONE//真機
#define PHONE_MARK 1
#endif

//16進制顏色轉換
#define UIColorFromRGB(rgbValue) [UIColor colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 green:((float)((rgbValue & 0xFF00) >> 8))/255.0 blue:((float)(rgbValue & 0xFF))/255.0 alpha:1.0]

//屏幕的寬高
#define SCREEN_WIDTH   [[UIScreen mainScreen] bounds].size.width
#define SCREEN_HEIGHT  [[UIScreen mainScreen] bounds].size.height

//轉化為weak對象(block循環(huán)引用使用時)
#define WeakObj(o) __weak typeof(o) obj##Weak = o;

自定義log并以一個宏區(qū)分是否為debug模式

#define DEBUGGER 1 //上線版本屏蔽此宏

#ifdef DEBUGGER
/* 自定義log 可以輸出所在的類名,方法名,位置(行數(shù))*/
#define VDLog(format, ...) NSLog((@"%s [Line %d] " format), __FUNCTION__, __LINE__, ##__VA_ARGS__)

#else

#define VDLog(...)

#endif  

示例在viewDidLoad中

VDLog(@"很好用的");

輸出結果為

-[ViewController viewDidLoad] [Line 35] 很好用的

一、UIView的擴展類(category)

1.在開發(fā)中會經(jīng)常獲取或者改變控件的位置大小,所以這樣的類別就大有用處了,你可以方便的改變?nèi)我馕恢么笮傩?這樣在做一些控件的位置大小動畫也很方便),廢話不多說直接上代碼。

UIView+tool.h

#import <UIKit/UIKit.h>

@interface UIView (tool)

#pragma mark [frame]

/**
*  view的x(橫)坐標
*/
@property (nonatomic, assign)CGFloat v_x;
/**
 *  view的y(縱)坐標
 */
@property (nonatomic, assign)CGFloat v_y;
/**
 *  view的寬度
 */
@property (nonatomic, assign)CGFloat v_w;
/**
 *  view的高度
 */
@property (nonatomic, assign)CGFloat v_h;


#pragma mark [layer]

/**
 *  view的圓角半徑
 */
@property (nonatomic, assign)CGFloat v_cornerRadius;


@end

2.此擴展的功能為給一些空的頁面添加默認圖,比如網(wǎng)頁加載失敗時或者一些tableView的列表數(shù)據(jù)為空時給出一個提示頁并且增加重新加載機制。這個在大部分項目中必不可少的一部分,所以這個東西就誕生了!

UIView+EmptyShow.h

#import <UIKit/UIKit.h>
typedef void (^ReloadDataBlock)();

typedef NS_ENUM(NSInteger, ViewDataType)
{
    ViewDataTypeMyOrder = 0,//我的訂單
    ViewDataTypeLoadFail//web頁加載失敗
};

@interface CustomerWarnView : UIView
//提示圖
@property (nonatomic, strong) UIImageView     *imageView;
//提示文字
@property (nonatomic, strong) UILabel         *tipLabel;
//刷新按鈕
@property (nonatomic, strong) UIButton        *loadBtn;
//用于回調(diào)
@property (nonatomic, copy) ReloadDataBlock reloadBlock;
//初始化
+ (CustomerWarnView *)initWithFrame:(CGRect)frame andType:(ViewDataType)type;


@end

@interface UIView (EmptyShow)

@property (strong, nonatomic) CustomerWarnView *warningView;
/**
 *  空頁面顯示提醒圖與文字并添加重新刷新
 *
 *  @param emptyType 頁面的展示的數(shù)據(jù)類別(例如:我的訂單或者web頁)
 *  @param haveData  是否有數(shù)據(jù)
 *  @param block     重新加載頁面(不需要時賦空)
 */
- (void)emptyDataCheckWithType:(ViewDataType)emptyType
                   andHaveData:(BOOL)haveData
                andReloadBlock:(ReloadDataBlock)block;

@end

源碼結構分析:源碼中使用runtime給類別添加屬性并使用純代碼實現(xiàn)一個自定義View,其中布局采用了第三庫Masonry(需要的請自行導入),刷新的回調(diào)使用的block。

用法:只需要在獲取數(shù)據(jù)后或者網(wǎng)頁加載失敗的回調(diào)中使用tableView或者webView等調(diào)用此方法

- (void)emptyDataCheckWithType:(ViewDataType)emptyType
                   andHaveData:(BOOL)haveData
                andReloadBlock:(ReloadDataBlock)block;

示例圖


emptyOrder.png

二、NSString的擴展類

在做項目中對字符串的處理是必不可少的,或者要對一些數(shù)據(jù)進行字符串的轉換等等。下面就介紹幾個自己在項目中經(jīng)常使用的方法。下面的category包括:時間戳轉化為字符串的各類形式,獲取當前設備deviceId和字符串向富文本的轉換(哥現(xiàn)在做的項目大部分頁面都用到了這東西)。
NSString+tool.h

#import <Foundation/Foundation.h>

static NSString  *const XCColorKey = @"color";
static NSString  *const XCFontKey = @"font";
static NSString  *const XCRangeKey = @"range";
/**
 range的校驗結果
 */
typedef enum
{
    RangeCorrect = 0,
    RangeError = 1,
    RangeOut = 2,
    
}RangeFormatType;

@interface NSString (tool)

#pragma mark - 常用工具
/**
 *  獲取當前Vindor標示符
 *
 *  @return deviceId
 */
+ (NSString *) getDeviceIdentifierForVendor;


/**
 *  轉換為XXXX年XX月XX日
 *
 *  @param time 時間戳
 *
 *  @return 年月日
 */
+ (NSString*) format:(NSTimeInterval) time;

/**
 *  轉化為XX時XX分XX秒
 *
 *  @param time 時間戳
 *
 *  @return 時:分:秒
 */
+ (NSString*) formatTime:(NSTimeInterval) time;

/**
 *  轉化為XXXX年XX月XX日XX時XX分XX秒
 *
 *  @param time 時間戳
 *
 *  @return 年月日 時:分:秒
 */
+ (NSString *) formatDateAndTime:(NSTimeInterval)time;

#pragma mark - 校驗NSRange
/**
 *  校驗范圍(NSRange)
 *
 *  @param range Range
 *
 *  @return 校驗結果:RangeFormatType
 */
- (RangeFormatType)checkRange:(NSRange)range;

#pragma mark - 改變單個范圍字體的大小和顏色
/**
 *  改變字體的顏色
 *
 *  @param color 顏色(UIColor)
 *  @param range 范圍(NSRange)
 *
 *  @return 轉換后的富文本(NSMutableAttributedString)
 */
- (NSMutableAttributedString *)changeColor:(UIColor *)color
                                  andRange:(NSRange)range;


/**
 *  改變字體大小
 *
 *  @param font  字體大小(UIFont)
 *  @param range 范圍(NSRange)
 *
 *  @return 轉換后的富文本(NSMutableAttributedString)
 */
- (NSMutableAttributedString *)changeFont:(UIFont *)font
                                 andRange:(NSRange)range;


/**
 *   改變字體的顏色和大小
 *
 *  @param colors      字符串的顏色
 *  @param colorRanges 需要改變顏色的字符串范圍
 *  @param fonts       字體大小
 *  @param fontRanges  需要改變字體大小的字符串范圍
 *
 *  @return 轉換后的富文本(NSMutableAttributedString)
 */

- (NSMutableAttributedString *)changeColor:(UIColor *)color
                              andColorRang:(NSRange)colorRange
                                   andFont:(UIFont *)font
                              andFontRange:(NSRange)fontRange;

#pragma mark - 改變多個范圍內(nèi)的字體和顏色

/**
 *  改變多段字符串為一種顏色
 *
 *  @param color  字符串的顏色
 *  @param ranges 范圍數(shù)組:[NSValue valueWithRange:NSRange]
 *
 *  @return 轉換后的富文本(NSMutableAttributedString)
 */
- (NSMutableAttributedString *)changeColor:(UIColor *)color andRanges:(NSArray<NSValue *> *)ranges;

/**
 *  改變多段字符串為同一大小
 *
 *  @param font   字體大小
 *  @param ranges 范圍數(shù)組:[NSValue valueWithRange:NSRange]
 *
 *  @return 轉換后的富文本(NSMutableAttributedString)
 */
- (NSMutableAttributedString *)changeFont:(UIFont *)font andRanges:(NSArray<NSValue *> *)ranges;

@end

下面是轉化為富文本的示例代碼

UILabel *lable = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, V_SCREEN_WIDTH, 100)];
    lable.center = self.view.center;
    lable.numberOfLines = 0;
    lable.textAlignment = NSTextAlignmentCenter;
    lable.textColor = [UIColor blackColor];
    lable.font = [UIFont systemFontOfSize:15.0];
    [self.view addSubview:lable];
    NSString *str = @"這個是綠色字號是20";
    //富文本
    lable.attributedText = [str changeColor:[UIColor greenColor] andColorRang:NSMakeRange(3, 2) andFont:[UIFont systemFontOfSize:20] andFontRange:NSMakeRange(8, 2)];

效果如圖所示


富文本.png

三、UIImage擴展類

下面分享的是對image進行處理的擴展類,主要包含:圖片的縮放,剪切和壓縮
UIImage+tool.h

#import <UIKit/UIKit.h>

@interface UIImage (tool)

/**
 *  等比縮放
 *
 *  @param size 設置尺寸
 *
 *  @return image
 */
-(UIImage *)scaleImageToSize:(CGSize)size;
/**
 *  自定長寬
 *
 *  @param reSize 設置尺寸
 *
 *  @return image
 */
-(UIImage *)imageReSize:(CGSize)reSize;
/**
 *  剪切
 *
 *  @param cutRect 選取截取部分
 *
 *  @return image
 */
-(UIImage *)cutImageWithRect:(CGRect)cutRect;
/**
 *  壓縮
 *
 *  @param image 待壓縮的圖片
 *
 *  @return image
 */
+ (UIImage *)smallTheImage:(UIImage *)image;
/**
 *  壓縮(上傳)
 *
 *  @param image 待壓縮圖片
 *
 *  @return 圖片的二進制文件
 */
+ (NSData *)smallTheImageBackData:(UIImage *)image;
/**
 *  view轉位圖(一般用于截圖)
 *
 *  @param view 需要轉化的view
 *
 *  @return image
 */
+ (UIImage *)imageFromView:(UIView*)view;

@end

四、UIControl的擴展類

相信大家都遇到過按鈕反復點擊問題的處理,下面介紹的UIControl+clickRepeatedly擴展類,只需一句代碼搞定此問題。不用太感謝我哦!(溫馨提示:建議此類別別大范圍使用)。

UIControl+clickRepeatedly.h

#import <UIKit/UIKit.h>

@interface UIControl (clickRepeatedly)

/**
 *  設置點擊的間隔(防止反復點擊)
 */
@property (nonatomic, assign)NSTimeInterval clickInterval;

@property (nonatomic, assign)BOOL ignoreClick;

@end

UIControl+clickRepeatedly.m

#import "UIControl+clickRepeatedly.h"
#import <objc/runtime.h>

static const char *ClickIntervalKey;
static const char *IgnoreClick;
@implementation UIControl (clickRepeatedly)

- (void)setClickInterval:(NSTimeInterval)clickInterval{
    objc_setAssociatedObject(self, &ClickIntervalKey, @(clickInterval), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (NSTimeInterval)clickInterval{
    
    return [objc_getAssociatedObject(self, &ClickIntervalKey) doubleValue];
}

- (void)setIgnoreClick:(BOOL)ignoreClick{
    objc_setAssociatedObject(self, &IgnoreClick, @(ignoreClick), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (BOOL)ignoreClick{
    return [objc_getAssociatedObject(self, &IgnoreClick) boolValue];
}

+ (void)load
{
    //替換點擊事件
    Method a = class_getInstanceMethod(self, @selector(sendAction:to:forEvent:));
    Method b = class_getInstanceMethod(self, @selector(rc_sendAction:to:forEvent:));
    method_exchangeImplementations(a, b);
}

- (void)rc_sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event
{
    if (self.ignoreClick) {
        return;
    }
    else{
        [self rc_sendAction:action to:target forEvent:event];
    }
    if (self.clickInterval > 0)
    {
        self.ignoreClick = YES;
        [self performSelector:@selector(setIgnoreClick:) withObject:@(NO) afterDelay:self.clickInterval];
    }
    
}



@end

看上面的代碼是不是很簡單,其實使用起來更加簡單,只需要在你初始化好的btn設置如下代碼:

btn.clickInterval = 3;//點擊完三秒后才能點哦

五、用戶信息(單例模式)

UserInfoModel:實現(xiàn)一些輕量級的用戶信息存儲和類的歸檔存入


六、AFNetWorking的二次封裝

1.簡單的HTTP(POST)請求:其中添加了多種請求錯誤判斷和debug模式下打印響應成功的數(shù)據(jù),最后采用block進行響應結果的回調(diào)

/**
 *  發(fā)送請求
 *
 *  @param requestAPI 請求的API
 *  @param vc         發(fā)送請求的視圖控制器
 *  @param params     請求參數(shù)
 *  @param className  數(shù)據(jù)模型
 *  @param response   請求的返回結果回調(diào)
 */
- (void)sendRequestWithAPI:(NSString *)requestAPI
                    withVC:(UIViewController *)vc
                withParams:(NSDictionary *)params
                 withClass:(Class)className
             responseBlock:(RequestResponse)response;

2.創(chuàng)建下載任務并對下載進度,任務對象和存儲路徑等進行回調(diào)(支持多任務下載),創(chuàng)建的任務會自動加到下載隊列中,下載進度的回調(diào)自動回到主線程(便于相關UI的操作)

/**
 *  創(chuàng)建下載任務
 *
 *  @param url          下載地址
 *  @param fileName     文件名
 *  @param downloadTask 任務
 *  @param progress     進度
 *  @param result       結果
 */
- (void)createDdownloadTaskWithURL:(NSString *)url
              withFileName:(NSString *)fileName
                       Task:(DownloadTask)downloadTask
                   Progress:(TaskProgress)progress
                     Result:(TaskResult)result;

3.創(chuàng)建上傳任務與下載方法回調(diào)基本一致

/**
 *  創(chuàng)建上傳任務
 *
 *  @param url        上傳地址
 *  @param mark       任務標識
 *  @param data       序列化文件
 *  @param uploadTask 任務
 *  @param progress   進度
 *  @param result     結果
 */
- (void)createUploadTaskWithUrl:(NSString *)url
                       WithMark:(NSString *)mark
                       withData:(NSData *)data
                           Task:(UploadTask)uploadTask
                       Progress:(TaskProgress)progress
                         Result:(TaskResult)result;

七、校驗工具類

1.手機號校驗

+(BOOL) isValidateMobile:(NSString *)mobile

2.郵箱校驗

+(BOOL)isValidateEmail:(NSString *)email

3.車牌號校驗

+(BOOL) isvalidateCarNo:(NSString*)carNo

4.身份證號驗證

+(BOOL) isValidateIDCardNo:(NSString *)idCardNo

待續(xù)

本筆記會持續(xù)更新。


附上github上源碼,工具類全部在tool文件目錄下

別著急離開,留點足跡給個喜歡!您的鼓勵是我最大的支持↖(ω)↗

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容