一些开发中用到的方法

0x00 前言

本文是一些我在开发过程中用到的比较有用、能用且好用的方法等一些干货。
将这些写成一篇文章,以后用到也能比较快的找到。

0x01 iOS

0x0100 获取 APP 信息

  • 获取 App 的版本号:
1
2
3
+ (NSString *)appVersion {
return [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"];
}
  • 获取 App 的 Build 号:
1
2
3
+ (NSString *)appBuildNumber {
return [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString *)kCFBundleVersionKey];
}

0x0101 获取设备信息

  • 获取 deviceModel:
1
2
3
4
5
+ (NSString *)deviceModel {
struct utsname systemInfo;
uname(&systemInfo);
return [NSString stringWithCString:systemInfo.machine encoding:NSUTF8StringEncoding];
}
  • 获取 Nodename:
1
2
3
4
5
+ (NSString *)deviceNodename {
struct utsname systemInfo;
uname(&systemInfo);
return [NSString stringWithCString:systemInfo.nodename encoding:NSUTF8StringEncoding];
}
  • 获取手机型号:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
- (NSString *)modelName {
NSString *machine = [MLBUtilities deviceModel];

if ([machine isEqualToString:@"iPod5,1"]) {
return @"iPod Touch 5";
} else if ([machine isEqualToString:@"iPod7,1"]) {
return @"iPod Touch 6";
} else if ([machine isEqualToString:@"iPhone3,1"] || [machine isEqualToString:@"iPhone3,2"] || [machine isEqualToString:@"iPhone3,3"]) {
return @"iPhone 4";
} else if ([machine isEqualToString:@"iPhone4,1"]) {
return @"iPhone 4s";
} else if ([machine isEqualToString:@"iPhone5,1"] || [machine isEqualToString:@"iPhone5,2"]) {
return @"iPhone 5";
} else if ([machine isEqualToString:@"iPhone5,3"] || [machine isEqualToString:@"iPhone5,4"]) {
return @"iPhone 5c";
} else if ([machine isEqualToString:@"iPhone6,1"] || [machine isEqualToString:@"iPhone6,2"]) {
return @"iPhone 5s";
} else if ([machine isEqualToString:@"iPhone7,2"]) {
return @"iPhone 6";
} else if ([machine isEqualToString:@"iPhone7,1"]) {
return @"iPhone 6 Plus";
} else if ([machine isEqualToString:@"iPhone8,1"]) {
return @"iPhone 6s";
} else if ([machine isEqualToString:@"iPhone8,2"]) {
return @"iPhone 6s Plus";
} else if ([machine isEqualToString:@"iPhone8,4"]) {
return @"iPhone SE";
} else if ([machine isEqualToString:@"iPhone9,1"] || [machine isEqualToString:@"iPhone9,3"]) {
return @"iPhone 7";
} else if ([machine isEqualToString:@"iPhone9,2"] || [machine isEqualToString:@"iPhone9,4"]) {
return @"iPhone 7 Plus";
} else if ([machine isEqualToString:@"iPhone10,1"] || [machine isEqualToString:@"iPhone10,4"]) {
return @"iPhone 8";
} else if ([machine isEqualToString:@"iPhone10,2"] || [machine isEqualToString:@"iPhone10,5"]) {
return @"iPhone 8 Plus";
} else if ([machine isEqualToString:@"iPhone10,3"] || [machine isEqualToString:@"iPhone10,6"]) {
return @"iPhone X";
} else if ([machine isEqualToString:@"iPad2,1"] || [machine isEqualToString:@"iPad2,2"] || [machine isEqualToString:@"iPad2,3"] || [machine isEqualToString:@"iPad2,4"]) {
return @"iPad 2";
} else if ([machine isEqualToString:@"iPad3,1"] || [machine isEqualToString:@"iPad3,2"] || [machine isEqualToString:@"iPad3,3"]) {
return @"iPad 3";
} else if ([machine isEqualToString:@"iPad3,4"] || [machine isEqualToString:@"iPad3,5"] || [machine isEqualToString:@"iPad3,6"]) {
return @"iPad 4";
} else if ([machine isEqualToString:@"iPad4,1"] || [machine isEqualToString:@"iPad4,2"] || [machine isEqualToString:@"iPad4,3"]) {
return @"iPad Air";
} else if ([machine isEqualToString:@"iPad5,3"] || [machine isEqualToString:@"iPad5,4"]) {
return @"iPad Air 2";
} else if ([machine isEqualToString:@"iPad6,11"] || [machine isEqualToString:@"iPad6,12"]) {
return @"iPad 5";
} else if ([machine isEqualToString:@"iPad2,5"] || [machine isEqualToString:@"iPad2,6"] || [machine isEqualToString:@"iPad2,7"]) {
return @"iPad Mini";
} else if ([machine isEqualToString:@"iPad4,4"] || [machine isEqualToString:@"iPad4,5"] || [machine isEqualToString:@"iPad4,6"]) {
return @"iPad Mini 2";
} else if ([machine isEqualToString:@"iPad4,7"] || [machine isEqualToString:@"iPad4,8"] || [machine isEqualToString:@"iPad4,9"]) {
return @"iPad Mini 3";
} else if ([machine isEqualToString:@"iPad5,1"] || [machine isEqualToString:@"iPad5,2"]) {
return @"iPad Mini 4";
} else if ([machine isEqualToString:@"iPad6,3"] || [machine isEqualToString:@"iPad6,4"]) {
return @"iPad Pro 9.7 Inch";
} else if ([machine isEqualToString:@"iPad6,7"] || [machine isEqualToString:@"iPad6,8"]) {
return @"iPad Pro 12.9 Inch";
} else if ([machine isEqualToString:@"iPad7,1"] || [machine isEqualToString:@"iPad7,2"]) {
return @"iPad Pro 12.9 Inch 2. Generation";
} else if ([machine isEqualToString:@"iPad7,3"] || [machine isEqualToString:@"iPad7,4"]) {
return @"iPad Pro 10.5 Inch";
} else if ([machine isEqualToString:@"AppleTV5,3"]) {
return @"Apple TV";
} else if ([machine isEqualToString:@"i386"] || [machine isEqualToString:@"x86_64"]) {
return [NSString stringWithFormat:@"%@-Simulator", self.localizedModel];
} else {
return machine;
}
}

