一,上传gif动图的时候,需要不解码的Data数据,需要通过路径获取转换成Data:
// //上传gif图 //bundle中 NSData *data = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"motion" ofType:@"GIF"] ]; //手机资源中 NSString *url = [info objectForKey:UIImagePickerControllerImageURL]; NSData *imageData = [NSData dataWithContentsOfFile:url]; //以下方式转换上传的gif图没有动态效果 UIImagePNGRepresentation(image); UIImageJPEGRepresentation(image, 1.0); //
二,collectionview滑动固定其滑动距离,分页滑动:
// // @interface SkyVideoCoueseLayout : UICollectionViewFlowLayout @property (nonatomic,assign)CGFloat dragShort; @end // // #import "SkyVideoCourseLayout.h" @implementation SkyVideoCourseLayout - (void)prepareLayout { [super prepareLayout]; if(self.dragShort <= 0){ return; } if(self.collectionView != nil){ self.collectionView.decelerationRate = UIScrollViewDecelerationRateFast; //CGSize size = [[self.collectionView valueForKey:@"interpageSpacing"] CGSizeValue]; //if(!CGSizeEqualToSize(CGSizeZero, size)){ if(self.scrollDirection == UICollectionViewScrollDirectionHorizontal){ NSValue *sizeValue = [NSValue valueWithCGSize:CGSizeMake(-self.dragShort, 0.0)]; [self.collectionView setValue:sizeValue forKey:@"interpageSpacing"]; }else{ NSValue *sizeValue = [NSValue valueWithCGSize:CGSizeMake(0.0, -self.dragShort)]; [self.collectionView setValue:sizeValue forKey:@"interpageSpacing"]; } //} //CGPoint origin = [[self.collectionView valueForKey:@"pagingOrigin"] CGPointValue]; //if(!CGPointEqualToPoint(CGPointZero, origin)){ NSValue *originValue = [NSValue valueWithCGPoint:CGPointZero]; [self.collectionView setValue:originValue forKey:@"pagingOrigin"]; //} } } @end
三,collectionview cell出现的时候产生动画:
// //代理 - (void)collectionView:(UICollectionView *)collectionView willDisplayCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath { // 这个方法会在 cell 即将显示在屏幕上时调用 // 你可以在这里执行缩小动画 // 假设你要为 cell 添加缩小动画 if ([cell isKindOfClass:[UICollectionViewCell class]]) { UICollectionViewCell *cellToAnimate = (UICollectionViewCell *)cell; // 缩小为原始尺寸的 80% cellToAnimate.transform = CGAffineTransformMakeScale(0.8, 0.8); [UIView animateWithDuration:0.3 animations:^{ // 恢复原始尺寸 cellToAnimate.transform = CGAffineTransformIdentity; }]; } } // //
四,网络监测工具,实时监测网络环境,网络强弱,主要思路是每几秒钟请求一次网络,如果请求成功,则网络连接成功,如果请求失败,则标识网络连接失败。
具体内部的重点是:
1,请求阿里的DNS公网地址:
NSString *const SkyAlibabaPublicDNS = @”https://223.5.5.5/”;
2,timeoutIntervalForResource和timeoutIntervalForRequest属性是设置当前请求的超时时间;
3,_urlSession = nil;重置session,主要是为了重置超时时间,否则超时时间不准确;
4,SkyPublicTimerTool为计时器封装工具;
具体代码如下:
// // //.h文件 // // SkyNetworkDetectionTool.h // Course // // Created by skyzizhu on 2023/12/5. // Copyright © 2023 Ashes. All rights reserved. // #import <Foundation/Foundation.h> NS_ASSUME_NONNULL_BEGIN typedef NS_ENUM(NSInteger,SkyNetworkDetectionState) { SkyNetworkDetectionUnknown = 0,//未知 SkyNetworkDetectionWifi = 2,//wifi SkyNetworkDetection2G,//2G SkyNetworkDetection3G,//3G SkyNetworkDetection4G,//4G SkyNetworkDetection5G,//5G }; @interface SkyNetworkDetectionTool : NSObject + (instancetype)detection; @property (nonatomic,assign)NSTimeInterval timeoutInterval; ///开始检测,reachable:是否有网,state:哪种网络类型 - (void)startDetectionResult:(void(^_Nullable)(SkyNetworkDetectionState state,BOOL reachable))result; - (void)stop; @end NS_ASSUME_NONNULL_END // //.m文件 // // SkyNetworkDetectionTool.m // Course // // Created by skyzizhu on 2023/12/5. // Copyright © 2023 Ashes. All rights reserved. // #import "SkyNetworkDetectionTool.h" #import "Reachability.h" #import "SkyPublicTimerTool.h" NSString *const SkyAlibabaPublicDNS = @"https://223.5.5.5/"; @interface SkyNetworkDetectionTool()<NSURLSessionDelegate> @property (nonatomic,strong,nullable)SkyPublicTimerTool *timerTool; @property (nonatomic,strong,nullable)Reachability *reachability; @property (nonatomic,strong,nullable)NSURLSession *urlSession; @property (nonatomic,copy,nullable)void(^networkStateDetectionResultHandle)(SkyNetworkDetectionState state,BOOL reachable); //是否有网络 @property (nonatomic,assign)BOOL isReachable; @end @implementation SkyNetworkDetectionTool + (instancetype)detection { static SkyNetworkDetectionTool *detection = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ detection = [[SkyNetworkDetectionTool alloc] init]; }); return detection; } - (instancetype)init { self = [super init]; if(self){ self.timerTool = [[SkyPublicTimerTool alloc]init]; self.timerTool.timeInterval = self.timeoutInterval; self.reachability = [Reachability reachabilityForInternetConnection]; //默认有网 self.isReachable = YES; } return self; } - (NSTimeInterval)timeoutInterval { if(0.0 == _timeoutInterval){ _timeoutInterval = 2.0; } return _timeoutInterval; } ///开始检测 - (void)startDetectionResult:(void(^_Nullable)(SkyNetworkDetectionState state,BOOL reachable))result { self.networkStateDetectionResultHandle = result; // __weak typeof(self) weakSelf = self; [self.timerTool startTheTimer]; [self.timerTool setDoingTimerHandle:^(NSInteger duration) { // 获取当前网络状态 NetworkStatus networkStatus = [weakSelf.reachability currentReachabilityStatus]; // 处理当前网络状态 [weakSelf handleNetworkStatus:networkStatus]; }]; } - (void)handleNetworkStatus:(NetworkStatus)networkStatus { SkyNetworkDetectionState netState = SkyNetworkDetectionUnknown; switch (networkStatus) { case NotReachable: netState = SkyNetworkDetectionUnknown; break; case ReachableViaWiFi: netState = SkyNetworkDetectionWifi; break; case ReachableViaWWAN: { // 根据网络类型判断是2G还是3G CTTelephonyNetworkInfo *telephonyNetworkInfo = [[CTTelephonyNetworkInfo alloc] init]; NSString *currentRadioAccessTechnology = telephonyNetworkInfo.currentRadioAccessTechnology; if (currentRadioAccessTechnology) { if ([currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyGPRS] || [currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyEdge]) { netState = SkyNetworkDetection2G; } else if ([currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyWCDMA] || [currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyHSDPA] || [currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyHSUPA] || [currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyCDMA1x] || [currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyCDMAEVDORev0] || [currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyCDMAEVDORevA] || [currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyCDMAEVDORevB] || [currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyeHRPD]) { netState = SkyNetworkDetection3G; } else if ([currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyLTE]) { netState = SkyNetworkDetection4G; } else{ if (@available(iOS 14.1, *)) { if ([currentRadioAccessTechnology isEqualToString:CTRadioAccessTechnologyNR]) { netState = SkyNetworkDetection5G; } } } } } break; default: break; } if(networkStatus == NotReachable){ self.isReachable = NO; }else{ __weak typeof(self) weakSelf = self; [self hostReachable:SkyAlibabaPublicDNS complate:^(NSError * _Nullable error) { weakSelf.isReachable = (error == nil); }];; } if(self.networkStateDetectionResultHandle){ self.networkStateDetectionResultHandle(netState, self.isReachable); } } - (void)hostReachable:(NSString *)host complate:(void(^_Nullable)(NSError * _Nullable error))complate { NSURL *url = [NSURL URLWithString:host]; NSURLRequest *request = [NSURLRequest requestWithURL:url]; NSURLSessionDataTask *dataTask = [self.urlSession dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { dispatch_sync(dispatch_get_main_queue(), ^{ if(complate){ complate(error); } }); }]; [dataTask resume]; } - (void)stop { [self.timerTool invalidate]; self.networkStateDetectionResultHandle = nil; self.isReachable = YES; } - (NSURLSession *)urlSession { _urlSession = nil; NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; configuration.requestCachePolicy = NSURLRequestReloadIgnoringLocalCacheData; configuration.timeoutIntervalForResource = self.timeoutInterval; configuration.timeoutIntervalForRequest = self.timeoutInterval; _urlSession = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil]; return _urlSession; } @end // //
五,如何获取collectionview的头部视图(section):
// // NSIndexPath *indexPath = [NSIndexPath indexPathForItem:0 inSection:0]; SkyShowHomeHeaderView *reusableView = [subController.collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"SkyShowHomeHeaderViewID" forIndexPath:indexPath]; // //
六,如何获取tableview的头部视图(section):
// // SkyFilterListSectionView *sectionView = (SkyFilterListSectionView *)[self.tableView headerViewForSection:0]; return sectionView; //通过headerViewForSection方法获取 //
七,navigationController销毁当前页面,并push到下一个页面:
// // // 销毁当前页面,并跳转到预约成功页面 NSMutableArray *viewControllers = self.navigationController.viewControllers.mutableCopy; //销毁当前页面 [viewControllers removeLastObject]; //跳转的新页面 SkyConsultAppointmentSucceedController *appoSucVc = [[SkyConsultAppointmentSucceedController alloc]init]; // [viewControllers addObject:appoSucVc]; [self.navigationController setViewControllers:viewControllers.copy animated:YES]; // //
八,Git中查看某一个文件具体修改了哪些内容:
//git diff filepath
//查看当前已修改且未提交的文件跟最后一次提交时修改的区别
git diff Course/Course.xcodeproj/project.pbxproj
//
//查看两次提交前后的区别,3a0e0e075为提交1,9d49b66c7为提交2
git diff 3a0e0e075 9d49b66c7 Course/Course.xcodeproj/project.pbxproj
九,OC中的异常捕获,try-catch:
//try块中的代码如果抛出异常,这个异常会被@catch块捕获,然后异常的reason属性会被打印出来。无论是否发生异常,finally块中的代码都会被执行。 // @try { NSMutableArray *array = [NSMutableArray array]; NSString *nilElem = nil; [array addObject:nilElem]; NSLog(@"%@",array); } @catch (NSException *exception) { NSLog(@"@catch - - %@",exception.reason); } @finally { NSLog(@"@finally"); } // //
十,OC中一些异常机制处理,NSString:
// //.h @interface NSString (SkyException) /// substringWithRange - (NSString *_Nullable)substringWithRange:(NSRange)range error:(NSError *_Nonnull*_Nullable)error; /// substringToIndex - (NSString *_Nullable)substringToIndex:(NSInteger)index error:(NSError *_Nonnull*_Nullable)error; /// substringFromIndex - (NSString *_Nullable)substringFromIndex:(NSInteger)index error:(NSError *_Nonnull*_Nullable)error; @end // //.m #import "NString+SkyException.h" typedef NS_ENUM(NSInteger,SkyNSStringExceptionErrorCode) { SkyStringSubstringWithRangeErrorCode = 100001, SkyStringSubstringToIndexErrorCode = 100002, SkyStringSubstringFromIndexErrorCode = 100003, }; @implementation NSString (SkyException) - (NSString *_Nullable)substringWithRange:(NSRange)range error:(NSError *_Nonnull*_Nullable)error { if (NSMaxRange(range) <= [self length]) { NSString *substring = [self substringWithRange:range]; return substring; }else{ NSError *curError = [NSError errorWithDomain:NSCocoaErrorDomain code:SkyStringSubstringWithRangeErrorCode userInfo:@{NSLocalizedDescriptionKey: @"Index out of bounds from substringWithRange"}]; if (error != NULL) { *error = curError; } return nil; } } - (NSString *_Nullable)substringToIndex:(NSInteger)index error:(NSError *_Nonnull*_Nullable)error { if (index <= [self length]) { NSString *substring = [self substringToIndex:index]; return substring; }else{ NSError *curError = [NSError errorWithDomain:NSCocoaErrorDomain code:SkyStringSubstringToIndexErrorCode userInfo:@{NSLocalizedDescriptionKey: @"Index out of bounds from substringToIndex"}]; if (error != NULL) { *error = curError; } return nil; } } - (NSString *_Nullable)substringFromIndex:(NSInteger)index error:(NSError *_Nonnull*_Nullable)error { if (index <= [self length]) { NSString *substring = [self substringFromIndex:index]; return substring; }else{ NSError *curError = [NSError errorWithDomain:NSCocoaErrorDomain code:SkyStringSubstringFromIndexErrorCode userInfo:@{NSLocalizedDescriptionKey: @"Index out of bounds from substringFromIndex"}]; if (error != NULL) { *error = curError; } return nil; } } @end // //使用: // // 原始字符串 NSString *str = @"Hello, World!"; // 尝试获取范围为 (50, 1) 的子字符串 NSRange range = NSMakeRange(1, 24); NSError *error = nil; NSString *substring = [str substringToIndex:100 error:&error]; if (error) { // 处理错误 NSLog(@"Error: %@ - %ld", error.localizedDescription,error.code); } else { // 成功获取子字符串 NSLog(@"Substring: %@", substring); }
十二,根据图片宽度,设置图片比例不变,宽高比根据屏幕宽度计算:
// // CGFloat width = self.bounds.size.width; CGFloat scale = width / self.detailImageView.image.size.width; CGFloat height = scale * self.detailImageView.image.size.height; self.detailImageView.frame = CGRectMake(0.0, 0.0, width, height); // //
十三,属性、返回值、参数等修饰的一些关键字作用:
1,Nullable,可以用于属性、方法返回值、方法参数中;
表示可以为空;
2,Nonnull,可以用于属性、方法返回值、方法参数中;
表示不为空;
3,null_resettable,可以用于属性、方法返回值、方法参数中;
set可以传入为空,get方法不能返回nil,必须要处理为空情况,重写get方法;
4,null_unspecified,可以用于属性、方法返回值、方法参数中;
不确定是否为空;
十四,代码内部判断swift的版本:
//#if swift(>=4.2) #else #endif // private var data: Data? { #if swift(>=4.2) return self.pngData() ?? self.jpegData(compressionQuality: Constant.jpegCompressionQuality) #else return self.pngData() ?? self.jpegData(compressionQuality: Constant.jpegCompressionQuality) #endif // swift(>=4.2) } //
十五,判断当前是否获取摄像头库权限:
// // UIImagePickerController.isSourceTypeAvailable(.camera) // //