提示:由于水平有限,如发现有疑问或错误的地方请毫不客气的提出、讨论,我会在第一时间回复,感谢在先
//给部分 字符串添加删除线不显示. 系统版本为iOS 8.1、10.3
NSMutableAttributedString *attrStr = [[NSMutableAttributedString alloc] initWithString:@"市场价格:"];
NSAttributedString* priceAtrrStr = [[NSMutableAttributedString alloc]initWithString:@"3.45¥" attributes:@{NsstrikethroughStyleAttributeName : @(NSUnderlinestyleSingle)}];
[attrStr appendAttributedString:priceAtrrStr];
_displayLB.attributedText = attrStr;
//解决方法
NSMutableAttributedString *attrStr = [[NSMutableAttributedString alloc] initWithString:@"市场价格:" attributes:@{NSBaselineOffsetAttributeName:@0}];
//@(NSUnderlinestyleNone) @0值是相同的;
- 价格计算
NSDecimalNumber继承NSNumber;可以利用NSDecimalNumber计算价格
// NSDecimalNumber 的利用类属性 来创建对象;
//@property (class,readonly,copy) NSDecimalNumber *zero;
//@property (class,copy) NSDecimalNumber *one;
N<a href="/tag/sst/" target="_blank" class="keywords">sst</a>ring* aPriceStr = @"34.34";
NSDecimalNumber* aDecimal = [NSDecimalNumber decimalNumberWithString:aPriceStr];
N<a href="/tag/sst/" target="_blank" class="keywords">sst</a>ring* bPriceStr = @"34.434";
NSDecimalNumber* bDecimal = [NSDecimalNumber decimalNumberWithString:bPriceStr];
// 加减乘除
NSDecimalNumber* addDecimal = [aDecimal decimalNumberByAdding:bDecimal];
NSDecimalNumber* subt<a href="/tag/rating/" target="_blank" class="keywords">rating</a>Decimal = [aDecimal decimalNumberBySubtracting:bDecimal];
NSDecimalNumber* multiplyingDecimal = [aDecimal decimalNumberByMultiplyingBy:bDecimal];
NSDecimalNumber* dividingDecimal = [aDecimal decimalNumberByDividingBy:bDecimal];
// 保留小数点
NSDecimalNumberHandler* behaviors = [NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:NSRoun<a href="/tag/dpl/" target="_blank" class="keywords">dpl</a>ain scale:2 rai<a href="/tag/SEO/" title="SEO">SEO</a>nExact<a href="/tag/nes/" target="_blank" class="keywords">nes</a>s:NO rai<a href="/tag/SEO/" title="SEO">SEO</a>nOverflow:NO rai<a href="/tag/SEO/" title="SEO">SEO</a>nUnderflow:NO rai<a href="/tag/SEO/" title="SEO">SEO</a>nDivideByZero:YES];
NSDecimalNumber* twoPointResult = [addDecimal decimalNumberByRoundingAccordingToBehavior:behaviors];
NSLog(@"addDecimal:%@",addDecimal.stringValue);
NSLog(@"subt<a href="/tag/rating/" target="_blank" class="keywords">rating</a>Decimal:%@",subt<a href="/tag/rating/" target="_blank" class="keywords">rating</a>Decimal.stringValue);
NSLog(@"multiplyingDecimal:%@",multiplyingDecimal.stringValue);
NSLog(@"dividingDecimal:%@",dividingDecimal.stringValue);
// 保留两位小数
NSLog(@"twoPointResult:%@",twoPointResult.stringValue);
/*
上面 decimalNumberByDividingBy,decimalNumberByMultiplyingBy,decimalNumberBySubtracting等<a href="/tag/fangfa/" target="_blank" class="keywords">方法</a>在实际算计存在安全风险
正确的做法使用各<a href="/tag/zidai/" target="_blank" class="keywords">自带</a>有behavior的<a href="/tag/fangfa/" target="_blank" class="keywords">方法</a>
- (NSDecimalNumber *)decimalNumberByAdding:(NSDecimalNumber *)decimalNumber;
- (NSDecimalNumber *)decimalNumberByAdding:(NSDecimalNumber *)decimalNumber withBehavior:(nullable id <NSDecimalNumberBehaviors>)behavior;
- (NSDecimalNumber *)decimalNumberBySubtracting:(NSDecimalNumber *)decimalNumber;
- (NSDecimalNumber *)decimalNumberBySubtracting:(NSDecimalNumber *)decimalNumber withBehavior:(nullable id <NSDecimalNumberBehaviors>)behavior;
- (NSDecimalNumber *)decimalNumberByMultiplyingBy:(NSDecimalNumber *)decimalNumber;
- (NSDecimalNumber *)decimalNumberByMultiplyingBy:(NSDecimalNumber *)decimalNumber withBehavior:(nullable id <NSDecimalNumberBehaviors>)behavior;
- (NSDecimalNumber *)decimalNumberByDividingBy:(NSDecimalNumber *)decimalNumber;
- (NSDecimalNumber *)decimalNumberByDividingBy:(NSDecimalNumber *)decimalNumber withBehavior:(nullable id <NSDecimalNumberBehaviors>)behavior;
behavior 只要遵循 NSDecimalNumberBehaviors 协议就好.
@protocol NSDecimalNumberBehaviors
- (NSRoundingMode)roundingMode;
- (short)scale; // The scale <a href="/tag/Could/" target="_blank" class="keywords">Could</a> return NO_SCALE for no defined scale.
- (nullable NSDecimalNumber *)exceptionDuringOperation:(SEL)operation error:(NSCal<a href="/tag/cula/" target="_blank" class="keywords">cula</a>tionError)error leftOperand:(NSDecimalNumber *)leftOperand rightOperand:(nullable NSDecimalNumber *)rightOperand; // Receiver can raise,return a new value,or return nil to ig<a href="/tag/nor/" target="_blank" class="keywords">nor</a>e the exception.
@end
@implementation NSDecimalNumberCustomOperBehavior
+ (instancetype)operBehaviorWithRoundingMode:(NSRoundingMode)mode scale:(short)scale {
NSDecimalNumberCustomOperBehavior* behavior = [[NSDecimalNumberCustomOperBehavior alloc]init];
behavior.roundingMode = mode;
behavior.scale = scale;
return behavior;
}
- (nullable NSDecimalNumber *)exceptionDuringOperation:(SEL)operation error:(NSCal<a href="/tag/cula/" target="_blank" class="keywords">cula</a>tionError)error leftOperand:(NSDecimalNumber *)leftOperand rightOperand:(nullable NSDecimalNumber *)rightOperand {
//处理异常
return [NSDecimalNumber notANumber];
}
- (NSRoundingMode)roundingMode {
//舍入模式
return _roundingMode;
}
- (short)scale {
//小数点精度
return _scale;
}
@end
系统<a href="/tag/mo/" target="_blank" class="keywords">默</a>认提供 <a href="/tag/yige/" target="_blank" class="keywords">一个</a> NSDecimalNumberHandler类也是遵循 NSDecimalNumberBehaviors协议的.
*/
/
addDecimal:68.774
subtratingDecimal:-0.094
multiplyingDecimal:1182.46356
dividingDecimal:0.9972701399779287913109136318754719172
twoPointResult:68.77
/
/* RoundingMode 含义
Original Value NSRoun<a href="/tag/dpl/" target="_blank" class="keywords">dpl</a>ain NSRoundDown & NS RoundUp NSRoundBankers
1.24 1.2 1.2 & 1.3 1.2
1.26 1.3 1.2 & 1.3 1.3
1.25 1.3 1.2 & 1.3 1.2
1.35 1.4 1.3 & 1.4 1.4
–1.35 –1.4 –1.4 & -1.3 –1.4
NSRoun<a href="/tag/dpl/" target="_blank" class="keywords">dpl</a>ain: 取最接近的数;如果最后一位为5;为正数时向上取值,为负数时向下取值
NSRoundDown: 向下值
NSRoundUp: 向上值
NSRoundBankers:取最接近的数;如果最后一位为5;通过向上或者向下取值使得取值后最后<a href="/tag/yige/" target="_blank" class="keywords">一个</a>数为偶数
*/
-
Pod Unable to find a pod with name,author,summary,or descriptionmatching
参考链接:- NSTextAttachment
- (void)configureUI { NSMutableAttributedString* mutAttrStr = [[NSMutableAttributedString alloc]initWithString:@"Tomorow is better " attributes:@{NSForegroundColorAttributeName:UIColor.lightGrayColor}]; NSTextAttachment* attm = [[NSTextAttachment alloc]init]; attm.image = [UIImage imageNamed:@"green-positioning"]; attm.bounds = [attm configureAttmentRectWithX:0 Y:-3 Height:15]; NSAttributedString* attmStr = [NSAttributedString attributedStringWithAttachment:attm]; [mutAttrStr appendAttributedString:attmStr]; self.contentLabel.attributedText = mutAttrStr; } //给NSTextAttachment添加配置bouds的分类方法 - (CGRect)configureAttmentRectWithX:(CGFloat)x Y:(CGFloat)y Height:(CGFloat)height { return CGRectMake(x,y,self.image.size.width * height /self.image.size.height,height); }
- Tracing Objc Message
(1)instrumentObjcMessageSends(YES); // 开启 instrumentObjcMessageSends(NO); //关闭 使用的时候需要添加函数声明extern instrumentObjcMessageSends(BOOL); log保存在 /tmp/msg-xxxx 的文件中(只能在模拟器中使用哦)
#import
typedef void(*func)(BOOL);
static inline void ste_tracing_msg(BOOL yesOrNo) {
void* libObj = dlopen("/usr/lib/libobjc.dylib",RTLD_LAZY);
func instrumentObjcMessageSends = dlsym(libObj,"instrumentObjcMessageSends");
instrumentObjcMessageSends(yesOrNo);
//同上面相同,log保存在 /tmp/msg-xxxx
}
(2)设置NSObjCMessageLoggingEnabled 环境变量可以打印所有message,log保存在 /tmp/msg-xxxx 的文件中;由于内容很多,查看的时候需要用vim 进行搜索
- 为带有XIB的ViewController减负;
对于简单界面而言;控件都放在xib上,然后把xib上的创建的不同View outLet 对应的view上面就可以了. - NSObject load vs initialize;
load
Invoked whenever a class or category is added to the Objective-C runtime; implement this method to perform class-specific behavior upon loading.
无论何时,当一个类或者类目添加到runtime中时,在这个类或者类目加载的过程中,实现的load方法就可以执行一些和类相关的业务逻辑. (重点:何时 + 做什么)
load order
A class’s +load method is called after all of its superclasses’ +load methods.
A category +load method is called after the class’s own +load method.
总结来说加载顺序就是: superclasse’+load ->classes’ + load -> category’ + load
void call_load_methods(void)
{
static BOOL loading = NO;
BOOL more_categories;
recursive_mutex_assert_locked(&loadMethodLock);
// Re-entrant calls do nothing; the outermost call will finish the job.
if (loading) return;
loading = YES;
void *pool = objc_autoreleasePoolPush();
do {
//从下面的顺序中可以看到,是先加载类的load方法,然后再加载category的load方法
// 1. Repeatedly call class +loads until there aren't any more
while (loadable_classes_used > 0) {
call_class_loads(); //分别调用class load方法
}
// 2. Call category +loads ONCE
more_categories = call_category_loads(); //调用类目的加载方法;
// 3. Run more +loads if there are classes OR more untried categories
} while (loadable_classes_used > 0 || more_categories);
objc_autoreleasePoolPop(pool);
loading = NO;
}
static void schedule_class_load(class_t *cls)
{
if (!cls) return;
assert(isRealized(cls)); // _read_images should realize
if (cls->data()->flags & RW_LOADED) return;
// Ensure superclass-first ordering
schedule_class_load(getSuperclass(cls)); //确保父类的load方法先加载
add_class_to_loadable_list((Class)cls);
changeInfo(cls,RW_LOADED,0);
}
需要注意的地方: In a custom implementation of load you can therefore safely message other unrelated classes from the same image,but any load methods implemented by those classes may not have run yet (假设一个镜像文件中有 A类、A类的父类、A类类目,B类、B类的父类、B类类目,我们唯一能确定的是:先加载一个类(A或者B其中一个)的父类然后再加载这个类(A或者B),我们无法确认是先加载A类还是B类)
initialize :Initializes the class before it receives its first message. 在对象接受到第一条消息之前执行initialize方法,但是注意 __这里message不包括load__;load的方法是在加载时执行的,在initialize执行之前.并且执行一次;因为使用的时候,如果一个类没有实现initialize方法,它就会调用父类的initialize的方法(如果父类实现这个方法的话),为了减少不必要的判断关系,我们一般使用load
void _class_initialize(Class cls)
{
//摘取的代码片段
assert(!_class_isMetaClass(cls));
Class supercls;
BOOL reallyInitialize = NO;
// Make sure super is done initializing BEFORE beginning to initialize cls.
// See note about deadlock above.
supercls = _class_getSuperclass(cls);
// 先initialize父类
if (supercls && !_class_isInitialized(supercls)) {
_class_initialize(supercls);
}
// initialize本类
// Try to atomically set CLS_INITIALIZING.
if (!_class_isInitialized(cls) && !_class_isInitializing(cls)) {
_class_setInitializing(cls);
reallyInitialize = YES;
}
}
需要的注意的是: The superclass implementation may be called multiple times if subclasses do not implement initialize—the runtime will call the inherited implementation—or if subclasses explicitly call [super initialize] If you want to protect yourself from being run multiple times,you can structure your implementation along these lines:
+ (void)initialize {
//判断是本类就执行相应的方法.
if (self == [ClassName self]) {
// ... do the initialization ...
}
}
另外一点要注意的是如果 在category也实现了initialize方法 那么父类的initialize估计要被覆盖了,个人 猜测是因为category加载时机在类的后面(gusess ) .其实 initialize方法基本和一般方法使用相同
load 和 initialize中方法应该只执行 轻量级的任务
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。