ForgetSou | Blog

❤ 武统台湾 刻不容缓 ❤

0%

日常开发小知识点收集

1.删除ToolBar下面的分割线

toolbar.showsBaselineSeparator = NO;

2.修改TextField的蓝色或橙色边框

self.textField.focusRingType = NSFocusRingTypeNone;

3.打开已安装的其他软件

// 1
NSString *appPath = @"/Applications/Foxmail.app";
[[NSWorkspace sharedWorkspace] openFile:appPath];
// 2
[[NSWorkspace sharedWorkspace] launchApplication:@"Foxmail"];

4.打开网页

[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"https://www.baidu.com"]];

5.Color生成纯色图片(iOS)

// 生成纯色图片

+ (UIImage *)pureColorImageWithColor:(UIColor *)color {
CGSize imageSize = CGSizeMake(1.0f, 1.0f);
UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0.0f);

CGContextRef theContext = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(theContext, color.CGColor);
CGContextFillRect(theContext, CGRectMake(0.0f, 0.0f, imageSize.width, imageSize.height));

CGImageRef theCGImage = CGBitmapContextCreateImage(theContext);
UIImage *theImage;
if ([[UIImage class] respondsToSelector:@selector(imageWithCGImage:scale:orientation:)]) {
theImage = [UIImage imageWithCGImage:theCGImage scale:[UIScreen mainScreen].scale orientation:UIImageOrientationUp];
} else {
theImage = [UIImage imageWithCGImage:theCGImage];
}
CGImageRelease(theCGImage);

return theImage;
}
// 生成纯色圆角图片

+ (UIImage *)pureColorImageWithSize:(CGSize)size
color:(UIColor *)color
cornRadius:(CGFloat)radius {
UIGraphicsBeginImageContextWithOptions(size, NO, 0);
CGContextRef cxt = UIGraphicsGetCurrentContext();

CGContextSetFillColorWithColor(cxt, color.CGColor);
CGContextSetStrokeColorWithColor(cxt, color.CGColor);

CGContextMoveToPoint(cxt, size.width, size.height-radius);
CGContextAddArcToPoint(cxt, size.width, size.height, size.width-radius, size.height, radius);//右下角
CGContextAddArcToPoint(cxt, 0, size.height, 0, size.height-radius, radius);//左下角
CGContextAddArcToPoint(cxt, 0, 0, radius, 0, radius);//左上角
CGContextAddArcToPoint(cxt, size.width, 0, size.width, radius, radius);//右上角
CGContextClosePath(cxt);
CGContextDrawPath(cxt, kCGPathFillStroke);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}

6.时间格式转换

/// 根据格式生成时间字符串
/// @param date 时间NSDate
/// @param formatStr 时间格式 eg:"YYYY-MM-dd HH:mm:ss"

+ (NSString *)stringFromDate:(NSDate *)date formatStr:(NSString *)formatStr {
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:formatStr];
return [formatter stringFromDate:date];
}
/// 根据格式生成NSDate
/// @param dateString 时间
/// @param formatStr 时间格式 eg:"YYYY-MM-dd HH:mm:ss"
+ (NSDate *)dateFromString:(NSString *)dateString formatStr:(NSString *)formatStr {
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:formatStr];
return [formatter dateFromString:dateString];
}
/// 获取当前时间戳(秒)
+ (NSNumber *)getCurrentTimeStampSec {
NSDate *date = [NSDate dateWithTimeIntervalSinceNow:0];
NSTimeInterval timeInterval = [date timeIntervalSince1970];
NSNumber *u = [NSNumber numberWithInteger:timeInterval];
return u;
}
/// 获取当前时间戳(毫秒)
+ (NSNumber *)getCurrentTimeStampMilliSec {
NSDate *date = [NSDate dateWithTimeIntervalSinceNow:0];
long long timeInterval = [date timeIntervalSince1970] * 1000;
NSNumber *u = [NSNumber numberWithLongLong:timeInterval];
return u;
}

7.合法性

  • 手机号是否合法
+ (BOOL)isValidMobile:(NSString *)mobile {
BOOL isValid = false;
if (!kStringIsEmpty(mobile) && mobile.length == 11) {
NSString *CM_NUM = @"^((13[0-9])|(14[5-9])|(15([0-3]|[5-9]))|(16[6-7])|(17[1-8])|(18[0-9])|(19[1|3])|(19[5|6])|(19[8|9]))\\d{8}$";
NSPredicate *pred = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", CM_NUM];
BOOL isMatch = [pred evaluateWithObject:mobile];
if (isMatch) {
isValid = true;
}
}
return isValid;
}
  • Url是否合法
