使用CGGeometry方法獲取CGRect數(shù)據(jù)

CGGeometry 中提供了取特定 CGRect 值的便捷方法。

  • CGRectGetMinX
  • CGRectGetMinY
  • CGRectGetMidX
  • CGRectGetMidY
  • CGRectGetMaxX
  • CGRectGetMaxY
  • CGRectGetWidth
  • CGRectGetHeight

這其中CGRectGetMidX,CGRectGetMidY,CGRectGetMaxX,CGRectGetMaxY四個方法十分有用。用CGRectGetMaxX代替frame.origin.x + frame.size.width將使代碼更加清晰北戏、語義上也更為生動直觀。另外三個方法也同樣英遭,他們都可以用來代替類似這樣的代碼庵佣。

  • CGRectGetMidX用來替代frame.origin.x + frame.size.width / 2
  • CGRectGetMidY用來替代frame.origin.y + frame.size.height / 2
  • CGRectGetMaxX用來替代frame.origin.x + frame.size.width
  • CGRectGetMaxY用來替代frame.origin.y + frame.size.height

這時你也許會想到检柬,那CGRectGetMinX,CGRectGetMinY,CGRectGetWidth,CGRectGetHeight四個方法是不是也是用來代替類似這樣的代碼。

  • CGRectGetMinX用來替代frame.origin.x
  • CGRectGetMinY用來替代frame.origin.y
  • CGRectGetWidth用來替代frame.size.width
  • CGRectGetHeight用來替代frame.size.width

答案是肯定的茴恰。但這四個方法看起來卻不是那么有必要颠焦。因?yàn)楦苯诱{(diào)用相比,這樣寫代碼要更長往枣。

  • CGRectGetMinX(frame)
  • frame.origin.x

而且如果想要喚起 Xcode 的聯(lián)想伐庭,最少需要輸入“CGRectGet”八個字母。而直接調(diào)用通常只需要輸入“f”婉商,“.o”似忧,“.x”五個字母就能聯(lián)想完成渣叛。經(jīng)過性能測試丈秩,CGRectGetMinX(frame) 的億次調(diào)用耗時561毫秒,而直接調(diào)用由于不明原因淳衙,不管循環(huán)多少次測試調(diào)用時間都低于1毫秒蘑秽。竟然代碼更長,輸入更慢箫攀,效率更低肠牲,那 CGGeometry 提供這些接口的意義在哪呢。其實(shí)靴跛,僅憑代碼統(tǒng)一的代碼風(fēng)格缀雳,生動直觀的語義也值得你這樣去做。而且效率上的差異只是理論數(shù)值梢睛,實(shí)際上CGRectGet的10萬次調(diào)用只耗時1毫秒肥印,在整個APP的運(yùn)行期間也很難有超過10萬次的調(diào)用。

蘋果官方文檔推薦使用 CGGeometry 方法绝葡,同時盡量避免直接調(diào)用深碱。事實(shí)上僅僅因?yàn)樯鲜龅倪@些好處蘋果是不會建議盡量避免直接調(diào)用的,這兩種調(diào)用方法其實(shí)存在這本質(zhì)的差異藏畅。在平時的使用中我們沒有遇到差異敷硅,是因?yàn)槲覀兪褂玫?frame 或 bounds 通常都是正數(shù),當(dāng)負(fù)數(shù)出現(xiàn)的時候愉阎,有意思的事情就來了绞蹦。

StackOverflow摘自蘋果郵件列表的原文說明了這個現(xiàn)象。大意就是“CGRectGetWidth/Height 會將 width 或者 height 格式化榜旦,格式化基本上只是檢查 width 或者 height 是否為負(fù)數(shù)幽七,如果為負(fù)數(shù)則取絕對值”。下邊就來解釋這個現(xiàn)象背后的原因和他們本質(zhì)的差別章办。

CGRectGetWidth/Height will normalize the width or height before returning them. Normalization is basically just checking if the width or height is negative, and negating it to make it positive if so.