0x0102 地图相关

  • 打开系统地图:
1
2
3
4
5
6
7
8
9
10
11
12
+ (void)openMapWithlatitude:(double)latitude longitude:(double)longitude name:(NSString *)name {
CLLocationDistance regionDistance = 500;
CLLocationCoordinate2D coord = CLLocationCoordinate2DMake(latitude, longitude);
CLLocationCoordinate2D coordGCJ = [self transformFromWGSToGCJ:coord];
MKCoordinateRegion regionSpan = MKCoordinateRegionMakeWithDistance(coordGCJ, regionDistance, regionDistance);
NSDictionary *options = @{MKLaunchOptionsMapCenterKey : [NSValue valueWithMKCoordinate:regionSpan.center],
MKLaunchOptionsMapSpanKey : [NSValue valueWithMKCoordinateSpan:regionSpan.span]};
MKPlacemark *placemark = [[MKPlacemark alloc] initWithCoordinate:coordGCJ addressDictionary:nil];
MKMapItem *mapItem = [[MKMapItem alloc] initWithPlacemark:placemark];
mapItem.name = name;
[mapItem openInMapsWithLaunchOptions:options];
}
  • 各类坐标转换:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
const double pi = 3.14159265358979324;
const double x_pi = pi * 3000.0 / 180.0;
const double a = 6378245.0;
const double ee = 0.00669342162296594323;

