一,上传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) // //