CGRect 是用來儲存矩形幾何信息的容器锉走,通過這些信息就能知道怎么去繪制矩形滨彻。UIView 通過 CGRect 類型的成員變量 frame 來描述自己的位置和形狀。通過 CGRectGet 方法獲取到的是 view 的實(shí)際位置和形狀挪蹭,而直接調(diào)用獲取的只是描述幾何體位置和形狀的信息亭饵,他們的是帶有方向性的。比如梁厉,view 的寬是-100辜羊,代表的是在 x 軸反方向的100,最終繪制出來矩形的寬還是100词顾,只是在 x 軸負(fù)方向而已八秃。所以,通過 CGRectGetWidth(frame) 獲取到的就是真實(shí)的寬度100,而直接調(diào)用只能獲取同時描述寬度和方向的數(shù)值-100肉盹。這看起來只是取絕對值這么簡單昔驱,但其他方法可并不是這樣。通過如下代碼繪制出來下圖所示的兩個 view 將幫助你更好的理解這一點(diǎn)上忍。

UIView *view = [[UIView alloc] initWithFrame:CGRectMake(200, 500, 100, 100)];
view.backgroundColor = [UIColor grayColor];
[self.view addSubview:view];

UIView *subview = [[UIView alloc] initWithFrame:CGRectZero];
subview.backgroundColor = [UIColor lightGrayColor];
[view addSubview:subview];

CGRect frame = CGRectMake(-50, -100, -100, -150);
NSLog(@"%f, %f", CGRectGetMinX(frame), frame.origin.x);
NSLog(@"%f, %f", CGRectGetMinY(frame), frame.origin.y);
NSLog(@"%f, %f", CGRectGetMidX(frame), frame.origin.x + frame.size.width / 2);
NSLog(@"%f, %f", CGRectGetMidY(frame), frame.origin.y + frame.size.height / 2);
NSLog(@"%f, %f", CGRectGetMaxX(frame), frame.origin.x + frame.size.width);
NSLog(@"%f, %f", CGRectGetMaxY(frame), frame.origin.y + frame.size.height);
NSLog(@"%f, %f", CGRectGetWidth(frame), frame.size.width);
NSLog(@"%f, %f", CGRectGetHeight(frame), frame.size.height);

subview.frame = frame;
CGRect.png

通過圖片顯而易見骤肛,使用 CGRectGetMinX 獲取到的是 viewB 顯示在屏幕上最左邊位置,就是-150窍蓝。而通過 frame.origin.x 獲取到的必然是-50腋颠。簡單來說,只要 width 或者 height 是負(fù)數(shù)吓笙,那么這個 view 的左右或者上下其實(shí)是翻轉(zhuǎn)過的淑玫。你之前用直接調(diào)用的方法(frame.origin.x + frame.size.width)去獲取的(-50 - 100 = -150)其實(shí) view 左邊。

代碼打印出來 CGRectGet 方法的數(shù)據(jù)都符合這樣的規(guī)則面睛。

2016-02-26 15:40:13.141 LPTest[2319:859916] -150.000000, -50.000000
2016-02-26 15:40:13.141 LPTest[2319:859916] -250.000000, -100.000000
2016-02-26 15:40:13.141 LPTest[2319:859916] -100.000000, -100.000000
2016-02-26 15:40:13.141 LPTest[2319:859916] -175.000000, -175.000000
2016-02-26 15:40:13.141 LPTest[2319:859916] -50.000000, -150.000000
2016-02-26 15:40:13.141 LPTest[2319:859916] -100.000000, -250.000000
2016-02-26 15:40:13.142 LPTest[2319:859916] 100.000000, -100.000000
2016-02-26 15:40:13.142 LPTest[2319:859916] 150.000000, -150.00000

通過這樣的規(guī)則絮蒿,我們推理出這八種方法的函數(shù)原型。如下所示侮穿。

CG_EXTERN CGFloat CGRectGetMinX(CGRect rect) {
    return rect.origin.x + (rect.size.width > 0? 0: rect.size.width);
}

CG_EXTERN CGFloat CGRectGetMinY(CGRect rect) {
    return rect.origin.y + (rect.size.height > 0? 0: rect.size.height);
}

CG_EXTERN CGFloat CGRectGetMidX(CGRect rect) {
    return rect.origin.x + rect.size.width / 2;
}