+ (BOOL)isValidUrl:(NSString *)urlStr {
NSString *regex =@"[a-zA-z]+://[^\\s]*";
NSPredicate *urlTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",regex];
return [urlTest evaluateWithObject:urlStr];
}
  • 银行卡是否合法
+ (BOOL)isValidCardNo:(NSString *)cardNumber {
int oddSum = 0; // 奇数和
int evenSum = 0; // 偶数和
int allSum =0; // 总和
// 循环加和
for(NSInteger i = 1; i <= cardNumber.length; i++) {
NSString *theNumber = [cardNumber substringWithRange:NSMakeRange(cardNumber.length-i,1)];
int lastNumber = [theNumber intValue];
if(i%2==0) {
// 偶数位
lastNumber *=2;
if(lastNumber >9) {
lastNumber -=9;
}
evenSum += lastNumber;
} else {
// 奇数位
oddSum += lastNumber;
}
}
allSum = oddSum + evenSum;
// 是否合法
if(allSum%10 == 0) {
return YES;
} else {
return NO;
}
}
  • 判断邮箱是否合法
    + (BOOL)isValidEmail:(NSString *)email {
    if ([CCUtility checkEmptyString:email]) return NO;

    NSString *emailRegex = @"^(([a-zA-Z0-9_-]+)|([a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)))@[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)+$";
    NSPredicate *emailTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", emailRegex];
    return [emailTest evaluateWithObject:email];
    }

    + (BOOL)isValidUrl:(NSString *)urlStr {
    NSString *regex =@"[a-zA-z]+://[^\\s]*";
    NSPredicate *urlTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",regex];
    return [urlTest evaluateWithObject:urlStr];
    }
  • 判断身份证(中国大陆)身份证是否合法