+ (void)bdLat:(double)bd_lat Lon:(double)bd_lon toAMapLat:(double *)gg_lat aMaplng:(double *)gg_lon {
double x = bd_lon - 0.0065, y = bd_lat - 0.006;
double z = sqrt(x * x + y * y) - 0.00002 * sin(y * x_pi);
double theta = atan2(y, x) - 0.000003 * cos(x * x_pi);
*gg_lon = z * cos(theta);
*gg_lat = z * sin(theta);
}

/**
* 将 WGS 的经纬度(GPS)转成 GCJ 的经纬度(比如高德)
*
* @param wgsLoc wgs 经纬度
*
* @return GCJ 经纬度
*/
+ (CLLocationCoordinate2D)transformFromWGSToGCJ:(CLLocationCoordinate2D)wgsLoc {
CLLocationCoordinate2D adjustLoc;

if ([self isLocationOutOfChina:wgsLoc]){
adjustLoc = wgsLoc;
} else {
double adjustLat = [self transformLatWithX:wgsLoc.longitude - 105.0 withY:wgsLoc.latitude - 35.0];
double adjustLon = [self transformLonWithX:wgsLoc.longitude - 105.0 withY:wgsLoc.latitude - 35.0];
double radLat = wgsLoc.latitude / 180.0 * pi;
double magic = sin(radLat);
magic = 1 - ee * magic * magic;
double sqrtMagic = sqrt(magic);
adjustLat = (adjustLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);
adjustLon = (adjustLon * 180.0) / (a / sqrtMagic * cos(radLat) * pi);
adjustLoc.latitude = wgsLoc.latitude + adjustLat;
adjustLoc.longitude = wgsLoc.longitude + adjustLon;
}

return adjustLoc;
}

/**
* 判断经纬度是否在中国
*
* @param location 经纬度
*
* @return 是否在中国
*/
+ (BOOL)isLocationOutOfChina:(CLLocationCoordinate2D)location {
if (location.longitude < 72.004 || location.longitude > 137.8347 || location.latitude < 0.8293 || location.latitude > 55.8271)
return YES;
return NO;
}

+ (double)transformLatWithX:(double)x withY:(double)y {
double lat = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * sqrt(fabs(x));
lat += (20.0 * sin(6.0 * x * pi) + 20.0 *sin(2.0 * x * pi)) * 2.0 / 3.0;
lat += (20.0 * sin(y * pi) + 40.0 * sin(y / 3.0 * pi)) * 2.0 / 3.0;
lat += (160.0 * sin(y / 12.0 * pi) + 320 * sin(y * pi / 30.0)) * 2.0 / 3.0;

return lat;
}

+ (double)transformLonWithX:(double)x withY:(double)y {
double lon = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * sqrt(fabs(x));
lon += (20.0 * sin(6.0 * x * pi) + 20.0 * sin(2.0 * x * pi)) * 2.0 / 3.0;
lon += (20.0 * sin(x * pi) + 40.0 * sin(x / 3.0 * pi)) * 2.0 / 3.0;
lon += (150.0 * sin(x / 12.0 * pi) + 300.0 * sin(x / 30.0 * pi)) * 2.0 / 3.0;

return lon;
}

/**
* GJC 经纬度(比如高德)转成 WGS 经纬度(GPS)
*
* @param location GJC 经纬度
*
* @return WGS 经纬度
*/
+ (CLLocationCoordinate2D)transformFromGCJ02ToWGS84:(CLLocationCoordinate2D)location {
return [self gcj02Decrypt:location.latitude gjLon:location.longitude];
}

+ (CLLocationCoordinate2D)gcj02Decrypt:(double)gjLat gjLon:(double)gjLon {
CLLocationCoordinate2D gPt = [self gcj02Encrypt:gjLat bdLon:gjLon];
double dLon = gPt.longitude - gjLon;
double dLat = gPt.latitude - gjLat;
CLLocationCoordinate2D pt;
pt.latitude = gjLat - dLat;
pt.longitude = gjLon - dLon;
return pt;
}

