4.SDWebImage圖片緩存庫github
10.CustomIOSAlertView自定義AlertViewwindows
12.JDStatusBarNotification自定義狀態欄通知
13.WMPageController相似網易頻道導航控制器
ASIHttp庫下載地址:https://github.com/pokeb/asi-http-request
ASIHTTP類庫依賴於如下5個框架或庫:
CFNetwork, SystemConfiguration, MobileCoreServices, CoreGraphics 和 libz1.2.5
-fno-objc-arc 讓非ARC類在ARC工程中適配運行
//TKOpenBankService.h文件
// // TKOpenBankService.h // TKBankOriginalPlugin // // Created by Vie on 15/9/18. // Copyright (c) 2015年 Vie. All rights reserved. // #import <Foundation/Foundation.h> //請求結果回調 typedef void(^CallBackASIRepose)(NSMutableDictionary *reposeParam); /** * @Author Vie, 2015-09-18 16:44:20 * 描述:網絡請求插件服務類 * @since 1.0 */ @interface TKOpenBankService : NSObject /** * @Author Vie, 2015-09-18 17:03:42 * 上傳單向視頻 * @param url url * @param reqParam 上傳參數 * @param callBackASIRepose 回調函數 * * @since 1.0 */ -(void)upLoadOneVideoWithURL:(NSString *)url param:(NSMutableDictionary*)reqParam callBackFunc:(CallBackASIRepose)callBackASIRepose; /** * @Author Vie, 2015-09-22 13:57:25 * * @param url url * @param reqParam 請求參數 * @param callBackImgRepose 回到參數 * * @since 1.0 */ -(void)upLoadPhotoWithURL:(NSString *)url param:(NSMutableDictionary *)reqParam callBackImgFunc:(CallBackASIRepose)callBackImgRepose; /** * @Author Vie, 2015-09-22 13:54:08 * 底層請求方法 * @param url 請求url * @param reqParam 請求參數 * @param callBackASIRepose 回調函數 * * @since 1.0 */ -(void)asiRequestWithURL:(NSURL *)url param:(NSMutableDictionary *)reqParam callBackFunc:(CallBackASIRepose)callBackASIRepose; @end
//TKOpenBankService.m文件
// // TKOpenBankService.m // TKBankOriginalPlugin // // Created by Vie on 15/9/18. // Copyright (c) 2015年 Vie. All rights reserved. // #import "TKOpenBankService.h" #import "ASIFormDataRequest.h" @implementation TKOpenBankService //上傳文件 -(void)upLoadOneVideoWithURL:(NSString *)url param:(NSMutableDictionary*)reqParam callBackFunc:(CallBackASIRepose)callBackASIRepose{ NSURL *postURL=[NSURL URLWithString:url]; [self asiRequestWithURL:postURL param:reqParam callBackFunc:callBackASIRepose]; } //上傳照片 -(void)upLoadPhotoWithURL:(NSString *)url param:(NSMutableDictionary *)reqParam callBackImgFunc:(CallBackASIRepose)callBackImgRepose{ NSURL *postURL=[NSURL URLWithString:url]; [self asiRequestWithURL:postURL param:reqParam callBackFunc:callBackImgRepose]; } //asi請求處理 -(void)asiRequestWithURL:(NSURL *)url param:(NSMutableDictionary *)reqParam callBackFunc:(CallBackASIRepose)callBackASIRepose{ ASIFormDataRequest *request=[ASIFormDataRequest requestWithURL:url]; for (id key in reqParam) { NSString *str=key; if ([str hasSuffix:@"@@F"]) { str=[str stringByReplacingOccurrencesOfString:@"@@F" withString:@""]; [request setData:[reqParam objectForKey:key] forKey:str]; }else{ [request setPostValue:[reqParam objectForKey:key] forKey:key]; NSLog(@"key:%@",key); } } //發送異步請求 [request startAsynchronous]; //用於存儲請求結果 NSMutableDictionary *repParam=[[NSMutableDictionary alloc] init]; //請求失敗回調 [request setFailedBlock:^{ [repParam setObject:@"-1" forKey:@"error_no"]; [repParam setObject:@"請求異常" forKey:@"error_info"]; callBackASIRepose(repParam); }]; //請求完成回調 [request setCompletionBlock:^{ NSLog(@"返回的數據--%@",request.responseString); //請求返回字符串轉換爲NSData NSData *curData=[request.responseStringdataUsingEncoding:NSUTF8StringEncoding]; //解析成JSON NSError *error; NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:curData options:kNilOptions error:&error]; NSString *tempLog = [NSString stringWithUTF8String:curData.bytes]; NSLog(@"return :\n%@",tempLog); int errNo; NSString *errMsg=nil; if(dic){ @try { errNo=[[dic objectForKey:@"error_no"] intValue]; [repParam setObject:[dic objectForKey:@"error_no"] forKey:@"error_no"]; if (errNo!=0) { errMsg=[dic objectForKey:@"error_info"]; [repParam setObject:errMsg forKey:@"error_info"]; }else{ NSArray *arr=(NSArray *)[dic objectForKey:@"results"]; if (arr.count>0) { NSDictionary *result=[arr objectAtIndex:0]; [repParam setObject:result forKey:@"result"]; } } } @catch (NSException *exception) { NSLog(@"%@ error:[%@]",@"501506",exception); } } callBackASIRepose(repParam); }]; } @end
第三方庫之MBProgressHUD下載地址:https://github.com/jdg/MBProgressHUD
//例
_mbHud = [[MBProgressHUD alloc] initWithView:self.view]; [self.view addSubview:_mbHud]; _mbHud.labelText = @"Loading"; //是否遮罩 _mbHud.dimBackground = YES;
//頁面加載方法 -(void)webViewDidStartLoad:(UIWebView *)webView{ //顯示指示層 [_mbHud show:YES]; } //頁面加載完成方法 -(void)webViewDidFinishLoad:(UIWebView *)webView{ //隱藏指示層 [_mbHud hide:YES]; _mbHud = nil; _mbHud = nil; }
//其餘示例
- (IBAction)showTextDialog:(id)sender { //初始化進度框,置於當前的View當中 HUD = [[MBProgressHUD alloc] initWithView:self.view]; [self.view addSubview:HUD]; //若是設置此屬性則當前的view置於後臺 HUD.dimBackground = YES; //設置對話框文字 HUD.labelText = @"請稍等"; //顯示對話框 [HUD showAnimated:YES whileExecutingBlock:^{ //對話框顯示時須要執行的操做 sleep(3); } completionBlock:^{ //操做執行完後取消對話框 [HUD removeFromSuperview]; [HUD release]; HUD = nil; }]; }
- (IBAction)showProgressDialog:(id)sender { HUD = [[MBProgressHUD alloc] initWithView:self.view]; [self.view addSubview:HUD]; HUD.labelText = @"正在加載"; //設置模式爲進度框形的 HUD.mode = MBProgressHUDModeDeterminate; [HUD showAnimated:YES whileExecutingBlock:^{ float progress = 0.0f; while (progress < 1.0f) { progress += 0.01f; HUD.progress = progress; usleep(50000); } } completionBlock:^{ [HUD removeFromSuperview]; [HUD release]; HUD = nil; }]; }
- (IBAction)showProgressDialog2:(id)sender { HUD = [[MBProgressHUD alloc] initWithView:self.view]; [self.view addSubview:HUD]; HUD.labelText = @"正在加載"; //設置爲圓圈進度條 HUD.mode = MBProgressHUDModeAnnularDeterminate; [HUD showAnimated:YES whileExecutingBlock:^{ float progress = 0.0f; while (progress < 1.0f) { progress += 0.01f; HUD.progress = progress; usleep(50000); } } completionBlock:^{ [HUD removeFromSuperview]; [HUD release]; HUD = nil; }]; }
- (IBAction)showCustomDialog:(id)sender { HUD = [[MBProgressHUD alloc] initWithView:self.view]; [self.view addSubview:HUD]; HUD.labelText = @"操做成功"; HUD.mode = MBProgressHUDModeCustomView; HUD.customView = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"Checkmark"]] autorelease]; [HUD showAnimated:YES whileExecutingBlock:^{ sleep(2); } completionBlock:^{ [HUD removeFromSuperview]; [HUD release]; HUD = nil; }]; }
下載地址:https://github.com/scalessec/Toast
//防止提示被鍵盤遮擋,直接展現到最高,屏幕底部
UIWindow *win=[[UIApplication sharedApplication].windows objectAtIndex:([UIApplication sharedApplication].windows.count-1)]; [win makeToast:@"發送消息內容超長,請分條發送。" duration:2 position:@"middle"];
github託管地址https://github.com/rs/SDWebImage
#import "SDWebImage.h" @property(nonatomic,strong) UIImageView *imgView; _imgView=[[UIImageView alloc] initWithFrame:self.view.frame]; //設置圖片緩存下載 [self.imgView sd_setImageWithURL:[NSURL URLWithString:@"http://imgsrc.baidu.com/forum/w%3D580/sign=64e98b6bc511728b302d8c2af8fec3b3/4300f03b5bb5c9eaa0270719dd39b60038f3b394.jpg"]]; //用block 能夠在圖片加載完成以後作些事情 [self.imgView sd_setImageWithURL:[NSURL URLWithString:@"http://imgsrc.baidu.com/forum/w%3D580/sign=64e98b6bc511728b302d8c2af8fec3b3/4300f03b5bb5c9eaa0270719dd39b60038f3b394.jpg"] completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) { NSLog(@"這裏能夠在圖片加載完成以後作些事情"); }]; //給一張默認圖片,先使用默認圖片,當圖片加載完成後再替換 [self.imgView sd_setImageWithURL:[NSURL URLWithString:@"http://imgsrc.baidu.com/forum/w%3D580/sign=64e98b6bc511728b302d8c2af8fec3b3/4300f03b5bb5c9eaa0270719dd39b60038f3b394.jpg"] placeholderImage:[UIImage imageNamed:@"1.jpg"]]; //使用默認圖片,並且用block 在完成後作一些事情 [self.imgView sd_setImageWithURL:[NSURL URLWithString:@"http://imgsrc.baidu.com/forum/w%3D580/sign=64e98b6bc511728b302d8c2af8fec3b3/4300f03b5bb5c9eaa0270719dd39b60038f3b394.jpg"] placeholderImage:[UIImage imageNamed:@"1.jpg"] completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) { NSLog(@"圖片加載完成後作的事情"); }]; //options 選擇方式 [self.imgView sd_setImageWithURL:[NSURL URLWithString:@"http://imgsrc.baidu.com/forum/w%3D580/sign=64e98b6bc511728b302d8c2af8fec3b3/4300f03b5bb5c9eaa0270719dd39b60038f3b394.jpg"] placeholderImage:[UIImage imageNamed:@"1.jpg"] options:SDWebImageProgressiveDownload]; [self.view addSubview:_imgView];
options全部選項:
//失敗後重試
SDWebImageRetryFailed = 1 << 0,
//UI交互期間開始下載,致使延遲下載好比UIScrollView減速。
SDWebImageLowPriority = 1 << 1,
//只進行內存緩存
SDWebImageCacheMemoryOnly = 1 << 2,
//這個標誌能夠漸進式下載,顯示的圖像是逐步在下載
SDWebImageProgressiveDownload = 1 << 3,
//刷新緩存
SDWebImageRefreshCached = 1 << 4,
//後臺下載
SDWebImageContinueInBackground = 1 << 5,
//NSMutableURLRequest.HTTPShouldHandleCookies = YES;
SDWebImageHandleCookies = 1 << 6,
//容許使用無效的SSL證書
SDWebImageAllowInvalidSSLCertificates = 1 << 7,
//優先下載
SDWebImageHighPriority = 1 << 8,
//延遲佔位符
SDWebImageDelayPlaceholder = 1 << 9,
//改變更畫形象
SDWebImageTransformAnimatedImage = 1 << 10,
//覆蓋方法,指哪打哪,這個方法是下載imagePath2的時候響應 SDWebImageManager *manager = [SDWebImageManager sharedManager]; [manager downloadImageWithURL:imagePath2 options:SDWebImageRetryFailed progress:^(NSInteger receivedSize, NSInteger expectedSize) { NSLog(@"顯示當前進度"); } completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, BOOL finished, NSURL *imageURL) { NSLog(@"下載完成"); }];
// SDWebImage改寫後支持gif動態圖
//讀取圖片 NSString *retinaPath = [[NSBundle mainBundle] pathForResource:@"ker" ofType:@"gif"]; //圖片轉換爲data NSData *data = [NSData dataWithContentsOfFile:retinaPath]; _imgView.image=[UIImage sd_animatedGIFWithData:data]; [self.view addSubview:_imgView];
//修改UIImage+GIF.m方法支持gif播放
//修改下面方法
/** 播放靜態圖或gif動態圖 @param data 圖片數據源 @return 返回圖片 */ + (UIImage *)sd_animatedGIFWithData:(NSData *)data { if (!data) { return nil; } CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)data, NULL); size_t count = CGImageSourceGetCount(source); UIImage *animatedImage; if (count <= 1) { animatedImage = [[UIImage alloc] initWithData:data]; } else { NSMutableArray *images = [NSMutableArray array]; NSTimeInterval duration = 0.0f; for (size_t i = 0; i < count; i++) { CGImageRef image = CGImageSourceCreateImageAtIndex(source, i, NULL); duration += [self frameDurationAtIndex:i source:source]; [images addObject:[UIImage imageWithCGImage:image scale:[UIScreen mainScreen].scale orientation:UIImageOrientationUp]]; CGImageRelease(image); } if (!duration) { duration = (1.0f / 10.0f) * count; } animatedImage = [UIImage animatedImageWithImages:images duration:duration]; } CFRelease(source); return animatedImage; }
//增長下面方法
/** 計算圖片顯示時間 @param index 圖片位置 @param source 當前圖片 @return 返回播放時間 */ + (float)frameDurationAtIndex:(NSUInteger)index source:(CGImageSourceRef)source { float frameDuration = 0.1f; CFDictionaryRef cfFrameProperties = CGImageSourceCopyPropertiesAtIndex(source, index, nil); NSDictionary *frameProperties = (__bridge NSDictionary *)cfFrameProperties; NSDictionary *gifProperties = frameProperties[(NSString *)kCGImagePropertyGIFDictionary]; NSNumber *delayTimeUnclampedProp = gifProperties[(NSString *)kCGImagePropertyGIFUnclampedDelayTime]; if (delayTimeUnclampedProp) { frameDuration = [delayTimeUnclampedProp floatValue]; } else { NSNumber *delayTimeProp = gifProperties[(NSString *)kCGImagePropertyGIFDelayTime]; if (delayTimeProp) { frameDuration = [delayTimeProp floatValue]; } } if (frameDuration < 0.011f) { frameDuration = 0.100f; } CFRelease(cfFrameProperties); return frameDuration; }
github下載地址:https://github.com/MortimerGoro/MGSwipeTableCell
//TestMGSwipeTableCell.h文件定義一個單元格繼承自MGSwipeTableCell
// // TestMGSwipeTableCell.h // UseMGSwipeTableCell // // Created by Vie on 2016/10/21. // Copyright © 2016年 Vie. All rights reserved. // #import "MGSwipeTableCell.h" @interface TestMGSwipeTableCell : MGSwipeTableCell @property(nonatomic,strong) UILabel *titleLable; -(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier; @end
//TestMGSwipeTableCell.m文件
// // TestMGSwipeTableCell.m // UseMGSwipeTableCell // // Created by Vie on 2016/10/21. // Copyright © 2016年 Vie. All rights reserved. // #import "TestMGSwipeTableCell.h" @implementation TestMGSwipeTableCell -(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{ self=[super initWithStyle:style reuseIdentifier:reuseIdentifier]; if (self) { [self drawView]; } return self; } -(void)drawView{ [self.contentView addSubview:self.titleLable]; } -(UILabel *)titleLable{ if (!_titleLable) { _titleLable=[[UILabel alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, 44)]; _titleLable.textAlignment=NSTextAlignmentCenter; } return _titleLable; } @end
//ViewController.h文件
// ViewController.h // UseMGSwipeTableCell // // Created by Vie on 2016/10/21. // Copyright © 2016年 Vie. All rights reserved. // #import <UIKit/UIKit.h> @interface ViewController : UIViewController @end
//ViewController.m文件
// ViewController.m // UseMGSwipeTableCell // // Created by Vie on 2016/10/21. // Copyright © 2016年 Vie. All rights reserved. // #import "ViewController.h" #import "TestMGSwipeTableCell.h" @interface ViewController ()<UITableViewDelegate,UITableViewDataSource> @property(nonatomic,strong) UITableView *tableView; @property(nonatomic,strong) NSArray *dataArry; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. _dataArry=[[NSArray alloc] initWithObjects:@"Vie",@"Joker",@"King",@"Tracer",@"Monkey",@"Mimi",@"Loli", nil]; _tableView=[[UITableView alloc] initWithFrame:self.view.frame]; _tableView.delegate=self; _tableView.dataSource=self; [self.view addSubview:_tableView]; } -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ TestMGSwipeTableCell *cell=[tableView dequeueReusableCellWithIdentifier:[NSString stringWithFormat:@"%ld",(long)indexPath.row]]; if (!cell) { cell =[[TestMGSwipeTableCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:[NSString stringWithFormat:@"%ld",(long)indexPath.row]]; } cell.titleLable.text=[_dataArry objectAtIndex:indexPath.row]; //置頂按鈕 MGSwipeButton *toTopBtn=[MGSwipeButton buttonWithTitle:@"置頂" backgroundColor:[UIColor lightGrayColor] callback:^BOOL(MGSwipeTableCell * _Nonnull cell) { NSLog(@"置頂按鈕"); //重載數據,側滑會還原 [self.tableView reloadData]; return NO; }]; //刪除按鈕 MGSwipeButton *deleteBtn=[MGSwipeButton buttonWithTitle:@"刪除" backgroundColor:[UIColor redColor] callback:^BOOL(MGSwipeTableCell * _Nonnull cell) { NSLog(@"刪除按鈕"); //重載數據,側滑會還原 [self.tableView reloadData]; return NO; }]; //添加按鈕到右側 cell.rightButtons=@[deleteBtn,toTopBtn]; //備註按鈕 MGSwipeButton *noteBtn=[MGSwipeButton buttonWithTitle:@"備註" backgroundColor:[UIColor blueColor] callback:^BOOL(MGSwipeTableCell * _Nonnull cell) { NSLog(@"備註按鈕"); //重載數據,側滑會還原 [self.tableView reloadData]; return NO; }]; //更多按鈕 MGSwipeButton *moreBtn=[MGSwipeButton buttonWithTitle:@"更多" backgroundColor:[UIColor greenColor] callback:^BOOL(MGSwipeTableCell * _Nonnull cell) { NSLog(@"更多按鈕"); //重載數據,側滑會還原 [self.tableView reloadData]; return NO; }]; //添加按鈕到左側 cell.leftButtons=@[noteBtn,moreBtn]; return cell; } //返回分區數量 -(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{ return 1; } //返回每一個分區的單元格數量 -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ return _dataArry.count; } @end
github地址:https://github.com/CoderMJLee/MJRefresh
#import "MJRefresh.h"
//添加頭部刷新控件方法 MJRefreshNormalHeader *mjHeader=[MJRefreshNormalHeader headerWithRefreshingTarget:self refreshingAction:@selector(mjHeaderRefresh)]; //修改狀態提示語 [mjHeader setTitle:@"鬆開進行刷新" forState:MJRefreshStatePulling];//鬆開就能夠進行刷新的狀態 [mjHeader setTitle:@"正在刷新" forState:MJRefreshStateRefreshing];//正在刷新中的狀態 [mjHeader setTitle:@"下拉刷新" forState:MJRefreshStateIdle];//普通閒置狀態 //修改提示語顏色 mjHeader.stateLabel.textColor=[UIColor blueColor]; //修改頭部提示時間語顏色 mjHeader.lastUpdatedTimeLabel.textColor=[UIColor blueColor]; //隱藏頭部時間提示語 mjHeader.lastUpdatedTimeLabel.hidden=YES; self.tableView.mj_header=mjHeader;
//添加底部加載控件方法 MJRefreshBackNormalFooter *mjFooter=[MJRefreshBackNormalFooter footerWithRefreshingTarget:self refreshingAction:@selector(mjFooterRefresh)]; //修改狀態提示語 [mjFooter setTitle:@"鬆開進行加載" forState:MJRefreshStatePulling];//鬆開就能夠進行刷新的狀態 [mjFooter setTitle:@"正在加載" forState:MJRefreshStateRefreshing];//正在刷新中的狀態 [mjFooter setTitle:@"上拉加載" forState:MJRefreshStateIdle];//普通閒置狀態 //修改提示語顏色 mjFooter.stateLabel.textColor=[UIColor blackColor]; self.tableView.mj_footer=mjFooter;
//設置回調(一旦進入刷新狀態,就調用 targett 的 action,即調用 self 的 loadNewData 方法) MJRefreshGifHeader *header = [MJRefreshGifHeader headerWithRefreshingTarget:self refreshingAction:@selector(loadNewData)]; // 設置普通狀態的動畫圖片 NSArray *idleImages = @[@"圖片1", @"圖片2", @"圖片3"]; [header setImages:idleImages forState:MJRefreshStateIdle]; // 設置即將刷新狀態的動畫圖片(一鬆開就會刷新的狀態) NSArray *pullingImages = @[@"圖片1", @"圖片2", @"圖片3"]; [header setImages:pullingImages forState:MJRefreshStatePulling]; // 設置正在刷新狀態的動畫圖片 NSArray *refreshingImages = @[@"圖片1", @"圖片2", @"圖片3"]; [header setImages:refreshingImages forState:MJRefreshStateRefreshing]; // 設置 header self.tableView.mj_header = header;
// 設置回調(一旦進入刷新狀態,就調用 target 的 action,即調用 self 的 loadMoreData 方法) MJRefreshAutoGifFooter *footer = [MJRefreshAutoGifFooter footerWithRefreshingTarget:self refreshingAction:@selector(loadMoreData)]; //設置刷新圖片 NSArray *refreshingImages = @[@"圖片1", @"圖片2", @"圖片3"]; [footer setImages:refreshingImages forState:MJRefreshStateRefreshing]; //設置尾部 self.tableView.mj_footer = footer;
//UIResponder+Router.h文件
/************************************************************ * * EaseMob CONFIDENTIAL * __________________ * Copyright (C) 2013-2014 EaseMob Technologies. All rights reserved. * * NOTICE: All information contained herein is, and remains * the property of EaseMob Technologies. * Dissemination of this information or reproduction of this material * is strictly forbidden unless prior written permission is obtained * from EaseMob Technologies. */ #import <UIKit/UIKit.h> @interface UIResponder (Router) /** * 發送一個路由器消息, 對eventName感興趣的 UIResponsder 能夠對消息進行處理 * * @param eventName 發生的事件名稱 * @param userInfo 傳遞消息時, 攜帶的數據, 數據傳遞過程當中, 會有新的數據添加 * */ - (void)routerEventWithName:(NSString *)eventName userInfo:(NSObject *)userInfo; @end
//UIResponder+Router.m文件
/************************************************************ * * EaseMob CONFIDENTIAL * __________________ * Copyright (C) 2013-2014 EaseMob Technologies. All rights reserved. * * NOTICE: All information contained herein is, and remains * the property of EaseMob Technologies. * Dissemination of this information or reproduction of this material * is strictly forbidden unless prior written permission is obtained * from EaseMob Technologies. */ #import "UIResponder+Router.h" @implementation UIResponder (Router) - (void)routerEventWithName:(NSString *)eventName userInfo:(NSObject *)userInfo { [[self nextResponder] routerEventWithName:eventName userInfo:userInfo]; } @end
事件傳遞:響應者鏈
當你設計你的app 時候,常常動態地響應事件對不對。好比,屏幕上的許多對象都會觸發一個觸摸的事件,你必須決定讓誰來響應這個時間而且要明白這個對象怎麼接收到事件。
當一個用戶產生的事件發生時,UIKit 建立了包含處理該事件所須要的信息。而後這個事件對象進入 一個app對應的事件隊列。 對於觸摸事件來講,該對象是一系UItouches對象的打包。對於手勢來講,該對象則是手勢的類型。
一個事件是經由特定的路徑到達能處理的對象的。一開始是UIApplication,其次是key window, 其次到initial object.
對於觸摸事件來講, window 會傳到 發生觸摸的view,被稱之爲hit-test view。此過程叫 hit-testing。
對於手勢和遠程控制,這個第一響應被髮到 first responder.
最終響應者鏈要找處處理事件的對象。規則以下。
1 Hit_testing (檢測的過程其實是自上而下的)
1 此觸摸被檢測抖到在A的邊界內,因此繼續檢測B和C。
2 一樣的道理,繼續檢測C的子類D和E。
3 最後排除了D,檢測E。
View E已是最低層的View,因此它使hit-Test找到的對象。
hitTest:withEvent: 參數爲CGpoint 和 UiEvent。
hitTest:withEvent: 的實現都是以pointInside:withEvent:爲檢驗的,先檢驗本身而後再檢驗subview,因此觸摸點是必須在superview而後同時在view纔會被傳下來,若是都沒有在superview檢測到是不會被傳下來的。這種狀況適用於cliptobounds的狀況。
而後就是nextresponder了。響應者鏈的組成部分是Responder, Responder的
nextResponder方法決定了傳遞的規則,而後蘋果公佈的規則是這樣子的
我知道了當事觸摸事件發生,經過一層層找到的這個View ,找到這個View 後先判斷這個view能不能響應這個事件,若是不能那就繼續找nextResponder咱們看上面圖能夠看出若是一個View有SuperView 那麼這個View的nextResponder 就是他的SuperView,若是沒有SuperView 那麼它的nextResponder 就是他所在ViewController 而後就這樣一直找下去,直到找到或拋出異常。
咱們瞭解這機制後那咱們怎麼把這個UIButton Click 事件傳遞出來呢,咱們先來給UIResponder 添加一個咱們自定義的事件,我就讓它傳遞咱們這個事件出去。
//ViewController.h文件
// // ViewController.h // UIResponder事件分發 // // Created by Vie on 2016/10/28. // Copyright © 2016年 Vie. All rights reserved. // #import <UIKit/UIKit.h> @interface ViewController : UIViewController @end
//ViewController.m文件
// // ViewController.m // UIResponder事件分發 // // Created by Vie on 2016/10/28. // Copyright © 2016年 Vie. All rights reserved. // #import "ViewController.h" #import "RouterView1.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. RouterView1 *view=[[RouterView1 alloc] initWithFrame:CGRectMake(0, 50, self.view.frame.size.width, 50)]; view.backgroundColor=[UIColor blueColor]; [self.view addSubview:view]; } //實現UIResponder+Router -(void)routerEventWithName:(NSString *)eventName userInfo:(NSDictionary *)userInfo { if ([eventName isEqualToString:@"TestSuperRouter"]) { NSLog(@"測試2的名稱:%@",userInfo[@"name"]); } } @end
// RouterView1.h文件
// // RouterView1.h // UIResponder事件分發 // // Created by Vie on 2016/10/28. // Copyright © 2016年 Vie. All rights reserved. // #import <UIKit/UIKit.h> @interface RouterView1 : UIView @end
// RouterView1.m文件
// // RouterView1.m // UIResponder事件分發 // // Created by Vie on 2016/10/28. // Copyright © 2016年 Vie. All rights reserved. // #import "RouterView1.h" #import "UIResponder+Router.h" @implementation RouterView1 /* // Only override drawRect: if you perform custom drawing. // An empty implementation adversely affects performance during animation. */ - (void)drawRect:(CGRect)rect { // Drawing code UIButton *btn=[[UIButton alloc] initWithFrame:CGRectMake(0, 0, 100, 50)]; [btn setTitle:@"測試轉發" forState:UIControlStateNormal]; [btn addTarget:self action:@selector(testRouter) forControlEvents:UIControlEventTouchUpInside]; [self addSubview:btn]; UIButton *btn2=[[UIButton alloc] initWithFrame:CGRectMake(200, 0, 100, 50)]; [btn2 setTitle:@"super轉發" forState:UIControlStateNormal]; [btn2 addTarget:self action:@selector(testSuperRouter) forControlEvents:UIControlEventTouchUpInside]; [self addSubview:btn2]; } -(void)testRouter{ NSMutableDictionary *dic=[NSMutableDictionary dictionary]; dic[@"name"]=@"King"; dic[@"id"]=@"10010"; //分發相關事件 [self routerEventWithName:@"TestRouter" userInfo:dic]; } -(void)testSuperRouter{ NSMutableDictionary *dic=[NSMutableDictionary dictionary]; dic[@"name"]=@"Super"; dic[@"id"]=@"10011"; [self routerEventWithName:@"TestSuperRouter" userInfo:dic]; } //實現UIResponder+Router,沒有繼續往SuperView發, -(void)routerEventWithName:(NSString *)eventName userInfo:(NSDictionary *)userInfo { if ([eventName isEqualToString:@"TestRouter"]) { NSLog(@"測試1的名稱:%@",userInfo[@"name"]); }else{ // 手動讓響應者傳遞到下一個事件 [self.nextResponder routerEventWithName:eventName userInfo:userInfo]; } } @end
FMDB庫下載地址:https://github.com/ccgus/fmdb
依賴的框架或庫:libsqlite3.tbd
//FMDBManager.h文件
// // FMDBManager.h // 使用fmdb的數據庫管理類 // // Created by Vie on 16/7/28. // Copyright © 2016年 Vie. All rights reserved. // #import <Foundation/Foundation.h> #import "FMDB.h" @interface FMDBManager : NSObject #pragma mark -屬性 #pragma mark 數據庫引用,使用它進行數據庫操做 @property(nonatomic) FMDatabase *database;//一次只能執行一條sql #pragma mark -共有方法 /** * @Author Vie, 2016-07-28 14:29:25 * * @param dbName 數據庫名 * * @return null * * @since 重寫初始化方法,打開對應數據庫。若是打開失敗返回null */ -(instancetype)initWithDB:(NSString *)dbName; /** * @Author Vie, 2016-07-28 14:34:24 * * @param sql SQL語句 * * @return 返回執行結果 * * @since 執行無返回的sql語句 */ -(BOOL)executeNonQuery:(NSString *)sql; /** * @Author Vie, 2016-07-28 14:35:25 * * @param sql SQL語句 * * @return 查詢結果 * * @since 執行有返回的sql語句 */ -(NSMutableArray *)executeQuery:(NSString *)sql; @end
// FMDBManager.m
// // FMDBManager.m // 使用fmdb的數據庫管理類 // // Created by Vie on 16/7/28. // Copyright © 2016年 Vie. All rights reserved. // #import "FMDBManager.h" @interface FMDBManager () @end @implementation FMDBManager #pragma mark重寫初始化方法,若是打開數據庫失敗就返回nil -(instancetype)initWithDB:(NSString *)dbName{ self=[super init]; if (self) { if (![self openDb:dbName]) { self=nil; } } return self; } /** * @Author Vie, 2016-07-28 14:39:33 * * @param dbname 數據庫名稱 * * @return 返回打開數據庫結果 * * @since 打開數據庫 */ -(BOOL)openDb:(NSString *)dbname{ NSString *filePath=[NSHomeDirectory() stringByAppendingString:[NSString stringWithFormat:@"/Documents/%@",dbname]]; NSLog(@"數據庫路徑|:%@",filePath); //建立fmdbatabase對象 _database=[FMDatabase databaseWithPath:filePath]; //打開數據庫上 if ([_database open]) { NSLog(@"數據庫%@打開成功",dbname); return YES; }else{ NSLog(@"數據庫%@打開失敗",dbname); return NO; } } #pragma mark -執行無返回結果的sql,將執行結果返回通知 -(BOOL)executeNonQuery:(NSString *)sql{ //執行更新sql語句,用於插入、修改。刪除 if (![_database executeUpdate:sql]) { NSLog(@"執行sql語句過程當中發生錯誤"); return NO; }else{ return YES; } } #pragma mark -執行有結果返回的sql,將查詢結果數據返回 -(NSMutableArray *)executeQuery:(NSString *)sql{ NSMutableArray *rows=[NSMutableArray array]; //執行查詢sql語句 FMResultSet *result=[_database executeQuery:sql]; //查詢結果可能不止一條 while (result.next) { NSMutableDictionary *dic=[NSMutableDictionary dictionary]; for (int i=0; i<result.columnCount; i++) { dic[[result columnNameForIndex:i]]=[result stringForColumnIndex:i]; } [rows addObject:dic]; } return rows; } -(void)dealloc{ [_database close]; } @end
// FMDBQueueManager.h
// // FMDBQueueManager.h // 使用fmdb的數據庫管理類,支持併發和事物 // // Created by Vie on 16/7/28. // Copyright © 2016年 Vie. All rights reserved. // #import <Foundation/Foundation.h> #import "FMDB.h" @interface FMDBQueueManager : NSObject #pragma mark -屬性 #pragma mark 數據庫引用,使用它進行數據庫操做 @property(nonatomic) FMDatabaseQueue *database;//一次只能執行一條sql #pragma mark -共有方法 /** * @Author Vie, 2016-07-28 14:29:25 * * @param dbName 數據庫名 * * @return null * * @since 重寫初始化方法,打開對應數據庫。若是打開失敗返回null */ -(instancetype)initWithDB:(NSString *)dbName; /** * @Author Vie, 2016-07-28 14:34:24 * * @param sql SQL語句 * * @return 返回執行結果 * * @since 執行無返回的sql語句 */ -(BOOL)executeNonQuery:(NSString *)sql; /** * @Author Vie, 2016-07-28 14:35:25 * * @param sql SQL語句 * * @return 查詢結果 * * @since 執行有返回的sql語句 */ -(NSMutableArray *)executeQuery:(NSString *)sql; /** * @Author Vie, 2016-07-28 18:14:26 * * @param sql 多條sql數組 * * @return 返回執行結果 * * @since 將多條sql當成事務處理 */ -(BOOL)executeTransaction:(NSMutableArray *)sqlArray; @end
// FMDBQueueManager.m
// // FMDBQueueManager.m // 使用fmdb的數據庫管理類,支持併發和事物 // // Created by Vie on 16/7/28. // Copyright © 2016年 Vie. All rights reserved. // #import "FMDBQueueManager.h" @interface FMDBQueueManager () @end @implementation FMDBQueueManager #pragma mark重寫初始化方法,若是打開數據庫失敗就返回nil -(instancetype)initWithDB:(NSString *)dbName{ self=[super init]; if (self) { if (![self openDb:dbName]) { self=nil; } } return self; } /** * @Author Vie, 2016-07-28 14:39:33 * * @param dbname 數據庫名稱 * * @return 返回打開數據庫結果 * * @since 打開數據庫 */ -(BOOL)openDb:(NSString *)dbname{ NSString *filePath=[NSHomeDirectory() stringByAppendingString:[NSString stringWithFormat:@"/Documents/%@",dbname]]; NSLog(@"數據庫路徑|:%@",filePath); //建立fmdbatabase對象,這裏不須要打開數據庫操做 _database=[FMDatabaseQueue databaseQueueWithPath:filePath]; if (_database) { NSLog(@"數據庫%@打開成功",dbname); return YES; }else{ NSLog(@"數據庫%@打開失敗",dbname); return NO; } } #pragma mark -執行無返回結果的sql,將執行結果返回通知 -(BOOL)executeNonQuery:(NSString *)sql{ NSMutableArray *rows=[NSMutableArray array]; [_database inDatabase:^(FMDatabase *db) { if (![db executeUpdate:sql]) { NSLog(@"執行sql語句過程當中發生錯誤"); [rows addObject:@"1"]; }else{ [rows addObject:@"0"]; } }]; return [[rows objectAtIndex:0] isEqualToString:@"0"]?YES:NO; } #pragma mark -執行有結果返回的sql,將查詢結果數據返回 -(NSMutableArray *)executeQuery:(NSString *)sql{ NSMutableArray *rows=[NSMutableArray array]; [_database inDatabase:^(FMDatabase *db) { //執行查詢sql FMResultSet *result=[db executeQuery:sql]; while (result.next) { NSMutableDictionary *dic=[NSMutableDictionary dictionary]; for (int i=0; i<result.columnCount; ++i) { dic[[result columnNameForIndex:i]]=[result stringForColumnIndex:i]; } [rows addObject:dic]; } }]; return rows; } #pragma mark -將多條sql當作事務處理,返回執行結果 -(BOOL)executeTransaction:(NSMutableArray *)sqlArray{ __block BOOL whoopsSomethingWrongHappened = true; [_database inTransaction:^(FMDatabase *db, BOOL *rollback) { for (int i=0;i<sqlArray.count ; i++) { BOOL executeFlag=[db executeUpdate:[sqlArray objectAtIndex:i]]; if (!executeFlag) { NSLog(@"---sql執行失敗:%@",[sqlArray objectAtIndex:i]); } //記錄操做結果,&= 同爲1才結果爲1,一個1一個0結果爲0 whoopsSomethingWrongHappened&=executeFlag; } if (!whoopsSomethingWrongHappened) { //當最後*rollback的值爲YES的時候,事務回退,若是最後*rollback爲NO,事務提交 *rollback = YES; NSLog(@"數據庫操做失敗"); return; }else{ NSLog(@"數據庫操做成功"); } }]; return whoopsSomethingWrongHappened; } -(void)dealloc{ [_database close]; } @end
//使用測試
// Do any additional setup after loading the view, typically from a nib. FMDBQueueManager *dbManager=[[FMDBQueueManager alloc] initWithDB:@"Newdb.db"]; //若是打開數據庫成功就執行下面操做 if (dbManager) { NSString *createTableSQL=@"create table if not exists user(id integer primary key autoincrement not null,name varchar(10),tel varchar(11),address varchar(50));"; if ([dbManager executeNonQuery:createTableSQL]) { NSLog(@"建立USER表成功"); //fmdb sql要一條一條執行 NSString *insertRows=@"insert into user(name,tel,address) values('Vie','18777777777','深圳');"; [dbManager executeNonQuery:@"insert into user(name,tel,address) values('Jack','18666666666','廣州'); "]; [dbManager executeNonQuery:@"insert into user(name,tel,address) values('Musk','15777777777','東莞');"]; [dbManager executeNonQuery:@"insert into user(name,tel,address) values('Mark','15888888888','武漢'); "]; [dbManager executeNonQuery:@"insert into user(name,tel,address) values('Tom','17777777777','孝感');"]; // NSString *insertRows=@"insert into user(name,tel,address) values('Vie','18777777777','深圳'); insert into user(name,tel,address) values('Jack','18666666666','廣州'); insert into user(name,tel,address) values('Musk','15777777777','東莞'); insert into user(name,tel,address) values('Mark','15888888888','武漢'); insert into user(name,tel,address) values('Tom','17777777777','孝感');"; if ([dbManager executeNonQuery:insertRows]) { NSLog(@"插入數據成功"); NSString *updateSQL=@"update user set address ='仙桃',name='哇哈哈' where id=5;"; if ([dbManager executeNonQuery:updateSQL]) { NSLog(@"修改數據成功"); NSString *deleteSQL=@"delete from user where id=1;"; if ([dbManager executeNonQuery:deleteSQL]) { NSLog(@"刪除數據成功"); //查詢數據 NSString *queryRow=@"select * from user "; NSMutableArray *array=[dbManager executeQuery:queryRow]; if (array.count>0) { NSLog(@"查詢到了數據"); } } } } } }
CMPopTipView下載地址:https://github.com/chrismiles/CMPopTipView
它會顯示一個圓角矩形「彈出視圖帶指示」,相似QQ會話界面+號點擊後展現視圖
// ViewController.m
// // ViewController.m // UseCMPopTipView // // Created by Vie on 2017/1/16. // Copyright © 2017年 Vie. All rights reserved. // #import "ViewController.h" #import "CMPopTipView.h" @interface ViewController () @property (nonatomic ,strong) CMPopTipView *popTipView; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. self.navigationItem.rightBarButtonItem=[[UIBarButtonItem alloc] initWithTitle:@"..." style:UIBarButtonItemStylePlain target:self action:@selector(popView)]; [self.view setBackgroundColor:[UIColor yellowColor]]; } -(void)popView{ if (!_popTipView) { UIView *customView=[[UIView alloc] initWithFrame:CGRectMake(0, 0, 150, 44*4)]; NSArray *titleArray=[NSArray arrayWithObjects:@"One",@"Two",@"Three",@"Four", nil]; for (int i=0; i<titleArray.count; i++) { //設置按鈕 UIButton *btn=[UIButton buttonWithType:UIButtonTypeSystem]; btn.frame=CGRectMake(0, i*44, 150, 43); btn.tag=110+i; [btn addTarget:self action:@selector(popViewAction:) forControlEvents:UIControlEventTouchUpInside]; //設置按鈕文本和顏色 [btn setTitle:[titleArray objectAtIndex:i] forState:UIControlStateNormal]; [btn setTintColor:[UIColor blackColor]]; //設置分格邊線 UIView *line=[[UIView alloc] initWithFrame:CGRectMake(0, 44*(i+1), 150, 1)]; line.backgroundColor=[UIColor colorWithRed:220./255 green:220./255 blue:220./255 alpha:1]; [customView addSubview:btn]; [customView addSubview:line]; } //初始化泡泡風格彈出頁面內容 _popTipView=[[CMPopTipView alloc] initWithCustomView:customView]; //設置彈出頁面背景色 _popTipView.backgroundColor=[UIColor whiteColor]; //設置邊框線顏色 _popTipView.borderColor = [UIColor colorWithRed:220./255 green:220./255 blue:220./255 alpha:1]; //點擊其餘地方事是否隱藏改彈出頁面 _popTipView.dismissTapAnywhere = YES; //是否3d效果 _popTipView.has3DStyle=NO; //是否容許自定義視圖填充 _popTipView.shouldEnforceCustomViewPadding=NO; //是否有陰影 _popTipView.hasShadow=NO; } //指定彈出itme,給到彈出頁面定位 [_popTipView presentPointingAtBarButtonItem:self.navigationItem.rightBarButtonItem animated:YES]; } -(void)popViewAction:(UIButton *)sender{ //隱藏彈出界面 [_popTipView dismissAnimated:NO]; if (sender.tag==110) { NSLog(@"One"); }else if (sender.tag==111){ NSLog(@"Two"); }else if (sender.tag==112){ NSLog(@"Three"); }else if (sender.tag==113){ NSLog(@"Four"); } } @end
CustomIOSAlertView自定義AlertView
CustomIOSAlertView下載地址:https://github.com/wimagguc/ios-custom-alertview
// ViewController.m
// // ViewController.m // UseCustomIOSAlertView // // Created by Vie on 2017/1/18. // Copyright © 2017年 Vie. All rights reserved. // #import "ViewController.h" #import "CustomIOSAlertView.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Just a subtle background color [self.view setBackgroundColor:[UIColor colorWithRed:0.8f green:0.8f blue:0.8f alpha:1.0f]]; // A simple button to launch the demo UIButton *launchDialog = [UIButton buttonWithType:UIButtonTypeCustom]; [launchDialog setFrame:CGRectMake(10, 30, self.view.bounds.size.width-20, 50)]; [launchDialog addTarget:self action:@selector(launchDialog:) forControlEvents:UIControlEventTouchDown]; [launchDialog setTitle:@"Launch Dialog" forState:UIControlStateNormal]; [launchDialog setBackgroundColor:[UIColor whiteColor]]; [launchDialog setTitleColor:[UIColor blueColor] forState:UIControlStateNormal]; [launchDialog.layer setBorderWidth:0]; [launchDialog.layer setCornerRadius:5]; [self.view addSubview:launchDialog]; } - (IBAction)launchDialog:(id)sender { CustomIOSAlertView *alertView=[[CustomIOSAlertView alloc] init]; alertView.tag=103; float containeWidth=290; //提示標題 NSString *titleText=@"新版本升級提示"; float titleLableHeight=66; UILabel *titleLable=[[UILabel alloc] initWithFrame:CGRectMake(0, 0, containeWidth, titleLableHeight)]; titleLable.font = [UIFont systemFontOfSize:20]; titleLable.textColor = [UIColor blackColor]; titleLable.backgroundColor = [UIColor clearColor]; titleLable.lineBreakMode =NSLineBreakByWordWrapping; titleLable.numberOfLines =0; titleLable.textAlignment =NSTextAlignmentCenter; titleLable.text=titleText; //提示內容 float textLabelX=20; NSString *messageText=@"000000000000000000000000000000\n11111111\n2222222222222222222\n23412412312321321312321312312312312312312312312321321312\n43424123123sjdfjdsklfjksjf\n000000000000000000000000000000\n11111111\n2222222222222222222\n23412412312321321312321312312312312312312312312321321312\n43424123123sjdfjdsklfjksjf\n"; CGSize messageSize=[messageText boundingRectWithSize:CGSizeMake(containeWidth-textLabelX-5, 10000) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:15]} context:nil].size; UILabel *textLabel = [[UILabel alloc] initWithFrame:CGRectMake(textLabelX, titleLableHeight, messageSize.width, messageSize.height)]; textLabel.font = [UIFont systemFontOfSize:15]; textLabel.textColor = [UIColor blackColor]; textLabel.backgroundColor = [UIColor clearColor]; textLabel.lineBreakMode =NSLineBreakByWordWrapping; textLabel.numberOfLines =0; textLabel.textAlignment =NSTextAlignmentLeft; textLabel.text=messageText; //自定義提示背景視圖 UIView *containeView=[[UIView alloc] initWithFrame:CGRectMake(0, 0, containeWidth, CGRectGetMaxY(textLabel.frame))]; [containeView addSubview:titleLable]; [containeView addSubview:textLabel]; //設置提示視圖 [alertView setContainerView:containeView]; //設置按鈕 [alertView setButtonTitles:@[@"取消",@"肯定"]]; //實現按鈕回調事件 [alertView setOnButtonTouchUpInside:^(CustomIOSAlertView *alertView, int buttonIndex) { NSLog(@"點擊按鈕下標:%d,按鈕tag:%ld",buttonIndex,(long)alertView.tag); [alertView close]; }]; [alertView setUseMotionEffects:true]; [alertView show]; } @end
Masonry庫下載地址:https://github.com/SnapKit/Masonry
簡介:
Masonry是一個對系統NSLayoutConstraint進行封裝的第三方自動佈局框架,採用鏈式編程的方式提供給開發者API。系統AutoLayout支持的操做,Masonry都支持,相比系統API功能來講,Masonry是有過之而無不及。Masonry是同時支持Mac和iOS兩個平臺的,在這兩個平臺上均可以使用Masonry進行自動佈局。
在使用Masonry進行約束時,有一些是須要注意的。
1.在使用Masonry添加約束以前,須要在addSubview以後才能使用,不然會致使崩潰。
2.在添加約束時初學者常常會出現一些錯誤,約束出現問題的緣由通常就是兩種:約束衝突和缺乏約束。對於這兩種問題,能夠經過調試和log排查(建議x,y,width,height分開添加)。
mas_makeConstraints() | 添加約束 |
mas_remakeConstraints() | 移除以前的約束,從新添加新的約束 |
mas_updateConstraints() | 更新約束 |
equalTo() | 參數是對象類型,通常是視圖對象或者mas_width這樣的座標系對象 |
mas_equalTo() | 和上面功能相同,參數能夠傳遞基礎數據類型對象,能夠理解爲比上面的API更強大 |
width() | 用來表示寬度,例如表明view的寬度 |
mas_width() | 用來獲取寬度的值。和上面的區別在於,一個表明某個座標系對象,一個用來獲取座標系對象的值 |
上面例如equalTo或者width這樣的,有時候須要涉及到使用mas_前綴,這在開發中須要注意做區分。
若是在當前類引入#import "Masonry.h"以前,用下面兩種宏定義聲明一下,就不須要區分mas_前綴。
// 定義這個常量,就能夠不用在開發過程當中使用"mas_"前綴。 #define MAS_SHORTHAND // 定義這個常量,就可讓Masonry幫咱們自動把基礎數據類型的數據,自動裝箱爲對象類型。 #define MAS_SHORTHAND_GLOBALS
//例
//ViewController.m文件
// // ViewController.m // MasonnyLearn // // Created by Vie on 2017/5/10. // Copyright © 2017年 Vie. All rights reserved. // #import "ViewController.h" // 定義這個常量,就能夠不用在開發過程當中使用"mas_"前綴。 #define MAS_SHORTHAND // 定義這個常量,就可讓Masonry幫咱們自動把基礎數據類型的數據,自動裝箱爲對象類型。 #define MAS_SHORTHAND_GLOBALS #import "Masonry.h" @interface ViewController () @property(nonatomic, strong) UIView *testView; @end @implementation ViewController #pragma mark 懶加載 -(UIView *)testView{ if (!_testView) { _testView=[[UIView alloc] init]; [_testView setBackgroundColor:[UIColor redColor]]; [_testView.layer setCornerRadius:5.0f]; } return _testView; } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. //在使用Masonry添加約束以前,須要在addSubview以後才能使用,不然會致使崩潰。 [self.view addSubview:self.testView]; [self.testView mas_makeConstraints:^(MASConstraintMaker *make) { make.width.equalTo(self.view.width).offset(-30);//設置寬度約束爲self.view的寬度-30 make.height.equalTo(50);//設置高度約束 make.left.equalTo(self.view.left).offset(15);//設置x軸約束 make.top.equalTo(self.view.top).offset(20);//設置y軸約束 }]; } @end
//效果
//讓約束從導航欄底部開始算起 self.edgesForExtendedLayout = UIRectEdgeNone; self.extendedLayoutIncludesOpaqueBars = NO; self.modalPresentationCapturesStatusBarAppearance = NO;
JDStatusBarNotification自定義狀態欄通知
//簡單實用示例,更多實用看下載介紹
[JDStatusBarNotification addStyleNamed:@"1111" prepare:^JDStatusBarStyle *(JDStatusBarStyle *style) { style.barColor = [UIColor yellowColor]; style.textColor = [UIColor blackColor]; style.font = [UIFont systemFontOfSize:14.0f]; style.textShadow = nil; style.animationType = JDStatusBarAnimationTypeNone; style.progressBarColor = [UIColor orangeColor]; style.progressBarHeight = 20; return style; }]; //顯示一條通知 [JDStatusBarNotification showWithStatus:@"Hahah" styleName:@"1111"]; [JDStatusBarNotification showProgress:0.1];
//示例
// // ViewController.m // CoreAnimationLearn // // Created by Vie on 2017/6/20. // Copyright © 2017年 Vie. All rights reserved. // #import "ViewController.h" #import "WMPageController.h" @interface ViewController ()<WMPageControllerDelegate,WMPageControllerDataSource> @property (nonatomic, strong) NSArray *infoArray;//單元格描述數組 @property (nonatomic, strong) NSArray *classNameArray;//單元格要調用的類名數組 @property (nonatomic, strong) WMPageController *pageCtl;//相似網頁頻道翻頁控制 @end @implementation ViewController #pragma mark Lazy loading -(WMPageController *)pageCtl{ if (!_pageCtl) { _pageCtl=[[WMPageController alloc] init]; _pageCtl.dataSource=self; _pageCtl.delegate=self; _pageCtl.automaticallyCalculatesItemWidths=YES;//字段計算每一個頻道的字符串寬度 _pageCtl.titleColorNormal=[UIColor redColor];//頻道欄默認標題顏色 _pageCtl.titleColorSelected = [UIColor orangeColor];//頻道欄選中標題顏色 _pageCtl.menuViewStyle=WMMenuViewStyleLine;//頻道欄選中樣式 _pageCtl.progressColor=[UIColor grayColor];//選中後的下劃線顏色 _pageCtl.itemMargin=10;//設置每一個Item之間的間隙統一值 } return _pageCtl; } -(NSArray *)infoArray{ if (!_infoArray) { _infoArray=@[@"圖層的樹狀結構", @"寄宿圖", @"圖層幾何學", @"視覺效果", @"變換", @"專有圖層", @"隱式動畫", @"顯式動畫", @"圖層時間", @"緩衝", @"基於定時器的動畫", @"性能調優", @"高效繪圖", @"圖像IO", @"圖層性能" ]; } return _infoArray; } -(NSArray *)classNameArray{ if (!_classNameArray) { _classNameArray=@[@"LayerTreeViewController", @"BoardingFigureViewController", @"LayerGeometryViewController", @"VisualEffectViewController", @"TransformViewController", @"ProprietaryLayerViewController", @"ImplicitAnimationViewController", @"ExplicitAnimationViewController", @"LayerOfTimeViewController", @"BufferViewController", @"AnimationBasedTimerViewController", @"PerformanceTuningViewController", @"EfficientMappingViewController", @"ImageIOViewController", @"LayerPropertiesViewController" ]; } return _classNameArray; } #pragma mark 視圖控制器回調 - (void)viewDidLoad { [super viewDidLoad]; [self.view setBackgroundColor:RGB_ALPHA_COLOR(230, 230, 230, 1)]; self.title=[[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"]; [self addChildViewController:self.pageCtl]; [self.view addSubview:self.pageCtl.view]; } #pragma mark WMPageControllerDataSource //設置頻道數量 -(NSInteger)numbersOfChildControllersInPageController:(WMPageController *)pageController{ return self.infoArray.count; } //設置頻道對應控制器 -(UIViewController *)pageController:(WMPageController *)pageController viewControllerAtIndex:(NSInteger)index{ Class class=NSClassFromString(self.classNameArray[index]); id classInstance=[[class alloc] init]; return classInstance; } //設置頻道標題 -(NSString *)pageController:(WMPageController *)pageController titleAtIndex:(NSInteger)index{ return [self.infoArray objectAtIndex:index]; } #pragma mark WMPageControllerDataSource @end
運行效果
MJExtension是一套字典和模型之間互相轉換的超輕量級框架,不須要你的模型類繼承任何特殊基類,毫無污染,毫無侵入性;MJExtension能完成的功能:
字典(JSON) --> 模型(Model)
模型(Model) --> 字典(JSON)
字典數組(JSON Array) --> 模型數組(Model Array)
模型數組(Model Array) --> 字典數組(JSON Array)
//MyinfoModel.h模型文件
// // MyinfoModel.h // RuntimeTest // // Created by Vie on 2017/2/14. // Copyright © 2017年 Vie. All rights reserved. // #import <Foundation/Foundation.h> @interface MyinfoModel : NSObject @property(nonatomic,strong) NSString *name;//姓名 @property(nonatomic,assign) NSNumber *age;//年齡 @property(nonatomic,strong) NSArray *array;//獲獎集合 @property(nonatomic,strong) NSDictionary *dic;//獲獎描述 @property(nonatomic,strong) MyinfoModel *mySon;//個人仔 @end
//MyinfoModel.m模型文件
// // MyinfoModel.m // RuntimeTest // // Created by Vie on 2017/2/14. // Copyright © 2017年 Vie. All rights reserved. // #import "MyinfoModel.h" @implementation MyinfoModel @end
//使用代碼
#import "MyinfoModel.h" #import "MJExtension.h" NSDictionary *dictionary = @{ @"xxxx":@"xxxx", @"name":@"Vie", @"age":@24, @"array":@[@"優秀少先隊員",@"優秀共青團員",@"優秀黨員"], @"dic":@{ @"info1":@"五年級得到優秀少先隊員稱號", @"info2":@"初三得到優秀共青團員稱號", @"info3":@"大三得到優秀黨員稱號", }, @"mySon":@{ @"name":@"Vieson", @"age":@3, @"array":@[@"乖寶寶",@"精靈鬼"], @"dic":@{ @"info1":@"小寶寶很可愛", }, }, }; //將字典轉模型 MyinfoModel *modelForMJ=[MyinfoModel mj_objectWithKeyValues:dictionary]; //將模型轉字典 NSMutableDictionary *dicByModelForMJ=[modelForMJ mj_keyValues]; //將字典數組轉模型數組 NSArray *modelArray = [MyinfoModel mj_objectArrayWithKeyValuesArray:@[dictionary,dictionary,dictionary]]; //將模型數組轉成字典數組 NSMutableArray *dicArray=[MyinfoModel mj_keyValuesArrayWithObjectArray:modelArray];
下載地址:https://github.com/AFNetworking/AFNetworking
3.0版本:
使用 AFHTTPSessionManager這個網絡管理者
//示例
// // ViewController.m // AFNetWorkingLearn // // Created by Vie on 2017/12/19. // Copyright © 2017年 Vie. All rights reserved. // #import "ViewController.h" #import "AFNetworking.h" @interface ViewController ()<NSXMLParserDelegate> @property (strong, nonatomic) NSURLSession *session; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; } /** @author Vie,2017年12月19日09:22:11 get請求測試 */ -(void)get { //1.建立會話管理者 AFHTTPSessionManager *manager = [AFHTTPSessionManager manager]; //2.封裝參數 NSDictionary *dic= @{ @"username":@"Vie", @"pwd":@"123456", }; //3.發送GET請求 /* 第一個參數:請求路徑(NSString)+ 不須要加參數 第二個參數:發送給服務器的參數數據 第三個參數:progress 進度回調 第四個參數:success 成功以後的回調(此處的成功或者是失敗指的是整個請求) task:請求任務 responseObject:注意!!!響應體信息--->(json--->oc)) task.response: 響應頭信息 第五個參數:failure 失敗以後的回調 */ [manager GET:@"須要請求的URL" parameters:dic progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { NSLog(@"success--%@--%@",[responseObject class],responseObject); } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { NSLog(@"failure--%@",error); }]; } /** @author Vie,2017年12月19日09:22:11 post請求測試 */ -(void)post { //1.建立會話管理者 AFHTTPSessionManager *manager = [AFHTTPSessionManager manager]; //2.封裝參數 NSDictionary *dic= @{ @"username":@"Vie", @"pwd":@"123456", }; //3.發送POST請求 /* 第一個參數:請求路徑(NSString)+ 不須要加參數 第二個參數:發送給服務器的參數數據 第三個參數:progress 進度回調 第四個參數:success 成功以後的回調(此處的成功或者是失敗指的是整個請求) task:請求任務 responseObject:注意!!!響應體信息--->(json--->oc)) task.response: 響應頭信息 第五個參數:failure 失敗以後的回調 */ [manager POST:@"須要請求的URL" parameters:dic progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { NSLog(@"success--%@--%@",[responseObject class],responseObject); } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { NSLog(@"failure--%@",error); }]; } /** @author Vie,2017年12月19日09:22:11 下載操做 */ -(void)download { //1.建立會話管理者 AFHTTPSessionManager *manager = [AFHTTPSessionManager manager]; //2.肯定請求路徑 NSURL *url = [NSURL URLWithString:@"須要請求的URL"]; //3.建立請求對象 NSURLRequest *request = [NSURLRequest requestWithURL:url]; //4.發送網絡請求下載文件 /* 第一個參數:請求對象 第二個參數:progress 進度回調 downloadProgress @property int64_t totalUnitCount; @property int64_t completedUnitCount; 第三個參數:destination 讓咱們告訴系統應該把文件存放到什麼地方 內部自動的完成剪切處理 第四個參數: completionHandler 完成以後的回調 response 響應頭信息 filePath 文件最終的存儲路徑 error 錯誤信息 */ [[manager downloadTaskWithRequest:request progress:^(NSProgress * _Nonnull downloadProgress) { //下載進度 NSLog(@"%f",1.0 * downloadProgress.completedUnitCount / downloadProgress.totalUnitCount); } destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) { //拼接文件的全路徑 NSString *fullpath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:response.suggestedFilename]; NSLog(@"fullpath == %@",fullpath); return [NSURL fileURLWithPath:fullpath]; } completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) { NSLog(@"%@",filePath); }] resume]; } /** @author Vie,2017年12月19日09:22:11 上傳操做 */ -(void)upload { //1.建立會話管理者 AFHTTPSessionManager *manager = [AFHTTPSessionManager manager]; //2.發送請求上傳文件 /* 第一個參數:請求路徑(NSString) 第二個參數:非文件參數 第三個參數:constructingBodyWithBlock 拼接數據(告訴AFN要上傳的數據是哪些) 第四個參數:progress 進度回調 第五個參數:success 成功回調 responseObject:響應體 第六個參數:failure 失敗的回調 */ [manager POST:@"須要請求的URL" parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> _Nonnull formData) { NSData *data = UIImagePNGRepresentation([UIImage imageNamed:@"1.png"]); //拼接數據 /* 第一個參數:文件參數 (二進制數據) 第二個參數:參數名~file 第三個參數:該文件上傳到服務器以什麼名稱來保存 第四個參數: */ [formData appendPartWithFileData:data name:@"file" fileName:@"123.png" mimeType:@"image/png"]; } progress:^(NSProgress * _Nonnull uploadProgress) { //上傳進度 NSLog(@"%f",1.0 * uploadProgress.completedUnitCount / uploadProgress.totalUnitCount); } success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { NSLog(@"success--%@",responseObject); } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { NSLog(@"failure -- %@",error); }]; } /** @author Vie,2017年12月19日09:22:11 NSURLSessionConfiguration配置信息 */ -(NSURLSession *)session { if (_session == nil) { //設置配置信息 NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration]; //統一設置請求超時 config.timeoutIntervalForRequest = 15.0; //設置是否容許蜂窩網絡訪問 config.allowsCellularAccess = YES; _session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[NSOperationQueue mainQueue]]; } return _session; } /** @author Vie,2017年12月19日09:46:44 json處理 */ -(void)JSon { //1.建立會話管理者 AFHTTPSessionManager *manager = [AFHTTPSessionManager manager]; /* 1)afn內部默認已經完成了JSON解析工做 優勢:方便 缺點:若是服務器返回的數據不是JSON會報錯 */ NSDictionary *dict = @{@"type":@"JSON"}; //2.發請求 [manager GET:@"須要請求的URL" parameters:dict progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { NSLog(@"%@--%@",[responseObject class],responseObject); } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { NSLog(@"%@---",error); }]; } /** @author Vie,2017年12月19日09:46:44 XML處理 */ -(void)XML { // <NSXMLParserDelegate>代理協議 //1.建立會話管理者 AFHTTPSessionManager *manager = [AFHTTPSessionManager manager]; //設置以XML的方式來解析數據 manager.responseSerializer = [AFXMLParserResponseSerializer serializer]; NSDictionary *dict = @{@"type":@"XML"}; //2.發請求 [manager GET:@"須要請求的URL" parameters:dict progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { NSLog(@"%@--%@",[responseObject class],responseObject); //1.建立解析器 NSXMLParser *parser = (NSXMLParser *)responseObject; //2.設置代理 parser.delegate = self; //3.開始解析 [parser parse]; } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { NSLog(@"%@---",error); }]; } #pragma mark NSXMLParserDelegate -(void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary<NSString *,NSString *> *)attributeDict { NSLog(@"%@--%@",elementName,attributeDict); } /** @author Vie,2017年12月19日09:46:44 其餘數據類型處理 */ -(void)OtherData { //1.建立會話管理者 AFHTTPSessionManager *manager = [AFHTTPSessionManager manager]; //設置不作處理 manager.responseSerializer = [AFHTTPResponseSerializer serializer]; //2.發請求 [manager GET:@"須要請求的URL" parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { NSLog(@"%@--%@",[responseObject class],responseObject); } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { NSLog(@"%@---",error); }]; } /** @author Vie,2017年12月19日09:46:44 網絡狀態監測 */ -(void)networkStatusChangeAFN { //1.得到一個網絡狀態監聽管理者 AFNetworkReachabilityManager *manager = [AFNetworkReachabilityManager sharedManager]; //2.監聽狀態的改變(當網絡狀態改變的時候就會調用該block) [manager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) { /* AFNetworkReachabilityStatusUnknown = -1, 未知 AFNetworkReachabilityStatusNotReachable = 0, 沒有網絡 AFNetworkReachabilityStatusReachableViaWWAN = 1, 3G|4G AFNetworkReachabilityStatusReachableViaWiFi = 2, WIFI */ switch (status) { case AFNetworkReachabilityStatusReachableViaWiFi: NSLog(@"wifi"); break; case AFNetworkReachabilityStatusReachableViaWWAN: NSLog(@"蜂窩網絡"); break; case AFNetworkReachabilityStatusNotReachable: NSLog(@"沒有網絡"); break; case AFNetworkReachabilityStatusUnknown: NSLog(@"未知"); break; default: break; } }]; //3.手動開啓 開始監聽 [manager startMonitoring]; } @end
下載地址:https://github.com/hackiftekhar/IQKeyboardManager
//在 AppDelegate 中設置全局屬性 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { IQKeyboardManager *keyboardManager = [IQKeyboardManager sharedManager]; // 獲取類庫的單例變量 keyboardManager.enable = YES; // 控制整個功能是否啓用 keyboardManager.shouldResignOnTouchOutside = YES; // 控制點擊背景是否收起鍵盤 keyboardManager.shouldToolbarUsesTextFieldTintColor = YES; // 控制鍵盤上的工具條文字顏色是否用戶自定義 keyboardManager.toolbarManageBehaviour = IQAutoToolbarBySubviews; // 有多個輸入框時,能夠經過點擊Toolbar 上的「前一個」「後一個」按鈕來實現移動到不一樣的輸入框 keyboardManager.enableAutoToolbar = YES; // 控制是否顯示鍵盤上的工具條 keyboardManager.shouldShowTextFieldPlaceholder = YES; // 是否顯示佔位文字 keyboardManager.placeholderFont = [UIFont boldSystemFontOfSize:17]; // 設置佔位文字的字體 keyboardManager.keyboardDistanceFromTextField = 10.0f; // 輸入框距離鍵盤的距離 return YES; }