+ (BOOL)isValidIDCardNo:(NSString *)value {
value = [value stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSInteger length =0;
if (!value) {
return NO;
} else {
length = value.length;
//不满足15位和18位,即身份证错误
if (length !=15 && length !=18) {
return NO;
}
}
// 省份代码
NSArray *areasArray = @[@"11",@"12", @"13",@"14", @"15",@"21", @"22",@"23", @"31",@"32", @"33",@"34", @"35",@"36", @"37",@"41", @"42",@"43", @"44",@"45", @"46",@"50", @"51",@"52", @"53",@"54", @"61",@"62", @"63",@"64", @"65",@"71", @"81",@"82", @"91"];
// 检测省份身份行政区代码
NSString *valueStart2 = [value substringToIndex:2];
BOOL areaFlag =NO; //标识省份代码是否正确
for (NSString *areaCode in areasArray) {
if ([areaCode isEqualToString:valueStart2]) {
areaFlag =YES;
break;
}
}
if (!areaFlag) {
return NO;
}

NSRegularExpression *regularExpression;
NSUInteger numberofMatch;

int year =0;
//分为15位、18位身份证进行校验
switch (length) {
case 15:
//获取年份对应的数字
year = [value substringWithRange:NSMakeRange(6,2)].intValue +1900;
if (year %4 ==0 || (year %100 ==0 && year %4 ==0)) {
//创建正则表达式 NSRegularExpressionCaseInsensitive:不区分字母大小写的模式
regularExpression = [[NSRegularExpression alloc]initWithPattern:@"^[1-9][0-9]{5}[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|[1-2][0-9]))[0-9]{3}$" options:NSRegularExpressionCaseInsensitive error:nil];//测试出生日期的合法性
} else {
regularExpression = [[NSRegularExpression alloc]initWithPattern:@"^[1-9][0-9]{5}[0-9]{2}((01|03|05|07|08|10|12)(0[1-9]|[1-2][0-9]|3[0-1])|(04|06|09|11)(0[1-9]|[1-2][0-9]|30)|02(0[1-9]|1[0-9]|2[0-8]))[0-9]{3}$" options:NSRegularExpressionCaseInsensitive error:nil];//测试出生日期的合法性
}
//使用正则表达式匹配字符串 NSMatchingReportProgress:找到最长的匹配字符串后调用block回调
numberofMatch = [regularExpression numberOfMatchesInString:value options:NSMatchingReportProgress range:NSMakeRange(0, value.length)];
if(numberofMatch > 0) {
return YES;
} else {
return NO;
}
case 18:
year = [value substringWithRange:NSMakeRange(6,4)].intValue;
if (year %4 ==0 || (year %100 ==0 && year %4 ==0)) {
regularExpression = [[NSRegularExpression alloc]initWithPattern:@"^((1[1-5])|(2[1-3])|(3[1-7])|(4[1-6])|(5[0-4])|(6[1-5])|71|(8[12])|91)\\d{4}(((19|20)\\d{2}(0[13-9]|1[012])(0[1-9]|[12]\\d|30))|((19|20)\\d{2}(0[13578]|1[02])31)|((19|20)\\d{2}02(0[1-9]|1\\d|2[0-8]))|((19|20)([13579][26]|[2468][048]|0[048])0229))\\d{3}(\\d|X|x)?$" options:NSRegularExpressionCaseInsensitive error:nil];//测试出生日期的合法性
} else {
regularExpression = [[NSRegularExpression alloc]initWithPattern:@"^((1[1-5])|(2[1-3])|(3[1-7])|(4[1-6])|(5[0-4])|(6[1-5])|71|(8[12])|91)\\d{4}(((19|20)\\d{2}(0[13-9]|1[012])(0[1-9]|[12]\\d|30))|((19|20)\\d{2}(0[13578]|1[02])31)|((19|20)\\d{2}02(0[1-9]|1\\d|2[0-8]))|((19|20)([13579][26]|[2468][048]|0[048])0229))\\d{3}(\\d|X|x)?$" options:NSRegularExpressionCaseInsensitive error:nil];//测试出生日期的合法性
}
numberofMatch = [regularExpression numberOfMatchesInString:value options:NSMatchingReportProgress range:NSMakeRange(0, value.length)];
if(numberofMatch > 0) {
//1:校验码的计算方法 身份证号码17位数分别乘以不同的系数。从第一位到第十七位的系数分别为:7-9-10-5-8-4-2-1-6-3-7-9-10-5-8-4-2。将这17位数字和系数相乘的结果相加。
int S = [value substringWithRange:NSMakeRange(0,1)].intValue*7 + [value substringWithRange:NSMakeRange(10,1)].intValue *7 + [value substringWithRange:NSMakeRange(1,1)].intValue*9 + [value substringWithRange:NSMakeRange(11,1)].intValue *9 + [value substringWithRange:NSMakeRange(2,1)].intValue*10 + [value substringWithRange:NSMakeRange(12,1)].intValue *10 + [value substringWithRange:NSMakeRange(3,1)].intValue*5 + [value substringWithRange:NSMakeRange(13,1)].intValue *5 + [value substringWithRange:NSMakeRange(4,1)].intValue*8 + [value substringWithRange:NSMakeRange(14,1)].intValue *8 + [value substringWithRange:NSMakeRange(5,1)].intValue*4 + [value substringWithRange:NSMakeRange(15,1)].intValue *4 + [value substringWithRange:NSMakeRange(6,1)].intValue*2 + [value substringWithRange:NSMakeRange(16,1)].intValue *2 + [value substringWithRange:NSMakeRange(7,1)].intValue *1 + [value substringWithRange:NSMakeRange(8,1)].intValue *6 + [value substringWithRange:NSMakeRange(9,1)].intValue *3;
//2:用加出来和除以11,看余数是多少?余数只可能有0-1-2-3-4-5-6-7-8-9-10这11个数字
int Y = S %11;
NSString *M =@"F";
NSString *JYM =@"10X98765432";
M = [JYM substringWithRange:NSMakeRange(Y,1)];// 3:获取校验位
NSString *lastStr = [value substringWithRange:NSMakeRange(17,1)];
//4:检测ID的校验位
if ([lastStr isEqualToString:@"x"]) {
if ([M isEqualToString:@"X"]) {
return YES;
} else {
return NO;
}
} else {
if ([M isEqualToString:[value substringWithRange:NSMakeRange(17,1)]]) {
return YES;
} else {
return NO;
}
}

} else {
return NO;
}
default:
return NO;
}
}

8.强弱引用

// 推荐使用(摘自YYKit)
/**
Synthsize a weak or strong reference.

Example:
@weakify(self)
[self doSomething^{
@strongify(self)
if (!self) return;
...
}];

*/
#ifndef weakify
#if DEBUG
#if __has_feature(objc_arc)
#define weakify(object) autoreleasepool{} __weak __typeof__(object) weak##_##object = object;
#else
#define weakify(object) autoreleasepool{} __block __typeof__(object) block##_##object = object;
#endif
#else
#if __has_feature(objc_arc)
#define weakify(object) try{} @finally{} {} __weak __typeof__(object) weak##_##object = object;
#else
#define weakify(object) try{} @finally{} {} __block __typeof__(object) block##_##object = object;
#endif
#endif
#endif

#ifndef strongify
#if DEBUG
#if __has_feature(objc_arc)
#define strongify(object) autoreleasepool{} __typeof__(object) object = weak##_##object;
#else
#define strongify(object) autoreleasepool{} __typeof__(object) object = block##_##object;
#endif
#else
#if __has_feature(objc_arc)
#define strongify(object) try{} @finally{} __typeof__(object) object = weak##_##object;
#else
#define strongify(object) try{} @finally{} __typeof__(object) object = block##_##object;
#endif
#endif
#endif

9.NSLog的宏定义

#ifdef DEBUG
#define NSLog(format,...) printf("\n[%s] %s [第%d行] %s\n",__TIME__,__FUNCTION__,__LINE__,[[NSString stringWithFormat:format,## __VA_ARGS__] UTF8String]);
#else
#define NSLog(format, ...)
#endif

10.判断是否为空

#define kStringIsEmpty(string)              (string == NULL || [string isKindOfClass:[NSNull class]] || string == nil || [string length] < 1)
#define kArrayIsEmpty(array) (array == nil || [array isKindOfClass:[NSNull class]] || array.count == 0)
#define kDictionaryIsEmpty(dictionary) (dictionary == nil || [dictionary isKindOfClass:[NSNull class]] || dictionary.allKeys.count == 0)
#define kObjectIsEmpty(object) (object == nil||[object isKindOfClass:[NSNull class]]||([object respondsToSelector:@selector(length)] && [(NSData *)object length] == 0)|| ([object respondsToSelector:@selector(count)] && [(NSArray *)object count] == 0))

11.使用xib创建自定义View并在背景添加点击事件

说明:
xib创建的自定义视图,添加的背景点击动作不会触发点击事件,因此需要单独添加一个xibView,添加到自定义视图上,点击动作添加到xibView上就可以触发点击事件了,具体步骤如下:

  • 创建自定义FSCommonView、创建FSCommonView.xib、关联到自定义的FSCommonView
    关联自定义视图
  • 将xib添加到FSCommonView
    #import <UIKit/UIKit.h>
    @interface FSCommonView : UIView

    @end

    #import "FSCommonView.h"

    @interface FSCommonView ()

    @property (strong, nonatomic) UIView *xibView;

    @end

    @implementation

    - (instancetype)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
    self.xibView = [self loadViewFromNib];
    [self settingUI];
    }
    return self;
    }

    - (instancetype)initWithCoder:(NSCoder *)coder {
    self = [super initWithCoder:coder];
    if (self) {
    self.xibView = [self loadViewFromNib];
    [self settingUI];
    }
    return self;
    }

    - (UIView *)loadViewFromNib {
    UIView *xibView = [[NSBundle mainBundle] loadNibNamed:NSStringFromClass([self class]) owner:self options:nil].firstObject;
    xibView.frame = self.bounds;
    [xibView addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(xibBgViewClick)]];
    [self addSubview:xibView];
    return xibView;
    }

    - (void)settingUI {
    // 设置背景色、圆角、边框、自定义子视图等。

    }

    - (void)xibBgViewClick {
    // 背景点击事件

    }
    @end

    12.啄幕鸟

