iOS開發(fā)小技巧和常用工具類(平時收集和整理)
前言
作為一個開發(fā)者應該學會去整理收集開發(fā)常用的工具類,這些復用的工具可以在項目開發(fā)中給你很大程度提高你的工作效率。難道你不想早點完成工作,然后出去撩妹、陪女朋友或者回家陪老婆孩子嗎?反正我想早點回家??。
更新
2017-12-12 PM 重新編輯
- 使用Pod管理公共類(常用的工具類和分類)傳送門-->
- 為后期的組件化學習和項目重構做準備
想學習的小伙伴歡迎一起哈
由于工作原因(其實是本人比較懶) 文章更新會很慢或者忘記更新,關于更新的說明: 文章中只提供方法名說明在俺的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
準備工作
- ReactiveCocoa的簡單介紹和使用(這是一個傳送門)
- pod導入(OC版本建議導入2.5版本)
pod 'ReactiveCocoa', '~> 2.5'
在這里我只介紹一個我經(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
- UINavigationBar擴展改變導航欄背景色
- FMDB二次封裝
- 文件與文件夾操作
- 下面的內(nèi)容我就不列舉了
一、常用的宏定義
善于利用宏在開發(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;
示例圖

二、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)];
效果如圖所示

三、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文件目錄下
別著急離開,留點足跡給個喜歡!您的鼓勵是我最大的支持↖(ω)↗