iOS 数据精度及大数的处理

在 iOS 开发中,我们很容易遇到使用 CGFloat 来标示浮点数,但这样的表示会造成精度失真。这时我们可以使用NSDecimalNumber来处理这个问题。

NSDecimalNumberNSNumber的子类,可以处理大数运算及数据的精度问题。

大数相乘可能导致的问题

我们先上一段代码:

NSString *priceStr = @"";
NSDecimalNumber *number = [NSDecimalNumber decimalNumberWithString:priceStr];
NSDecimalNumber *countNum = [NSDecimalNumber decimalNumberWithString:stringWithNSInteger(NSIntegerMax)];
number = [number decimalNumberByMultiplyingBy:countNum];

在这段代码中,number的值为:NaN,即:not a number ,非数值;
而countNum 是一个最大的整数,
最后,将NaN和最大的整数相乘,导致了overflow的crash。

解决方案:

//定义数值处理的行为
NSDecimalNumberHandler *roundUp = [NSDecimalNumberHandler
                                      decimalNumberHandlerWithRoundingMode:NSRoundBankers
                                      scale:2
                                      raiseOnExactness:NO
                                      raiseOnOverflow:NO
                                      raiseOnUnderflow:NO
                                      raiseOnDivideByZero:NO];
    
NSString *priceStr = @"";
NSDecimalNumber *number = [NSDecimalNumber decimalNumberWithString:priceStr];
NSDecimalNumber *countNum = [NSDecimalNumber decimalNumberWithString:stringWithNSInteger(NSIntegerMax)];

//使用数据处理行为的约定来进行运算,防止crash
number = [number decimalNumberByMultiplyingBy:countNum withBehavior:roundUp];

上面这个例子不会crash了,但是最终number的值为NaN,需要后续的业务逻辑进行判断处理;

NSDecimalNumberHandler 用到的参数,其中:

NSRoundBankers

枚举,截断的方式;完整的定义如下:

// Rounding policies :
// Original
//    value 1.2  1.21  1.25  1.35  1.27
// Plain    1.2  1.2   1.3   1.4   1.3
// Down     1.2  1.2   1.2   1.3   1.2
// Up       1.2  1.3   1.3   1.4   1.3
// Bankers  1.2  1.2   1.2   1.4   1.3

typedef NS_ENUM(NSUInteger, NSRoundingMode) {
    NSRoundPlain,   // Round up on a tie
    NSRoundDown,    // Always down == truncate
    NSRoundUp,      // Always up
    NSRoundBankers  // on a tie round so last digit is even
};

scale

小数点后面的位数(精度)

raiseOnExactness

The exception raised if there is an exactness error.

raiseOnOverflow

是否抛出溢出错误,如果为YES,则APP会捕获溢出错误,这会导致APPcrash;

The exception raised on overflow.

raiseOnUnderflow

The exception raised on underflow.

raiseOnDivideByZero

The exception raised on divide by zero.

补充知识:

  • 判断一个数值是否为NaN可以使用系统方法:isnan(x);注:x为数值类型,不是NSDecimalNumber,更不是NSNumber;
  • 如果要判断一个NSDecimalNumber 是否为 NAN ,则使用下面的方法:
if([number isEqualToNumber:NSDecimalNumber.notANumber]){
    NSLog(@"number is nan");
}else{
    NSLog(@"number:%@",number);
}

参考链接:iOS 两个数相乘导致 NSDecimalNumber overflow exception 错误的分析及解决

RuntimeError - [Xcodeproj] Unknown object version.

今天遇到 CocoaPods 不能使用了,提示:RuntimeError - [Xcodeproj] Unknown object version.

经过百度+谷歌之后还是不能解决,然后就想着重装吧,重装一般能解决大部分问题的。使用命令如下:

sudo gem uninstall cocoapods -n /usr/local/bin
sudo gem install cocoapods -n /usr/local/bin

Done !

总结:如果遇到问题很久都没有头绪,可以尝试从 0 开始。

XXX.APP 已损坏,打不开.你应该将它移到废纸篓

如遇:「xxx.app已损坏,打不开.你应该将它移到废纸篓」,并非你安装的软件已损坏,而是Mac系统的安全设置问题,因为这些应用都是破解或者汉化的,那么解决方法就是临时改变Mac系统安全设置。

出现这个问题的解决方法:

修改系统配置:系统偏好设置... -> 安全性与隐私。修改为任何来源

如果没有这个选项的话(macOS Sierra 10.12),打开终端,执行 sudo spctl --master-disable即可。

重点是这一行命令:

sudo spctl --master-disable

然后重新打开 APP

Done !

文章转载自:千橙工坊

Swift 在命令行下使用及退出方法

一直在做 iOS 开发,习惯了在 Xcode 里面进行代码编写,今天使用命令行感受了下 Geeker 们的不一样的代码编写
  • 在启动台打开终端
  • 进入 Swift 命令行
swift