啄幕鸟,阿里开源项目,即手机屏幕上的啄木鸟,专抓App里的Bug。啄幕鸟集合了UI检查、对象查看、方法监听等多种开发工具,通过拾取UI控件、查看对象属性、监听方法调用、App内抓包等,不依赖电脑联调,直接获取运行时数据,快速定位Bug,提高开发效率。

功能简介

  1. UI检查:快速查看页面布局、UI控件间距、字体颜色、UI控件类名、对象属性/成员变量、图片URL等。
  2. JSON抓包:便捷JSON抓包工具,通过监听系统json解析抓包。
  3. 方法监听:Bug听诊器,可监听App中任意OC方法的调用,输出调用参数、返回值等信息,可以通过屏幕日志输入监听、KVC取值等命令,支持后台配置命令。
  4. po命令:执行类似LLDB的po命令,在App运行时执行po命令,调用任意方法。
  5. 系统信息:查看各种系统名称、版本、屏幕、UA等信息,支持外部添加信息。
  6. SandBox:查看沙盒文件,导出文件等。
  7. Bundle:查看、导出Bundle目录中的内容。
  8. Crash:查看Crash日志,需先打开一次Crash插件以开启Crash监控。
  9. Defaults:查看、新增、删除User Defaults。
  10. 清除数据:清除所有沙盒数据、User Default。
  11. 触点显示:显示手指触控。
  12. UI对比:支持将设计图导入到App中进行对比,并可画线、标注需修改的地方,方便UI走查。
  13. 查看图片资源:查看、导出App中的资源图片。
  14. CPU:查看CPU占用。
  15. 内存:查看内存占用。
  16. FPS:查看App帧率。
  17. 网络流量:查看发送、接收网络流量。
