「 iOS 知識小集 」2018 · 第 23 期

上週公衆號發佈的如下文章:ios

本期知識小集的主要內容包括:web

  • 用 NSDecimalNumber 處理 iOS 中的貨幣金額
  • 如何更容易看懂宏
  • Storyboard/Xib 顏色空間的坑
  • VC 多層 push 後回到指定頁面的幾種方法
  • 添加沙箱技術測試員報錯的問題
  • UIViewController 設置導航欄和標籤欄不一樣 title 的問題
  • 蘋果官方類庫中 NSDateFormatter 的小 bug

用 NSDecimalNumber 處理 iOS 中的貨幣金額

做者: halohily小程序

在iOS開發中,常常遇到貨幣金額的表示與計算,你可能會使用 double 或 float 這樣的浮點數,也可能使用 NSString 。不管用哪一個,都須要再編寫繁瑣的精度控制、小數位數控制等代碼。其實,蘋果爲咱們提供了一個標準類 NSDecimalNumber 來處理這樣的需求。swift

NSDecimalNumber 是 NSNumber 的子類,它提供了完善的初始化方法。對於使人頭疼的金額計算,它還提供了貼心的加、減、乘、除運算方法。在進行這些運算的時候,你還能夠經過 NSDecimalNumberHandler 對象來對運算的處理策略進行設置,好比舍入模式的選擇,數據溢出、除零等異常狀況的處理等。微信小程序

下次遇到貨幣金額的需求,不妨瞭解一下 NSDecimalNumber。微信

參考資料:app

  • iOS 數字精準計算之NSDecimalNumber https://www.jianshu.com/p/ea4da259a062
  • NSDecimalNumber數字精確 https://www.jianshu.com/p/25d24a184016

如何更容易看懂宏

做者: Lefe_x框架

相信你和我同樣,也遇到過特別難理解的宏定義,好比宏與宏之間嵌套、帶參數的宏。咱們看個例子(這個宏並非特別難,但也很繞):iview

#define JPBOXING_GEN(_name, _prop, _type) \
+ (instancetype)_name:(_type)obj  \
{   \
    JPBoxing *boxing = [[JPBoxing alloc] init]; \
    boxing._prop = obj;   \
    return boxing;  \
}

JPBOXING_GEN(boxObj, obj, id)
複製代碼

這個例子看着老是怪怪的,若是把上面的宏轉換成實際代碼,相信你會很容易看懂。ide

+ (instancetype)boxObj:(id)obj
{
    JPBoxing *boxing = [[JPBoxing alloc] init];
    boxing.obj = obj;
    return boxing;
}
複製代碼

其實就是各類參數的替換致使閱讀起來比較困難。咱們都知道程序通過預處理後就會把宏轉換爲實際的代碼,而 Xcode 爲咱們提供了對單個文件進行預處理(Produce -> Perform Action -> Preprocess 'xxxx.m'),這樣處理後,上面的宏就變成了:

+ (instancetype)boxObj:(id)obj { 
   JPBoxing *boxing = [[JPBoxing alloc] init]; 
   boxing.obj = obj; 
   return boxing; 
}
複製代碼

通過預處理後和咱們手動翻譯的結果同樣。

Storyboard/Xib 顏色空間的坑

做者: Vong_HUST

今天分享一下 Xcode Interface Builder 設置背景色的一個坑。從 Xcode8 起,Xib/Storyboard 裏的顏色空間默認從 Generic RGB 換成了 sRGB,但又不是全部的都會轉換,很奇怪。因此當時在適配 Xcode8 的時候,顏色空間都統一全局替換了一遍。最近又遇到一次這個坑,在 Storyboard 把某個視圖背景色從白色更改成 0xf0f1f2,而後 run 起來,和其 superview (superview 的背景色是用代碼設置的 0xf0f1f2)居然有一個明顯的分割線,因此回想起當時適配時的這個問題,而後取到 Storyboard 裏面一看,果真是顏色空間被莫名改成了 Generic RGB,如圖所示。因此手動改變其顏色空間爲 sRGB 便可。

參考連接

  • Xcode Interface Builder 指定顏色與實際有出入 http://t.cn/RgpFOPg
  • WWDC Working with Wide Color http://t.cn/ReADdu7

VC 多層 push 後回到指定頁面的幾種方法

做者: 這個湯圓沒有餡

場景以下: RootVC -- > A -- > B -- > C,而後如今要求C直接pop回到A。

方法一:C返回到B的時候寫個回調,B接收到回調再本身pop到A,可是這個方法B的頁面會閃現一下,用戶體驗很差,不推薦。