Welcome to Apple Swift version 4.0.3 (swiftlang-900.0.74.1 clang-900.0.39.2). Type :help for assistance.
  • 在命令行输入语法命令
1 + 1

回车

$R0: Int = 2
  • 退出命令行
:q   或者  :quit

Ubuntu 安装 Swift

一直想尝试下 swift 的服务器开发,但碍于工作时间问题,没有如愿。

环境:

Ubuntu 16.04.2 LTS

Swift : Swift 4.0.3

  • 下载 Swift 包 并解压
mkdir swift
cd swift

wget https://swift.org/builds/swift-4.0.3-release/ubuntu1604/swift-4.0.3-RELEASE/swift-4.0.3-RELEASE-ubuntu16.04.tar.gz

tar zvxf swift-4.0.3-RELEASE-ubuntu16.04.tar.gz
  • 配置环境变量
export PATH="$PATH:/root/swift/swift-4.0.3-RELEASE-ubuntu16.04/usr/bin"
  • 更新源
sudo apt-get update
  • 安装依赖库
sudo apt-get install clang
  • 测试是否安装成功
swift --version

Swift version 4.0.3 (swift-4.0.3-RELEASE)
Target: x86_64-unknown-linux-gnu

PS :

  • 安装问题及解决方法:

Ubuntu 16.0.4 安装 Swift 后提示 error while loading shared libraries: libpython2.7.so.1.0

  • Swift 命令使用及退出方法:

Swift 在命令行下使用及退出方法

Chrome 无法改变 button 高度

今天查看中文转拼音页面时,发下转换按钮的样式变成了默认样式了,重新再 Safari 打开,显示样式正常,怀疑是不是 Chrome 最近有改变对 css 的样式支持,Google 到高手秘籍:

源代码:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8"/>
    <title></title>
    <style type="text/css">
    .set{
        height: 40px;
        width: 90px;
        }
    </style>
</head>
<body>
<input class="set" type="button" value="点击设置"/>
</body>
</html>

解决方法一:

把 input 改为 button :

<button class="set" type="button" value="点击设置"/></button>

解决方法二:

在css中增加一个参数(input button 类型,只能用 class 来修改样式);

<style type="text/css">
.set{
    -webkit-appearance:button;
    height: 40px;
    width: 90px;
    }
</style>

参考链接:

[css]button的高度无法改变

git 同时 push 至多个仓库

今天想把个人博客同时推送至 GitHub 和个人私有 Git,当使用

git remote add origin https://github.com/HJDev/Xday.git

添加仓库时,提示错误:

fatal: remote origin already exists.

根据错误提示,我们可以知道,origin 仓库已经存在,所以我们需要更改仓库名称,(如:origin1):

git remote add origin1 https://github.com/HJDev/Xday.git

然后再push 到仓库。

git push -u origin1 

终极秘籍

身为攻城狮的我们,一定不会满足与使用重复的体力来解决毫无意义的体力劳动

使用一条命令同时推送至多个仓库

编辑配置文件

vim .git/config 
[remote "all"]
        url = http://git.teamleader.cn/hejun/blog.git
        url = https://github.com/HJDev/Xday.git

保存。

使用命令:

git push all

Done !

解决 iTunes 12.7 无法下载 AppStore 应用的 IPA 包问题

问题描述

苹果 iTunes 12.7 已经无法下载 ipa 包,如果想在 iTunes 12.7 使用已经无力回天。所以,只能降级!降级!降级!

注:降级 iTunes 12.6.2 会导致无法识别到 iPhone8 / iPhone8 plus / iPhone X 设备, 2017.10月30号更新,下载 iTunes 12.6.3 支持 iPhone 8,iPhone X和iOS 11。

降级步骤

  • 下载 12.6.3 安装包
  • 按步骤进行安装刚才下载的安装包

错误处理

iTunes安装完之后显示:不能读取文件‘iTunes Library.itl'',说因为它是由更高版本iTunes所创建的。你要现在下载 iTunes 吗?

到 Music/iTunes 目录下,删除 iTunes Library.itl 目录就可以,重启打开就正常

rm -rf ~/Music/iTunes/iTunes\ Library.itl

文章转载自: 解决 iTunes 12.7 无法下载 AppStore 应用的 IPA 包问题

Mac AppStore 下载软件提示“发生未知错误,请稍后重试4”

今天同事电脑在 Mac App Store 下载软件提示“发生未知错误,请稍后重试4”,经过排查网络问题、AppleID 问题、App Store 和 iTunes 账号不一致问题以及 AppleID 所在地区 App Store 所在地区不一致问题后,重新设置 App Store 所在地区(App Store 底部右下角中国区标志),使问题得到圆满解决。

总结:App Store 页面上显示的地区可能不是 App Store 所在的地区,可能是显示错误而已,重新设置 App Store 所在地区可以确保设置地区和显示地区的正确。

经验:软件是会有 bug 的,重新修改软件设置可能会使软件问题得到解决。