pod 'YKWoodpecker'

官方github地址:YKWoodpecker

啄幕鸟

使用

// 显示啄幕鸟,启动默认打开UI检查插件
[[YKWoodpeckerManager sharedInstance] show];

13.ViewController的生命周期、执行顺序

1. initWithCoder:通过nib文件初始化时触发。
2. awakeFromNib:nib文件被加载的时候,会发生一个awakeFromNib的消息到nib文件中的每个对象。
3. loadView:开始加载视图控制器自带的view。
4. viewDidLoad:视图控制器的view被加载完成。
5. viewWillAppear:视图控制器的view将要显示在window上。
6. updateViewConstraints:视图控制器的view开始更新AutoLayout约束。
7. viewWillLayoutSubviews:视图控制器的view将要更新内容视图的位置。
8. viewDidLayoutSubviews:视图控制器的view已经更新视图的位置。
9. viewDidAppear:视图控制器的view已经展示到window上。
10. viewWillDisappear:视图控制器的view将要从window上消失。
11. viewDidDisappear:视图控制器的view已经从window上消失。

14. 去除Cocopods第三方库部分警告和MobileCoreServices.framework过期的问题

Podfile的末尾处添加如下代码,再 pod install

post_install do |pi|
# 去除Pods版本警告
pi.pods_project.targets.each do |t|
t.build_configurations.each do |config|
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '9.0'
end
end
# 替换Pods引用的不再使用的静态库MobileCoreServices.framework
framework = pi.pods_project.frameworks_group["iOS"]["MobileCoreServices.framework"]
framework.referrers.each do |ref|
if ref.isa == "PBXBuildFile"
ref.remove_from_project
end
end
framework.remove_from_project
end

15. 解决NSTimer循环引用的问题

解决方法如下:

  1. 方式一

    • timer改为弱引用
    @property (weak, nonatomic) NSTimer *timer;
    • 在适当的时机销毁timer
    - (void) viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];

    if (self.timer) {
    [self.timer invalidate];
    self.timer = nil;
    }
    }

    如果控制器push到下个控制器,viewDidDisappear执行后,timer被销毁,下次进入APP的时候还要重新创建

    • viewWillAppear开启定时器
    -(void)viewWillAppear:(BOOL)animated{
    [super viewWillAppear:animated];
    if (!self.timer) {
    self.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(showMsg) userInfo:nil repeats:YES];
    }
    }
  2. 方式二

    self添加proxy

  1. 方式三

16. lldb(gdb)常用的控制台调试命令?

  1. p 输出基本类型。是打印命令,需要指定类型。是print的简写
    p (int)[[[self view] subviews] count]
  2. po 打印对象,会调用对象description方法。是print-object的简写
    po [self view]
  3. expr 可以在调试时动态执行指定表达式,并将结果打印出来。常用于在调试过程中修改变量的值。
  4. bt:打印调用堆栈,是thread backtrace的简写,加all可打印所有thread的堆栈
  5. br l:是breakpoint list的简写

17. iOS的沙盒目录结构