CG_EXTERN CGFloat CGRectGetMidY(CGRect rect) {
    return rect.origin.y + rect.size.height / 2;
}

CG_EXTERN CGFloat CGRectGetMaxX(CGRect rect) {
    return rect.origin.x + (rect.size.width < 0? 0: rect.size.width);
}

CG_EXTERN CGFloat CGRectGetMaxY(CGRect rect) {
    return rect.origin.y + (rect.size.height < 0? 0: rect.size.height);
}

CG_EXTERN CGFloat CGRectGetWidth(CGRect rect) {
    return fabs(rect.size.width);
}

CG_EXTERN CGFloat CGRectGetHeight(CGRect rect) {
    return fabs(rect.size.height);
}

大部分情況下歌径,我們調(diào)用 frame.origin.x 的目的其實(shí)都是想獲取 view 最左邊的位置,其實(shí)都應(yīng)該調(diào)用 CGRectGetMinX(frame) 方法亲茅。也許你以前習(xí)慣通過 frame.origin.x 來獲取左邊的位置回铛,通過 CGRectGetMaxX(frame) 來獲取右邊的位置。這樣混合調(diào)用的代碼是存在很多隱患的克锣,只是可能并沒有體現(xiàn)出來茵肃。在這種情況你最好還是改正下自己的習(xí)慣。了解了這些后你就能根據(jù)使用場景來決定自己應(yīng)該怎么做袭祟。最后验残,對 CGRectGet 方法的好處進(jìn)行簡單總結(jié)。

  1. 語義生動直觀
  2. 代碼風(fēng)格統(tǒng)一
  3. 能夠獲取到view真實(shí)的位置
  4. 調(diào)用接口簡單

參考資料

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末巾乳,一起剝皮案震驚了整個濱河市您没,隨后出現(xiàn)的幾起案子鸟召,更是在濱河造成了極大的恐慌,老刑警劉巖氨鹏,帶你破解...
    沈念sama閱讀 218,858評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件欧募,死亡現(xiàn)場離奇詭異,居然都是意外死亡仆抵,警方通過查閱死者的電腦和手機(jī)跟继,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來镣丑,“玉大人舔糖,你說我怎么就攤上這事≥航常” “怎么了金吗?”我有些...
    開封第一講書人閱讀 165,282評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長慨蛙。 經(jīng)常有香客問我辽聊,道長,這世上最難降的妖魔是什么期贫? 我笑而不...
    開封第一講書人閱讀 58,842評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮异袄,結(jié)果婚禮上通砍,老公的妹妹穿的比我還像新娘。我一直安慰自己烤蜕,他們只是感情好封孙,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,857評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著讽营,像睡著了一般虎忌。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上橱鹏,一...
    開封第一講書人閱讀 51,679評論 1 305
  • 那天膜蠢,我揣著相機(jī)與錄音,去河邊找鬼莉兰。 笑死挑围,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的糖荒。 我是一名探鬼主播杉辙,決...
    沈念sama閱讀 40,406評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼捶朵!你這毒婦竟也來了蜘矢?” 一聲冷哼從身側(cè)響起狂男,我...
    開封第一講書人閱讀 39,311評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎品腹,沒想到半個月后并淋,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,767評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡珍昨,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年县耽,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片镣典。...
    茶點(diǎn)故事閱讀 40,090評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡兔毙,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出兄春,到底是詐尸還是另有隱情澎剥,我是刑警寧澤,帶...
    沈念sama閱讀 35,785評論 5 346
  • 正文 年R本政府宣布赶舆,位于F島的核電站哑姚,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏芜茵。R本人自食惡果不足惜叙量,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,420評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望九串。 院中可真熱鬧绞佩,春花似錦、人聲如沸猪钮。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽烤低。三九已至肘交,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間扑馁,已是汗流浹背涯呻。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留檐蚜,地道東北人魄懂。 一個月前我還...
    沈念sama閱讀 48,298評論 3 372
  • 正文 我出身青樓,卻偏偏與公主長得像闯第,于是被迫代替她去往敵國和親市栗。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,033評論 2 355

推薦閱讀更多精彩內(nèi)容