+ (CLLocationCoordinate2D)gcj02Encrypt:(double)ggLat bdLon:(double)ggLon {
CLLocationCoordinate2D resPoint;
double mgLat;
double mgLon;
if ([self isLocationOutOfChina:CLLocationCoordinate2DMake(ggLat, ggLon)]) {
resPoint.latitude = ggLat;
resPoint.longitude = ggLon;
return resPoint;
}

double dLat = [self transformLatWithX:(ggLon - 105.0) withY:(ggLat - 35.0)];
double dLon = [self transformLonWithX:(ggLon - 105.0) withY:(ggLat - 35.0)];
double radLat = ggLat / 180.0 * M_PI;
double magic = sin(radLat);
magic = 1 - ee * magic * magic;
double sqrtMagic = sqrt(magic);
dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * M_PI);
dLon = (dLon * 180.0) / (a / sqrtMagic * cos(radLat) * M_PI);
mgLat = ggLat + dLat;
mgLon = ggLon + dLon;

resPoint.latitude = mgLat;
resPoint.longitude = mgLon;
return resPoint;
}

0x0103 字符串

  • 将对象转成字符串,可以防止 NSNull 对象:
1
2
3
4
5
6
7
8
9
10
11
12
13
+ (NSString *)stringWithObject:(id)object {
if ((NSNull *)object == [NSNull null]) {
return @"";
}

if ([object isKindOfClass:[NSString class]]) {
return object;
} else if (object) {
return [NSString stringWithFormat:@"%@", object];
} else {
return @"";
}
}
  • 随机字符串:
1
2
3
4
5
6
7
8
9
10
11
static NSString *const letters = @"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";

+ (NSString *)randomLettersWithCount:(NSUInteger)count {
NSMutableString *string = @"".mutableCopy;
for (int i = 0; i < count; i++) {
uint32_t random = arc4random_uniform(letters.length);
[string appendString:[letters substringWithRange:NSMakeRange(random, 1)]];
}

return [string copy];
}
  • 给文字添加行间距:
1
2
3
4
5
6
7
8
9
+ (NSAttributedString *)attributedStringWithText:(NSString *)text lineSpacing:(CGFloat)lineSpacing font:(UIFont *)font textColor:(UIColor *)textColor {
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.lineSpacing = lineSpacing;

NSDictionary *attrsDictionary = @{NSFontAttributeName : font, NSForegroundColorAttributeName : textColor, NSParagraphStyleAttributeName : paragraphStyle};
NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString:text attributes:attrsDictionary];

return attributedString;
}

0x0104 图片

公共方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
+ (UIImage *)createNonInterpolatedUIImageFromCIImage:(CIImage *)image withScale:(CGFloat)scale {
// Render the CIImage into a CGImage
CGImageRef cgImage = [[CIContext contextWithOptions:nil] createCGImage:image fromRect:image.extent];
// Now we'll rescale using CoreGraphics
UIGraphicsBeginImageContext(CGSizeMake(image.extent.size.width * scale, image.extent.size.width * scale));
CGContextRef context = UIGraphicsGetCurrentContext();
// We don't want to interpolate (since we've got a pixel-correct image)
CGContextSetInterpolationQuality(context, kCGInterpolationNone);
CGContextDrawImage(context, CGContextGetClipBoundingBox(context), cgImage);
// Get the image out
UIImage *scaledImage = UIGraphicsGetImageFromCurrentImageContext();
// Tidy up
UIGraphicsEndImageContext();
CGImageRelease(cgImage);

return scaledImage;
}
  • 生成二维码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