1). Application:存放程序源文件,上架前经过数字签名,上架后不可修改。
2). Documents:常用目录,iCloud备份目录,存放数据。(这里不能存缓存文件,否则上架不被通过)
3). Library:
Caches:存放体积大又不需要备份的数据。(常用的缓存路径)
Preference:设置目录,iCloud会备份设置信息。
4). tmp:存放临时文件,不会被备份,而且这个文件下的数据有可能随时被清除的可能。

18. 安装包优化

1.1 安装包的构成

包含资源和可执行文件 Mach-o 两部分,其中资源包括 Assets.car 文件和其他资源

1.1.1 Mach-o

Mach-o是iOS上的可执行文件,是由代码源文件经过编译和静态链接获取的。经过App Slicing之后的Mach-o文件往往只包含单个架构。

1.1.2 Assets.car

Assets.car 是Asset catalog 的构建产物。Xcode中的actool负责构建Assets.car 。在构建Assets.car的过程中actool会按照一定的策略编码算法,对png图片进行编码。

1.2 资源大小优化

1.2.1 使用合适的资源压缩配置

1.2.2 使用 RGB with palette 压缩图片

19. UITableView键盘隐藏的问题

@property (nonatomic, strong) UITableView *tableView;
- (UITableView *)tableView {
if (!_tableView) {
_tableView = [[UITableView alloc] init];
// 控制键盘隐藏
UITableViewController *tvc = [[UITableViewController alloc] initWithStyle:UITableViewStyleGrouped];
[self addChildViewController:tvc];
_tableView = tvc.tableView;

_tableView.delegate = self;
_tableView.dataSource = self;
// 隐藏键盘
_tableView.separatorStyle = 0;
}
return _tableView;
}

20. 数组去重

  • NSOrderedSet去重

    - (NSArray *)removeDuplicateArr:(NSArray *)arr {
    NSOrderedSet *orderSet = [NSOrderedSet orderedSetWithArray:arr];
    return orderSet.array;
    }
  • ValueForKeyPath去重

    - (NSArray *)removeDuplicateArr:(NSArray *)arr {
    arr = [arr valueForKeyPath:@"@distinctUnionOfObjects.self"];
    return arr;
    }
  • 其他

    - (NSArray *)removeDuplicateArr3:(NSArray *)arr {
    NSMutableArray *mArr = [NSMutableArray arrayWithCapacity:arr.count];
    for (NSString *str in arr) {
    if (![mArr containsObject:str]) {
    [mArr addObject:str];
    }
    }
    return mArr;
    }

    - (NSArray *)removeDuplicateArr4:(NSArray *)arr {
    NSMutableDictionary *mDict = [NSMutableDictionary dictionaryWithCapacity:0];
    for (NSString *str in arr) {
    [mDict setObject:str forKey:str];
    }
    return mDict.allKeys;
    }

    - (NSArray *)removeDuplicateArr5:(NSArray *)arr {
    NSMutableArray *mArr = [NSMutableArray arrayWithArray:arr];
    for (NSString *str in arr) {
    if ([mArr containsObject:str]) {
    [mArr removeObject:str];
    }
    }
    return mArr;
    }

    21. iOS 判断平面上一个点是否在不规则的封闭区域内

    1. 在二维空间创建不规则封闭区域

    1.1 路径绘图

    CGMutablePathRef pathRef = CGPathCreateMutable();

    1.2 路径连线

    CGPathMoveToPoint(pathRef, NULL, 83.277656, -169.938307);

    CGPathAddLineToPoint(pathRef, NULL, 21.083895, -169.938307);

    CGPathAddLineToPoint(pathRef, NULL, 21.083895, -36.617291);

    CGPathAddLineToPoint(pathRef, NULL, 83.877837, -35.508388);

    CGPathAddLineToPoint(pathRef, NULL, 83.277656, -169.938307);

    1.3 关闭绘图

    CGPathCloseSubpath(pathRef);

    2. 判断任意点是否在此区域内

    CGPoint point= CGPointMake(aircraftLocation.latitude, aircraftLocation.longitude);

    BOOL containsPoint = (CGPathContainsPoint(pathRef, NULL, point, NO));

个人博客: 🏡 ForgetSou


-------------本文结束感谢您的阅读-------------
坚持原创技术分享,您的支持将鼓励我继续创作!

欢迎关注我的其它发布渠道