方法二:在B push 到C的時候,直接把B從導航控制器的堆棧中移除,如圖一。

方法三:寫一個UIViewController的catrgory,方法實現如圖二。在C的backAct方法中使用,如圖三。有的同窗可能會懷疑B會不會內存泄露,能夠在B中打印dealloc。

這裏比較推薦方法三。不論有多少級的push,只要傳入指定頁面的類名,都能回到該頁面。

添加沙箱技術測試員報錯的問題

做者: 高老師很忙

在測試 IAP 的時候須要添加沙箱技術測試員,至關於建立一個虛擬的 AppleID,填寫的郵箱是不能寫真實 AppleID 郵箱的,要否則就會報錯,能夠隨意寫一個不存在的郵箱,爲了方便,建立一個簡短的密碼就會報錯誤:

按照提示改好後,依然報錯:

而且沒有任何的提示,感受這點好坑,嘗試了N遍以後發現是密碼的複雜度不夠,要包含大小寫和數字,雖然是虛擬的 AppleID,可是密碼規則要和正式的 AppleID 同樣,但願之後蘋果把錯誤提示作的更好吧!😂

UIViewController 設置導航欄和標籤欄不一樣 title 的問題

做者: KANGZUBIN

咱們一般會在一個 UIViewControllerviewDidLoad 方法中經過 self.title = xxx 的方式給一個頁面設置其導航欄標題,相信你們對這再熟悉不過了。

若是一個 VC 頁面中同時具備 NavigationBar(導航欄)和 TabBar(標籤欄),並且咱們又想讓這兩個地方的標題顯示不一致,以下圖所示,在首頁頂部導航欄標題中顯示「知識小集」,而在底部標籤欄標題中顯示「首頁」:

可是,當咱們在 UITabBarController 中初始化好上述頁面結構後,且設置首頁 VC 的 tabBarItem.title 爲 「首頁」,而後在首頁 VC 的 viewDidLoad 方法中設置 self.title 爲 「知識小集」,編譯運行後咱們發現首頁底部標籤欄的標題也變成「知識小集」了,而不是剛設置的「首頁」。

查了蘋果文檔中關於 UIViewControllertitle 屬性的定義,有以下一段描述:

If the view controller has a valid navigation item or tab-bar item, assigning a value to this property updates the title text of those objects.

也就是說,若是一個 VC 同時有導航欄和標籤欄,那麼當給 title 賦值時,會同時修改這兩個地方的標題。因此若是咱們只想設置導航欄的標題,能夠經過 self.navigationItem.title = xxx 的方式來實現。

所以,在一個 VC 中設置相關標題簡單總結以下:

  • self.navigationItem.title: 設置 VC 頂部導航欄的標題

  • self.tabBarItem.title: 設置 VC 底部標籤欄的標題

  • self.title: 同時修改上述兩處的標題

參考文檔

  • UIViewController.title https://developer.apple.com/documentation/uikit/uiviewcontroller/1621364-title?language=objc

蘋果官方類庫中 NSDateFormatter 的小 bug

做者: 我是喬忘記瘋狂

不知道有多少人和我同樣是今天才知道這個問題的

let formatter = NSDateFormatter()
formatter.dateFormat = "yyyy-MM-dd"
let date = formatter.dateFromString("1987-04-12") // nil
複製代碼

這個問題在 StackOverflow 上是有人提過的。其實主要跟一些國家實行 夏時制(Daylight saving time) 有關係,尤爲是美國

解決辦法我是嘗試這樣增長一句代碼

let formatter = NSDateFormatter()
formatter.dateFormat = "yyyy-MM-dd"
formatter.calendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierISO8601)
let date = formatter.dateFromString("1987-04-12") // Apr 12, 1987, 1:00 AM
複製代碼

最後推薦一個夏時制的相關閱讀,高曉鬆的 魚羊野史 第1卷 中1月6日那一章,有講到美國於1974年1月6日開始實行夏時制並一直到今天,還講到其餘一些相關的有意思的事情。

參考文檔

  • NSDateFormatter.dateFromString returns nil for specific dates in specific languages

https://stackoverflow.com/questions/32408898/nsdateformatter-datefromstring-returns-nil-for-specific-dates-in-specific-langua

關注咱們

歡迎關注咱們的公衆號:iOS-Tips,也歡迎加入咱們的羣組討論問題。能夠公衆號留言 iosflutterwebpwa小程序 等關鍵詞獲取入羣方式。

相關文章
相關標籤/搜索