1、UIView和UILayer的關(guān)系碌秸?
不同的地方:
1 )繼承結(jié)構(gòu)不同
UIView繼承自UIResponder間接繼承自NSObject的,CALayer是直接繼承NSObject悄窃。因此UIView是可以響應事件的讥电,如手勢;CA Layer則不可以轧抗。
2)所屬框架不同
UIView在UIKit.framework中定義的恩敌,UIKit主要是用來構(gòu)建用戶界面,并且可以響應事件横媚。CALayer則在QuartzCore.framework中定義的纠炮,CALayer是用來承載繪制內(nèi)容的底層對象月趟。
3)相似的樹形結(jié)構(gòu)
4)在做iOS動畫的時候,修改非rootlayer的屬性(譬如位置恢口、背景色等)會默認產(chǎn)生隱式動畫狮斗,而修改UIView則不會。
總結(jié)兩者最大的不同則是弧蝇,UIView可以響應用戶事件碳褒,而CALayer不可以。UIView側(cè)重于對內(nèi)容的繪制看疗,UIView側(cè)重于對顯示內(nèi)容的管理沙峻。
UIView和CALayer是相互依賴的關(guān)系。UIView依賴于CALayer提供的內(nèi)容两芳,CALayer依賴UIView提供的容器來顯示繪制的內(nèi)容摔寨。歸根結(jié)底CALayer是一切的基礎(chǔ),如果沒有CALayer怖辆,UIView自身也不會存在是复。UIView是一個特殊的CALayer實現(xiàn)且添加了響應事件的能力。UIView本身更像是一個CALayer的管理器竖螃,訪問它的跟繪圖以及坐標相關(guān)的屬性淑廊,例如frame、bounds等等特咆,實際上內(nèi)部都是在訪問它所包含的CALayer的相關(guān)屬性季惩。UIView的layer樹形在系統(tǒng)中,存在著三份copy:
一腻格、邏輯樹画拾,代碼里可以操作的,如修改layer的屬性等就在這里菜职;
二青抛、動畫樹,中間層酬核,系統(tǒng)正是在這一層上更改屬性蜜另,進行各種渲染操作;
三愁茁、顯示樹蚕钦,這棵樹的內(nèi)容是當前正被顯示在屏幕上的內(nèi)容亭病。
這三棵樹的邏輯結(jié)構(gòu)都是一樣的鹅很,區(qū)別只有各自的屬性。
UIView的主layer以外罪帖,對它的subLayer即子layer的屬性進行更改促煮,系統(tǒng)將自動進行動畫生成邮屁。
CALayer的坐標系系統(tǒng)和UIView的有點不一樣,多了一個anchorPoint屬性(相對于bound 坐標系)(CGPoint類型菠齿,值域是0-1佑吝,即按照比例來設(shè)置),這個點是各種圖形變換的坐標原點绳匀,同時會改變layer的position位置(相對于superLayer)芋忿,它的缺省值是{0.5,0.5}疾棵,layer的中央
frame戈钢、position以及anchorPoint關(guān)系:
frame.origin.x = position.x - anchorPoint.x * bounds.size.width;
frame.origin.y = position.y - anchorPoint.y * bounds.size.height是尔;
2殉了、hitTest
就直接描述一下事件響應鏈吧。
一拟枚、查找用戶點擊視圖薪铜。
當用戶點擊某視圖時,UIWindow首先接受到響應恩溅,此響應包括用戶點擊區(qū)域和一個封裝好的UIEvent對象隔箍,然后UIWindow會通過這些信息調(diào)用pointInside:withEvent:方法返回yes得知用戶點擊的范圍ViewA(假設(shè));ViewA調(diào)用hitTest:withEvent:方法脚乡,在方法中遍歷所有的subView(如ViewB鞍恢、ViewC)調(diào)用hitTest:withEvent:方法;在遍歷中發(fā)現(xiàn)使用ViewC調(diào)用pointInside:withEvent:方法時返回yes得知用戶點擊范圍ViewC中每窖;再遍歷ViewC中各子視圖帮掉,并調(diào)用pointInside:withEvent:判斷點擊范圍;重復上述過程直至找到一個視圖的subviews個數(shù)為0窒典,此視圖即為用戶點擊的View蟆炊;
二、響應用戶點擊事件
利用UIResponder來實現(xiàn)瀑志,具體方法為UIResponder的nextResponder方法涩搓。
可以通過用戶點擊View,查看View是否響應了點擊事件劈猪,如果沒有昧甘,則找其nextResponder,如果沒有再繼續(xù)找战得,直至找到AppDelegate在沒有響應充边,則點擊事件會被系統(tǒng)丟棄
注意:
在調(diào)用nextResponder有以下幾條規(guī)則:
- 當一個view調(diào)用其nextResponder會返回其superView;
- 如果當前的view為UIViewController的view被添加到其他view上,那么調(diào)用nextResponder會返回當前的UIViewController,而這個UIViewController的nextResponder為view的superView浇冰;
- 如果當前的UIViewController的view沒有添加到任何其他view上贬媒,當前的UIViewController的nextResponder為nil,不管它是keyWinodw或UINavigationController的rootViewController肘习,都是如此际乘;
- 如果當前application的keyWindow的rootViewController為UINavigationController(或UITabViewController),那么通過調(diào)用UINavigationController(或UITabViewController)的nextResponder得到keyWinodw漂佩;
- keyWinodw的nextResponder為UIApplication脖含,UIApplication的nextResponder為AppDelegate,AppDelegate的nextResponder為nil投蝉。
hit-Test View具體的應用見鏈接:http://www.reibang.com/p/d8512dff2b3e
3器赞、block
1)什么是block?
block是帶有自動變量值的匿名函數(shù)墓拜,它也屬于對象(有isa指針)港柜。
2)block類型
根據(jù)block存儲域block主要有三種類型,分別為:
_NSConcreteGlobalBlock存儲在棧上咳榜,沒有引用外部變量(但static以及全局變量除外)夏醉;
_NSConcreteStackBlock,存儲在程序的數(shù)據(jù)區(qū)域(.data區(qū))涌韩,引用了外部變量畔柔,不會持有外部變量;
_NSConcreteMallocBlock存儲在堆上臣樱,一個block被copy時會生成_NSConcreteMallocBlock靶擦,會持有外部變量;
3)__block修飾符
當我們想在block體中修改引用的外部變量值(不包括全局以及static變量)的時候,需要使用__block來修飾外部變量雇毫。當我們對一個block進行copy的時候玄捕,若此block為stack類型,__block變量也會隨著block的copy棚放,從棧復制到堆并被block所持有枚粘;當對malloc類型的block進行copy的話,對__block變量沒有任何影響飘蚯。
4)block的循環(huán)引用問題
block是對象馍迄,擁有著和對象一樣的生命周期,如果沒有強引用的話局骤,就會被釋放攀圈;若產(chǎn)生循環(huán)引用,可以使用__weak(ARC)或者__block(MRC)來解決
MRC環(huán)境下峦甩,如果沒有用__block會持有引用對象赘来,而使用了__block則不會進行copy操作,只是進行指針復制,不會retain引用的對象撕捍。
5)block對以參數(shù)形式傳進來的對象,會不會強引用泣洞?
可以參考函數(shù)以及方法忧风,block對于傳進來的參數(shù),并不會持有
6)block的實現(xiàn)
使用clang -rewrite-objc來編譯可以得到球凰,block最后是被轉(zhuǎn)化成指向__main_block_impl_0結(jié)構(gòu)體的指針狮腿,struct中包括isa(block類型)、FunPtr(函數(shù)實現(xiàn)指針)呕诉,引用變量(若是__block修飾的話缘厢,會是一個__Block_byref_i_0結(jié)構(gòu)體的指針)。當不使用__block修飾的話甩挫,引用變量也僅僅是傳值贴硫,當使用__block修飾的話,會變成傳指針伊者。
詳見http://www.reibang.com/p/ca6ac0ae93ad
4英遭、runtime以及JSpatch
1)為什么說c語言等叫函數(shù)調(diào)用,而OC中叫消息發(fā)送亦渗?
c語言函數(shù)調(diào)用是編譯時就已經(jīng)決定要調(diào)用哪個函數(shù)了挖诸,編譯完成之后直接順序執(zhí)行,無任何二義性法精。OC中函數(shù)調(diào)用稱為消息發(fā)送多律,屬于動態(tài)調(diào)用過程。在編譯的時候搂蜓,并不能決定真正調(diào)用哪個函數(shù)(事實上狼荞,在編譯階段,OC可以調(diào)用任何函數(shù)帮碰,即使這個函數(shù)并未實現(xiàn)粘秆,只要聲明過就不會報錯。這是與c函數(shù)調(diào)用是不同的)收毫。只有在真正運行的時候才會根據(jù)函數(shù)的名稱找到對應的函數(shù)來調(diào)用攻走。
2)消息發(fā)送過程
編譯器將[obj make]轉(zhuǎn)化成obj_msgSend(obj,@selector(make))。在obj_msgSend函數(shù)中此再,首先通過obj的isa指針找到obj所屬的class昔搂,在class中先去cache中通過SEL查找對應函數(shù)實現(xiàn)指針,若是沒有找到則在class的methodList中查找输拇,若仍未找到摘符,則去superClass中查找直到查找到最頂層的class,若是一直未找到則進行消息轉(zhuǎn)發(fā)過程。若是查找到逛裤,則將其加入cache中以方便下次查找瘩绒,并通過查找到的method的函數(shù)指針跳轉(zhuǎn)到對應的函數(shù)中去執(zhí)行。
3)消息轉(zhuǎn)發(fā)過程
1.動態(tài)方法解析
向當前類發(fā)送resolveInstanceMethod:信號带族,檢查是否動態(tài)向該類添加了方法(class_addMethod)锁荔。
2.快速消息轉(zhuǎn)發(fā)
檢查該類是否實現(xiàn)了forwardingTargetForSelector:方法,若是實現(xiàn)了則調(diào)用這個方法蝙砌。若該方法返回非nil或非self阳堕,則向該返回對象重新發(fā)送消息。
3.標準消息轉(zhuǎn)發(fā)
runtime發(fā)送methodSignatureForSelector:消息獲取selector對應的方法簽名择克。返回值非空恬总,則通過forwardInvocation:轉(zhuǎn)發(fā)消息;返回值為空則向當前對象發(fā)送doesNotRecognizeSelector:消息肚邢,程序crash壹堰。
4)快速消息轉(zhuǎn)發(fā)與標準消息準發(fā)比較
快速消息轉(zhuǎn)發(fā):簡單、快速骡湖,但僅能轉(zhuǎn)發(fā)給一個對象
標準消息轉(zhuǎn)發(fā):較復雜缀旁、較慢、但操作實現(xiàn)可控勺鸦,可以實現(xiàn)多對象轉(zhuǎn)發(fā)
5并巍、UIButton的繼承關(guān)系
UIButton繼承自UIControl->UIView->UIResponder,UIControl這個父類添加了target-action事件
6、UINavigationController用啥數(shù)據(jù)結(jié)構(gòu)實現(xiàn)的换途?
這個是使用棧來實現(xiàn)的懊渡,因為navigationController下有許多ViewController,而且存在pushViewController和popViewController這兩種方法
7军拟、__bridge剃执、__bridge__transfer、__bridge__retained
__bridge只做類型轉(zhuǎn)換懈息,但是不修改對象(內(nèi)存)管理權(quán)肾档;
__bridge_retained(也可以使用CFBridgingRetain)將Objective-C的對象轉(zhuǎn)換為Core Foundation的對象,同時將對象(內(nèi)存)的管理權(quán)交給我們辫继,后續(xù)需要使用CFRelease或者相關(guān)方法來釋放對象怒见;
__bridge_transfer(也可以使用CFBridgingRelease)將Core Foundation的對象轉(zhuǎn)換為Objective-C的對象,同時將對象(內(nèi)存)的管理權(quán)交給ARC姑宽。
8遣耍、怎么讓一個UIScrollView不左右滑動?上下滑動炮车?
禁止UIScrollView垂直方向滾動舵变,只允許水平方向滾動
scrollview.contentSize = CGSizeMake(你要的長度, 0);
禁止UIScrollView水平方向滾動酣溃,只允許垂直方向滾動
scrollview.contentSize = CGSizeMake(0, 你要的寬度);
9、svn版本控制命令
服務(wù)器拉取代碼:svn checkout http:XXXX
新建一個test.c文件然后提交:svn add test.c加到本地庫里面纪隙,然后svn ci -m "添加問價說明"赊豌,ci是commit的縮寫
查看修改情況:svn status
對比服務(wù)器與本地版本之間的區(qū)別:svn diff
退到原來的工作拷貝:svn revert,這樣你的本地修改就會丟失
更新本地庫:svn update
解決沖突:svn resolved XX 這個會在更新的同時并保留本地的修改,并將沖突文件標記為resolved绵咱,此后你可以直接在沖突文件中看到標記
10碘饼、svn和git的區(qū)別(了解不深)
1)git是分布式的,svn卻不是麸拄;
2)git把內(nèi)容按元數(shù)據(jù)方式存儲派昧,svn是按文件
3)git沒有一個全局版本號
4)git下載下來后黔姜,在離線狀態(tài)下可以看到所有的log
5)svn克隆一份全新的目錄耗時長
6)svn只有一個版本庫拢切,一旦掛掉所有的工作都不可以進行
7)git的分支很強大。svn的分支是一個完整的目錄秆吵,開辟一個新分支會影響所有人淮椰。
詳情請見 http://www.reibang.com/p/bfec042349ca