+ (UIImage *)generateQRCodeImageWithString:(NSString *)qrString scale:(CGFloat)scale color:(UIColor *)color backgroundColor:(UIColor *)backgroundColor {
CIFilter *qrFilter = [CIFilter filterWithName:@"CIQRCodeGenerator"];
if (!qrFilter) {
NSLog(@"Error: Could not load filter");
return nil;
}

NSData *stringData = [qrString dataUsingEncoding:NSUTF8StringEncoding]; // NSISOLatin1StringEncoding
[qrFilter setValue:stringData forKey:@"inputMessage"];

CIFilter *colorQRFilter = [CIFilter filterWithName:@"CIFalseColor"];
[colorQRFilter setValue:qrFilter.outputImage forKey:@"inputImage"];

// 二维码颜色
if (color == nil) {
color = [UIColor blackColor];
}

if (backgroundColor == nil) {
backgroundColor = [UIColor whiteColor];
}

[colorQRFilter setValue:[CIColor colorWithCGColor:color.CGColor] forKey:@"inputColor0"];
// 背景颜色
[colorQRFilter setValue:[CIColor colorWithCGColor:backgroundColor.CGColor] forKey:@"inputColor1"];

CIImage *ciImage = colorQRFilter.outputImage;

UIImage *qrCodeImage = [self createNonInterpolatedUIImageFromCIImage:ciImage withScale:scale * [UIScreen mainScreen].scale];

return qrCodeImage;
}
  • 生成条形码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
+ (UIImage *)generateBarcodeImageWithString:(NSString *)codeString scale:(CGFloat)scale color:(UIColor *)color backgroundColor:(UIColor *)backgroundColor {
CIFilter *filter = [CIFilter filterWithName:@"CICode128BarcodeGenerator"];
if (!filter) {
NSLog(@"Error: Could not load filter");
return nil;
}

NSData *data = [codeString dataUsingEncoding:NSISOLatin1StringEncoding allowLossyConversion:false];
[filter setValue:data forKey:@"inputMessage"];

CIFilter * colorFilter = [CIFilter filterWithName:@"CIFalseColor"];
[colorFilter setValue:filter.outputImage forKey:@"inputImage"];

// 条形码颜色
if (color == nil) {
color = [UIColor blackColor];
}

if (backgroundColor == nil) {
backgroundColor = [UIColor whiteColor];
}

[colorFilter setValue:[CIColor colorWithCGColor:color.CGColor] forKey:@"inputColor0"];
// 背景颜色
[colorFilter setValue:[CIColor colorWithCGColor:backgroundColor.CGColor] forKey:@"inputColor1"];

CIImage *ciImage = colorFilter.outputImage;

UIImage *barCodeImage = [self createNonInterpolatedUIImageFromCIImage:ciImage withScale:scale * [UIScreen mainScreen].scale];

return barCodeImage;
}
  • UIView 转 UIImage:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
+ (UIImage *)renderImageFromView:(UIView *)view withRect:(CGRect)frame transparentInsets:(UIEdgeInsets)insets {
CGSize imageSizeWithBorder = CGSizeMake(frame.size.width + insets.left + insets.right, frame.size.height + insets.top + insets.bottom);
// Create a new context of the desired size to render the image
UIGraphicsBeginImageContextWithOptions(imageSizeWithBorder, NO, 0);
CGContextRef context = UIGraphicsGetCurrentContext();

// Clip the context to the portion of the view we will draw
CGContextClipToRect(context, (CGRect){{insets.left, insets.top}, frame.size});
// Translate it, to the desired position
CGContextTranslateCTM(context, -frame.origin.x + insets.left, -frame.origin.y + insets.top);

// Render the view as image
[view.layer renderInContext:UIGraphicsGetCurrentContext()];

// Fetch the image
UIImage *renderedImage = UIGraphicsGetImageFromCurrentImageContext();

// Cleanup
UIGraphicsEndImageContext();

return renderedImage;
}
  • UIColor 转 UIImage:
