我的应用程序允许用户选择各种货币进行支出跟踪.我有一个标签,显示带有当前符号的金额.我使用NSNumberFormatter与kCFNumberFormatterCurrencyStyle格式化金额字符串,并在标签中显示出来;
numberFormatter = [[NSNumberFormatter alloc] init];
numberFormatter.numberStyle = kCFNumberFormatterCurrencyStyle;
numberFormatter.currencyCode = @"EUR";
Run Code Online (Sandbox Code Playgroud)
我的目标是显示不同颜色的货币符号,所以我使用NSAttributedString,试图找到符号的范围并为其设置不同的属性.问题是格式化程序在我初始化属性字符串时返回错误的符号:
MLOG(@"internationalCurrencySymbol %@", numberFormatter.internationalCurrencySymbol);
MLOG(@"currencySymbol %@", numberFormatter.currencySymbol);
MLOG(@"currencyCode %@", numberFormatter.currencyCode);
//logs:
//USD
//$
//EUR
Run Code Online (Sandbox Code Playgroud)
但当标签显示在屏幕上时,我看到正确的欧元货币符号: €
有谁知道如何获得给定货币代码的货币符号?
我发现了另一个问题,它带来了有关问题和可能解决方案的更多细节.似乎有一个已知的bug是未来改进的主题.
基于iOS Swift的动态框架中的Objective C类
我正在Swift中开发一个框架,我在框架中使用了一些Objective-C代码.到目前为止,我的模块映射如下所示:
framework module MyModule {
umbrella header "MyModule-umbrella.h"
export *
explicit module Private {
header "MyTools.h"
}
}
Run Code Online (Sandbox Code Playgroud)
我担心的是所有的API MyTools.h都是从框架外部看到的:例如,如果你使用Cocoapods安装框架,那么你import MyModule进入你的应用程序(而不是MyModule.Private),你就能够访问MyTools.h哪些不可取和多余.有没有办法让MyTools从框架外部看不见?
PS.我使用Cocoapods来分发框架,这是我的podspec(最重要的部分):
s.module_map = 'Pod/MyModule.modulemap'
s.frameworks = 'CoreData', 'CoreTelephony', 'SystemConfiguration'
s.resources = 'Pod/Classes/MessageStorage/*.xcdatamodeld'
s.public_header_files = 'Pod/Classes/**/*.h'
s.private_header_files = 'Pod/Classes/MyTools/**/*.h'
s.source_files = 'Pod/Classes/**/*.{h,m,swift}'
Run Code Online (Sandbox Code Playgroud)
PSS.我的伞形标题不会导入MyTools.h
PSSS.只是试图从主模块中排除标题:
framework module MyModule {
umbrella header "MyModule-umbrella.h"
export *
exclude header "MyTools.h"
explicit module Private {
header "MyTools.h"
}
}
Run Code Online (Sandbox Code Playgroud)
没运气.
首先我引用《Apple Threading 编程指南》中的一章:
注意代码正确性的威胁
使用锁和内存屏障时,您应该始终仔细考虑它们在代码中的位置。即使是看起来位置很好的锁,实际上也会让你产生一种错误的安全感。以下一系列示例试图通过指出看似无害的代码中的缺陷来说明这个问题。基本前提是您有一个包含一组不可变对象的可变数组。假设您要调用数组中第一个对象的方法。您可以使用以下代码来执行此操作:
NSLock* arrayLock = GetArrayLock();
NSMutableArray* myArray = GetSharedArray();
id anObject;
[arrayLock lock];
anObject = [myArray objectAtIndex:0];
[arrayLock unlock];
[anObject doSomething];
Run Code Online (Sandbox Code Playgroud)
因为数组是可变的,所以数组周围的锁可以防止其他线程修改数组,直到获得所需的对象为止。而且由于您检索的对象本身是不可变的,因此在调用 doSomething 方法时不需要锁。
不过,前面的示例存在一个问题。如果您释放锁并且另一个线程进入并在您有机会执行 doSomething 方法之前从数组中删除所有对象,会发生什么情况?在没有垃圾回收的应用程序中,代码所持有的对象可能会被释放,从而使 anObject 指向无效的内存地址。要解决此问题,您可能决定简单地重新排列现有代码并在调用 doSomething 后释放锁定,如下所示:
NSLock* arrayLock = GetArrayLock();
NSMutableArray* myArray = GetSharedArray();
id anObject;
[arrayLock lock];
anObject = [myArray objectAtIndex:0];
[anObject doSomething];
[arrayLock unlock];
Run Code Online (Sandbox Code Playgroud)
通过将 doSomething 调用移到锁内,您的代码可以保证在调用该方法时该对象仍然有效。不幸的是,如果 doSomething 方法需要很长时间才能执行,这可能会导致您的代码长时间持有锁,从而可能造成性能瓶颈。
代码的问题不是关键区域定义不明确,而是没有理解实际问题。真正的问题是内存管理问题,该问题仅由其他线程的存在触发。因为它可以被另一个线程释放,所以更好的解决方案是在释放锁之前保留 anObject。该解决方案解决了释放对象的实际问题,并且不会带来潜在的性能损失。
NSLock* arrayLock = GetArrayLock();
NSMutableArray* myArray = GetSharedArray();
id anObject;
[arrayLock lock];
anObject = [myArray objectAtIndex:0];
[anObject retain]; …Run Code Online (Sandbox Code Playgroud) 根据文档,我们必须担心一些事情:内存泄漏。https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/CoreData/Articles/cdMemory.html:
\n\n\n\n\n打破关系强引用循环
\n\n当托管对象之间存在关系时,每个对象都会维护对其相关的一个或多个对象的强引用。这可能会导致强引用循环。为了确保引用循环被打破,当您完成一个对象时,您可以使用托管对象上下文方法refreshObject:mergeChanges:将其转换为错误。
\n\n您通常使用refreshObject:mergeChanges: 刷新托管对象\n\xe2\x80\x99s 属性值。如果 mergeChanges 标志为 YES,则该方法将对象 xe2x80x99s 属性值与持久存储协调器中可用对象的属性值合并。但是,如果该标志为 NO,则该方法只是将对象恢复为故障而不进行合并,这会导致它破坏对相关托管对象的强引用。这会打破该托管对象与其他托管对象之间的强引用循环。
\n\n当然,请注意,在解除分配托管对象之前,必须没有对其的强引用,包括来自 Core Data 外部的强引用。另请参阅更改和撤消管理。
\n
但。没有任何 Apple 的代码示例可以解决此问题。\n我检查了 TopSongs、iPhoneCoreDataRecipes、CoreDataBooks、ThreadedCoreData 示例项目,但没有一个涉及此问题。这是否意味着现在对象关系很弱?
\n