1
2
3
4
5
6
7
8
9
10
11
12
13
+ (UIImage *)imageWithColor:(UIColor *)aColor {
return [UIImage imageWithColor:aColor withFrame:CGRectMake(0, 0, 1, 1)];
}

+ (UIImage *)imageWithColor:(UIColor *)aColor withFrame:(CGRect)aFrame {
UIGraphicsBeginImageContext(aFrame.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, [aColor CGColor]);
CGContextFillRect(context, aFrame);
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return img;
}

0x0105 其他

  • 按照给定的总数和每列的个数计算行数:
1
2
3
4
+ (NSInteger)rowsWithCount:(NSInteger)count colNumber:(NSInteger)colNumber {
NSInteger rows = ceilf(count / (CGFloat)colNumber);
return rows;
}
  • 将数字转成中文大写金额:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
static NSArray<NSString *> *chineseDigits;

+ (NSString *)stringFromMoney:(CGFloat)amount {
if (!chineseDigits) {
chineseDigits = @[@"零", @"壹", @"贰", @"叁", @"肆", @"伍", @"陆", @"柒", @"捌", @"玖"];
}

if (amount > 99999999999999.99 || amount < -99999999999999.99) {
NSAssert(YES, @"参数值超出允许范围 (-99999999999999.99 ~ 99999999999999.99)!");
}

bool negative = false;
if (amount < 0) {
negative = true;
amount = amount * (-1);
}

long temp = round(amount * 100);
int numFen = (int)(temp % 10); // 分
temp = temp / 10;
int numJiao = (int)(temp % 10); //角
temp = temp / 10;
// temp 目前是金额的整数部分

NSMutableArray *parts = [NSMutableArray arrayWithCapacity:20]; // 其中的元素是把原来金额整数部分分割为值在 0~9999 之间的数的各个部分
int numParts = 0; // 记录把原来金额整数部分分割为了几个部分(每部分都在 0~9999 之间)
for (int i = 0; ; i++) {
if (temp == 0) { break; }

int part = (int)(temp % 10000);
parts[i] = @(part);
numParts++;
temp = temp / 10000;
}

bool beforeWanIsZero = true; // 标志“万”下面一级是不是 0

NSString *chineseStr = @"";
for (int i = 0; i < numParts; i++) {
NSString *partChinese = [MLBUtilities partTranslate:[parts[i] intValue]];
if (i % 2 == 0) {
if (IsStringEmpty(partChinese)) {
beforeWanIsZero = true;
} else {
beforeWanIsZero = false;
}
}

if (i != 0) {
if (i % 2 == 0) {
chineseStr = [@"亿" stringByAppendingString:chineseStr];
} else {
if (IsStringEmpty(partChinese) && !beforeWanIsZero) { // 如果“万”对应的 part 为 0,而“万”下面一级不为 0,则不加“万”,而加“零”
chineseStr = [@"零" stringByAppendingString:chineseStr];
} else {
if ([parts[i-1] intValue] < 1000 && [parts[i-1] intValue] > 0) { // 如果"万"的部分不为 0, 而"万"前面的部分小于 1000 大于 0, 则万后面应该跟“零”
chineseStr = [@"零" stringByAppendingString:chineseStr];
}

chineseStr = [@"万" stringByAppendingString:chineseStr];
}
}
}

chineseStr = [partChinese stringByAppendingString:chineseStr];
}

if (IsStringEmpty(chineseStr)) { // 整数部分为 0, 则表达为"零元"
chineseStr = chineseDigits[0];
} else if (negative) { // 整数部分不为 0, 并且原金额为负数
chineseStr = [@"负" stringByAppendingString:chineseStr];
}

chineseStr = [chineseStr stringByAppendingString:@"元"];

if (numFen == 0 && numJiao == 0) {
chineseStr = [chineseStr stringByAppendingString:@"整"];
} else if (numFen == 0) { // 0 分,角数不为 0
chineseStr = [NSString stringWithFormat:@"%@%@%@", chineseStr, chineseDigits[numJiao], @"角"];
} else { // “分”数不为 0
if (numJiao == 0) {
chineseStr = [NSString stringWithFormat:@"%@%@%@%@", chineseStr, @"零", chineseDigits[numFen], @"分"];
} else {
chineseStr = [NSString stringWithFormat:@"%@%@%@%@%@", chineseStr, chineseDigits[numJiao], @"角", chineseDigits[numFen], @"分"];
}
}

return chineseStr;
}

+ (NSString *)partTranslate:(int)amountPart {
if (amountPart < 0 || amountPart > 10000) {
NSAssert(YES, @"参数必须是大于等于 0,小于 10000 的整数!");
}

NSArray *units = @[@"", @"拾", @"佰", @"仟"];

int temp = amountPart;

NSString *amountStr = [@(amountPart) stringValue];
int amountStrLength = (int)amountStr.length;
bool lastIsZero = true; //在从低位往高位循环时,记录上一位数字是不是 0
NSString *chineseStr = @"";

for (int i = 0; i < amountStrLength; i++) {
if (temp == 0) { break; } // 高位已无数据

int digit = temp % 10;
if (digit == 0) { // 取到的数字为 0
if (!lastIsZero) { //前一个数字不是 0,则在当前汉字串前加“零”字;
chineseStr = [@"零" stringByAppendingString:chineseStr];
}

lastIsZero = true;
} else { // 取到的数字不是 0
chineseStr = [NSString stringWithFormat:@"%@%@%@", chineseDigits[digit], units[i], chineseStr];
lastIsZero = false;
}

temp = temp / 10;
}

return chineseStr;
}

0x02 其他

  • 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换

算法代码如下,其中 bd_encrypt 将 GCJ-02 坐标转换成 BD-09 坐标,bd_decrypt 反之。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <math.h>

const double x_pi = 3.14159265358979324 * 3000.0 / 180.0;

void bd_encrypt(double gg_lat, double gg_lon, double &bd_lat, double &bd_lon)
{
double x = gg_lon, y = gg_lat;
double z = sqrt(x * x + y * y) + 0.00002 * sin(y * x_pi);
double theta = atan2(y, x) + 0.000003 * cos(x * x_pi);
bd_lon = z * cos(theta) + 0.0065;
bd_lat = z * sin(theta) + 0.006;
}

void bd_decrypt(double bd_lat, double bd_lon, double &gg_lat, double &gg_lon)
{
double x = bd_lon - 0.0065, y = bd_lat - 0.006;
double z = sqrt(x * x + y * y) - 0.00002 * sin(y * x_pi);
double theta = atan2(y, x) - 0.000003 * cos(x * x_pi);
gg_lon = z * cos(theta);
gg_lat = z * sin(theta);
}

原博客地址
这篇博文是通过 SegmentFault 上的 这篇文章 找到的。

  • 日期转换格式
    iOS NSDateFormatter 格式说明:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    G: 公元时代,例如AD公元
    yy: 年的后2位
    yyyy: 完整年
    MM: 月,显示为1-12
    MMM: 月,显示为英文月份简写,如 Jan
    MMMM: 月,显示为英文月份全称,如 Janualy
    dd: 日,2位数表示,如02
    d: 日,1-2位显示,如 2
    EEE: 简写星期几,如Sun
    EEEE: 全写星期几,如Sunday
    aa: 上下午,AM/PM
    H: 时,24小时制,0-23
    K:时,12小时制,0-11
    m: 分,1-2位
    mm: 分,2位
    s: 秒,1-2位
    ss: 秒,2位
    S: 毫秒
    Z:GMT

常用的时间格式有:

1
2
3
4
yyyy-MM-dd HH:mm:ss.SSS
yyyy-MM-dd HH:mm:ss
yyyy-MM-dd
MM dd yyyy

原博客地址