ios 使用uinavigationcontroller 作为根视图好吗

ios 使用uinavigationcontroller 作为根视图好吗,第1张

如果 是在 根视图 重新出现的时候 改变label的话 那就在 根视图的 viewwillapperar里面写 开始设置一个 bool值,在viewDidload中 设置成No,在你离开这个界面 push到下一个界面的时候 设置成 yes,

然后 在 viewWillApperar里面 判断这个是否为 yes 如果yes就改变label

UIView是UIResponder的四大直接子类之一,是UI两大类之一。为构建完整的iOS系统知识框架,下文整理UIView的没用过的或不知道的或似懂非懂的属性和方法,并逐个吃透。目标通读 Apple api 文档。

isOpaque、tintColor、mask、isExclusiveTouch、window、isDescendant(of:)、didMoveToSuperview、didMoveToWindow、directionalLayoutMargins、layoutMargins、preservesSuperviewLayoutMargins、layoutMarginsDidChange、safeAreaInsets、safeAreaLayoutGuide、insetsLayoutMarginsFromSafeArea、constraints、addConstraint、layoutGuides、intrinsicContentSize

1、isOpaque

isOpaque属性的真实用处是给绘图系统提供一个性能优化开关!如果了解 opaque,需要点屏幕绘制的知识,屏幕上的每个像素点都是通过 RGBA 值(Red、Green、Blue 三原色再配上 Alpha 透明度)表示的,当纹理(UIView 在绘图系统中对应的表示项)出现重叠时,GPU 会按照 Result = Source + Destination (1 - SourceAlpha)公式计算重叠部分的像素。

Result 是结果 RGB 值,Source 为处在重叠顶部纹理的 RGB值,Destination 为处在重叠底部纹理的 RGB 值。

当 SourceAlpha 为 1 时,绘图系统认为下面的颜色全部被遮盖住了,Result = Source,如果 Source 的 Alpha 不为 0,上下层颜色就会进行合成,所以 opaque 默认设置 YES,提升绘制性能,如果开发中 UIView 是不透明的,opaque 设置为YES, 如果 opaque 设置NO,那么Alpha应该小于1。

总结:isOpaque是一个性能开关,=false会走混合计算逻辑R=S+D(1-SA)。alpha是一个显示属性,也会走混合计算逻辑。自定义UIView的时候在draw方法内使用,系统提供的类设置该属性无效。

思考:直接设置alpha就行了,opaque用处是什么?自定义UIView的时候在draw方法内使用,系统提供的类UILabel等设置该属性无效。

参考: UIView的 alpha、hidden、opaque属性之间的关系和区别

2、tintColor

具有传递性。举个例子,当我们用xib或者storyboard拖一个UIButton进入面板后,会发现UIButton的颜色为蓝色,可能有人会问为什么是这个颜色呢? 这是因为,默认情况下,一个视图的tintColor为nil,它会使用父视图tintColor属性的值。当我们为指定视图tintColor属性赋值以后,这个色值会自动传播到视图层次结构(以当前视图为根视图)中所有的子视图上。如果在视图层次结构中没有找到一个非默认的tintColor值,则会使用系统定义的颜色值(蓝色,RGB值为[0,0478431,1]),所以这就是为什么我们拖一个button后显示的是蓝色了。对一个视图来说, 如果没有设置它的tintColor,那么它会默认使用父视图的tintColor,如果设置了这个视图的tintColor, 那么它就会把这个tintColor传递给没有设置tintColor的所有子视图。

tintColorDidChange方法会在视图的tintColor或tintAdjustmentMode属性改变时自动调用。另外,如果当前视图的父视图的tintColor或tintAdjustmentMode属性改变时,也会调用这个方法。

模式颜色:夜间模式的颜色等

思考:用处?UIImageView使用tintColor、APP设置全局TintColor

参考: 小谈iOS UIView的tintColor属性

3、clearsContextBeforeDrawing

???

假定您的PNG始终填充整个UIImageView,则应使用以下方法获得最佳性能:opaque = YES,clearsContextBeforeDrawing = NO在此模式下,backgroundColor无关紧要像素只需替换为新的图像数据即可

对于单色背景上的透明PNG,最快的是:opaque = YES,clearsContextBeforeDrawing = YES和backgroundColor匹配您需要的任何内容在这种情况下[UIColor whiteColor]

4、mask

UIViewmask和layermask原理相同,重叠部分显示,其他部分丢掉,重叠部分,可以这样理解,是将maskView每个point的alpha赋值给View的重叠部分相对应的point,这样view的重叠每个point都有个alpha值了,view重叠部分就可能显示多种透明色。

应用:UILabel渐进式显示(歌词同步)、UIImageView部分展示(切圆角或多图阶段展示)。mask 可以配合CAGradientLayer、CAShapeLayer 使用。可以实现蒙层透明度、显示不同形状图层、图案镂空、文字变色等等功能。mask在动画中使用,可以产生很好的动画效果。

参考: UIView的 maskView 属性

5、layerClass

提供了对外的override属性,可以替换viewlayer为其他layer,如CATiledLayer 、AVPlayerLayer、TBPaperLayer等。不过可以通过另一种方式:自定义View,新加一个属性XXLayer。

layer的出现是为了mac OS 和 iOS的解耦和跨平台。

6、userInteractionEnabled

在一次动画执行流程中,动画包含的所有UIView都会被临时禁止用户交互,而不管每个UIView本身userInteractionEnabled此时的属性值是YES还是NO。但是在配置动画时,通过添加allowUserInteraction选项可以禁止这种行为的发生,使UIView即使是在执行动画期间依然能响应用户事件。userInteractionEnabled属性默认值为YES,但UIView的一些子类中对该属性进行了覆盖,并将其默认值设置为了NO,其中UIImageView和UILabel就是这样的类

7、isMultipleTouchEnabled

一个view的多指触控开关,不包含子view。不能通过设置父view=false实现两个子view不能同时点击。不影响手势。

8、isExclusiveTouch

阻止向同一window中的其他视图传递触摸事件

9、frame

frame改变将会自动重新显示,且不调用draw方法。想让调用draw方法可以设置contentMode为redraw。该属性可以动画化(alpha也可以)。如果transform包含非恒等变换时要用center和bound代替frame,否则会出问题 frame和transform的坑

10、transform

可以动画化。

改变frame的时候,不要用frame属性,用center和bound。

改anchor point的时候用CALayer的anchorPoint属性。

iOS8之后transform不能影响自动布局, AutoLayout布局与Transform的冲突

11、window

每一个view都有一个该属性,当view被add到父view上的时候,该值不在是nil,而是当前window。每个view都是事件响应者链中的一个节点,相应地,每一个节点view都有一个根节点window的引用。

12、addSubview

给next responder赋值为superview。

给window赋值。

继承父view的alpha。

view只能有一个superview,所以一个view不能加载两个view上。

13、removeFromSuperview

注意判空。

不要在视图的draw(_:)方法中调用这个方法。

14、isDescendant

是否是subview或他本身。是视图层次关系的判断。注意isMember是继承关系的判断,不一样。

15、didAddSubview

有子view才会调用。任何adding a subview 的方法都会调用该方法,默认无实现,子类可重写实现额外的 *** 作。UIView的生命周期还有willRemoveSubview、willMove(toSuperview)、didMoveToSuperview、willMove(toWindow)、didMoveToWindow等。

remove的时候也会调用didMoveToSuperview和didMoveToWindow,只是顺序不同

16、directionalLayoutMargins

iOS11之后的,考虑到当前的语言方向(阿拉伯语是从右到左)的内容布局边距。默认为8,也可自行设置。preservesSuperviewLayoutMargins是否保护父视图边距,默认false。

17、addLayoutGuide

引入UILayoutGuide系统的一系列功能性方法之一。UILayoutGuide是 iOS 9 中增加的帮助开发者在使用auto layout布局时的一个虚拟占位对象。所有需要一个虚拟View帮助的事情都可以交给UILayoutGuide来做。它更轻量、更快速、更高效。并没有真正的创建一个View,只是创建了一个矩形空间,只在进行auto layout时参与进来计算。

18、systemLayoutSizeFitting(_ targetSize: CGSize)

该方法为视图返回一个大小值,该值最优地满足视图的当前约束,并且尽可能接近targetSize参数中的值。这个方法实际上并没有改变视图的大小。参数size可以设置layoutFittingCompressedSize或layoutFittingExpandedSize获得一个尽可能小或大的size。还可以设置fittingSizeLevel或low或high的约束优先级来返回需要的最接近或高度优先或宽度优先的大小。

思考:和sizeThatFit有什么区别?可以在layout异步布局之前拿到frame吗?

用处:可以获取自动填充的静态cell的高度。可以在autolayout时拿到size(也可以用layoutIfNeeded)。

19、intrinsicContentSize

只读属性,可通过重写来更改相应控件的内置尺寸大小,告知系统值已改变。在AutoLayout中,它作为UIView的属性(不是语法上的属性),意思就是说我知道自己的大小,如果你没有为我指定大小,我就按照这个大小来。比如:大家都知道在使用AutoLayout的时候,UILabel是不用指定尺寸大小的,只需指定位置即可,就是因为,只要确定了文字内容,字体等信息,它自己就能计算出大小来。同样的UILabel,UIImageView,UIButton等这些组件及某些包含它们的系统组件都有 Intrinsic Content Size 属性,也就说他们都有自己计算size的能力。

使用场景:自定义视图重写该方法。如在MBProgressHUD添加自定义视图时,若给定视图为不确定大小的,展示出来的效果就很差强人意,这时就需要更改对应View中的内置大小来适配合适的尺寸。

invalidateIntrinsicContentSize():当自定义视图中的某些内容发生变化,使其固有内容大小失效时调用此函数。这允许基于约束的布局系统在下一个布局过程中考虑新的内在内容大小。重写intrinsicContentSize时可主动调用该方法通知系统内容大小变化了。另外还有 详解 intrinsicContentSize 及 约束优先级/content Hugging/content Compression Resistance

20、alignmentRect

Autolayout系统的布局 *** 作是基于alignment rect而非frame。绝大部分情况下它们是一样的,但是当你设置了alignmentRectInsets或者重写了alignmentRectForFrame:和frameForAlignmentRect:时就需要注意两者的差异。

alignmentRec + alignmentRectInsets = frame

forFirstBaselineLayout:使用baseLine做约束的时候autolayout会调用该方法返回的view。重写此属性以返回基于文本的子视图(例如,UILabel或非滚动的UITextView)。返回的视图必须是接收方的子视图。

应用?自定义view,重写方法返回一个view,然后设置其他基于baseline的约束

21、Debugging Auto Layout

constraintsAffectingLayout:返回影响x/y轴的视图布局的约束

hasAmbiguousLayout:视图是否有模糊(不完全确定)约束

exerciseAmbiguityInLayout:在不同的有效值之间以模糊的布局随机改变视图的约束,用于检测有效约束和必要约束

22、sizeToFit与sizeThatFits

sizeThatFits主要用于计算,返回一个最佳size,不更改view的实际大小。

sizeToFit不应该在子类中被重写,应该重写sizeThatFits,调用sizeToFit会自动调用sizeThatFits方法;

sizeToFit和sizeThatFits方法都没有递归,对subviews也不负责,只负责自己

23、setNeedsLayout

标记下一个更新周期(1/60s)中触发布局更新。由于此方法不强制立即更新,而是等待下一个更新周期,因此您可以使用它在更新任何视图之前使多个视图的布局失效。这种行为允许您将所有布局更新合并到一个更新周期中,这 通常有利于提高性能 。layoutIfNeeded:如果布局更新正在等待,则立即布局子视图。常用来在snp或masonry布局的时候获取view的frame

23、requiresConstraintBasedLayout

如果你在updateConstraints这个方法里面给自定义的控件更新控件的constraint,那么需要重写requiresConstraintBasedLayout方法,并且返回YES否则的话,就不会显示该控件直接在init方法中设置自定义控件的constraint,那么则不需要重写也可以显示。

translatesAutoresizingMaskIntoConstraints:将 frame 布局 自动转化为 约束布局,转化的结果是为这个视图自动添加所有需要的约束,如果我们这时给视图添加自己创建的约束就会约束冲突。

24、overrideUserInterfaceStyle

iOS13新增的设置light/dark模式。设置view之后会影响该view所在的vc的所有view(不包含child vc),设置window之后会影响window的所有view和vc。

semanticContentAttribute:设置左右布局翻转。一般用在语言翻转。也可用在按钮文字的左右翻转。

25、addInteraction

主要涉及UIInteraction。

UIContextMenuInteraction:iOS13可用,上下文菜单功能。如系统相册列表长按,d出一个带可 *** 作菜单的预览界面。

UIDragInteraction+UIDropInteraction:iOS11可用。在mac上可以将直接拖入聊天软件进行发送,可以将文档、音乐、视频文件等文件拖入相应应用程序直接进行使用。在iPhone上能应用内使用。iPad上能跨应用使用。

UIIndirectScribbleInteraction:iOS14可用。在ipad上使用apple pencil手写输入文本。

UILargeContentViewerInteraction:iOS13可用。在超大字体(辅助功能)的情况下,内容视图展示文案会很大,但是一些系统的bar button如tabbar item之类的仍然很小,这里提供一种补偿方式,手指按住的时候会d出一个大内容视图查看器。

UIPencilInteraction:iOS121可用。Apple Pencil 双击的处理对象

UIPointerInteraction:iOS134可用。指针交互??

UIScribbleInteraction:iOS14可用。接受或抑制手写输入文本

UISpringLoadedInteraction:iOS11可用。d簧加载交互??

UITextInteraction:iOS13可用。??

26、draw

当这个方法被调用时,UIKit已经为你的视图配置了适当的绘图环境,但是不要建立对图形上下文的强引用,因为它会在调用draw(_:)方法之间发生变化。如果你直接子类化UIView不需要调用super。如果子类化一个不同的视图类应该在你的实现中调用super。调用setNeedsDisplay方法会调用draw重新绘制。

27、viewPrintFormatter

UIViewPrintFormatter??

28、canBecomeFocused

默认值为false。此属性通知 焦点引擎 视图是否能够被聚焦。有时即使一个视图返回true,一个视图可能因为以下原因而不能被聚焦:视图是隐藏的。视图将alpha设置为0。视图将userInteractionEnabled设置为false。视图当前不在视图层次结构中。

inheritedAnimationDuration:在一个UIView animation block中获取duration的值。

29、addMotionEffect

UIMotionEffect:随着手机的倾斜微移动view

30、restorationIdentifier

视图恢复用

31、snapshotView

截图用。可用场景:添加购物车,移动交换Cel,点击放大。多window截图可以先逐个截图然后合并。直播截图是opengl实现的,要用drawHierarchy方法。

32、viewWithTag

会先遍历自己,再遍历子views。如果view和subview1是一个tag,找到的是view,而不是subview1。

33、convert(_ point

获取cell的位置。要先获取cell在列表中的位置,再获取列表在view中的位置。

34、hitTest和point(inside

返回触碰点的最佳的view。内部实现如下:

// 1判断自己能否接收触摸事件

if (selfuserInteractionEnabled == NO || selfhidden == YES || selfalpha <= 001) return nil;

// 2判断触摸点在不在自己范围内

if (![self pointInside:point withEvent:event]) return nil;

// 3从后往前遍历自己的子控件,看是否有子控件更适合响应此事件

35、endEditing(_ force)

让subviews中的first responder的文本控件失去响应

36、动画

demo和效果

总结:费劲弄完,效果甚微。很多api看了文档描述也不知道是什么效果和怎么使用。重点:效果、使用场景、demo。接下来计划-常用的大体都过下。不知道怎么使用的查外网或看wwdc。

当我们做app的时候有时候会遇到这样的需求,根视图是A一个“个人信息” 页面,点击头像会push到“个人详细信息”的B页面,当我们点击某一个详细的信息进行修改时会push到“修改信息”的C页面(或者会有详细的地区选择的D、E、F等等)。修改后我们需要Pop到B视图,然而苹果给我们提供的有两种方法:

推出到根视图控制器

- (nullable NSArray<__kindof UIViewController > )popToRootViewControllerAnimated:(BOOL)animated;

推出到指定的视图控制器

- (nullable NSArray<__kindof UIViewController > )popToViewController:(UIViewController )viewController animated:(BOOL)animated;

然而当我们直接用第二种方法时系统会“崩溃”,提示

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Tried to pop to a view controller that doesn't exist'

pop推出的视图控制器并不存在,那么我们该如何使用呢?

for (UIViewController controller in selfnavigationControllerviewControllers) {  

         if ([controller isKindOfClass:[ReviseUserInformationViewController class]]) {

ReviseUserInformationViewController revise =(ReviseUserInformationViewController )controller;

[selfnavigationController popToViewController:revise animated:YES];

          }

}

RootViewController 根视图控制器。搭积木玩过吧,类似最下面一块积木。其他视图控制器都是在这个rootviewcontroller的基础上push。最下面只能放一块积木,至于这个积木是什么颜色,你需要自己定制,这就是下面的mainViewController了。MainViewController 是你自己定制的一个控制器,你可以把这个视图控制器设置成为你的rootViewController(比如下面一块积木我可以放蓝色也可以放红色,但他们都是rootViewController)。不知道这么说你能明白不。另外建议看看《无限互联ios》开发视频,跟着做。比纠结这些有用,用几次就知道该怎么用了。

直接两个controller了啊,

[selfnavigationController pushViewController: animated:YES];推到新的view

[selfnavigationController popViewControllerAnimated:YES]退出到原来的view

注 意 : 如果父控件不能接受触摸事件,那么子控件就不可能接收到触摸事件

UIView不能接收触摸事件的三种情况:

注 意 :默认UIImageView不能接受触摸事件,因为不允许交互,即userInteractionEnabled = NO。所以如果希望UIImageView可以交互,需要设置UIImageView的userInteractionEnabled = YES。

1点击一个UIView或产生一个触摸事件A,这个触摸事件A会被添加到由UIApplication管理的事件队列中(即,首先接收到事件的是UIApplication)。

2UIApplication会从事件对列中取出最前面的事件(此处假设为触摸事件A),把事件A传递给应用程序的主窗口(keyWindow)。

3窗口会在视图层次结构中找到一个最合适的视图来处理触摸事件。(至此,第一步已完成)

如果想让某个view不能处理事件(或者说,事件传递到某个view那里就断了),那么可以通过刚才提到的三种方式。比如,设置其userInteractionEnabled = NO;那么传递下来的事件就会由该view的父控件处理。

例如,不想让蓝色的view接收事件,那么可以设置蓝色的view的userInteractionEnabled = NO;那么点击**的view或者蓝色的view所产生的事件,最终会由橙色的view处理,橙色的view就会成为最合适的view。

所以,不管视图能不能处理事件,只要点击了视图就都会产生事件,关键在于该事件最终是由谁来处理!也就是说,如果蓝色视图不能处理事件,点击蓝色视图产生的触摸事件不会由被点击的视图(蓝色视图)处理!

注意:如果设置父控件的透明度或者hidden,会直接影响到子控件的透明度和hidden。如果父控件的透明度为0或者hidden = YES,那么子控件也是不可见的!

应用如何找到最合适的控件来处理事件?

1首先判断主窗口(keyWindow)自己是否能接受触摸事件

2触摸点是否在自己身上

3从后往前遍历子控件,重复前面的两个步骤(首先查找数组中最后一个元素)

4如果没有符合条件的子控件,那么就认为自己最合适处理

详述:1主窗口接收到应用程序传递过来的事件后,首先判断自己能否接手触摸事件。如果能,那么在判断触摸点在不在窗口自己身上

2如果触摸点也在窗口身上,那么窗口会从后往前遍历自己的子控件(遍历自己的子控件只是为了寻找出来最合适的view)

3遍历到每一个子控件后,又会重复上面的两个步骤(传递事件给子控件,1判断子控件能否接受事件,2点在不在子控件上)

4如此循环遍历子控件,直到找到最合适的view,如果没有更合适的子控件,那么自己就成为最合适的view。

找到最合适的view后,就会调用该view的touches方法处理具体的事件。所以,只有找到最合适的view,把事件传递给最合适的view后,才会调用touches方法进行接下来的事件处理。找不到最合适的view,就不会调用touches方法进行事件处理。

注意:之所以会采取从后往前遍历子控件的方式寻找最合适的view只是为了做一些循环优化。因为相比较之下,后添加的view在上面,降低循环次数。

两个重要的方法:

hitTest:withEvent: 方法

pointInside 方法

什么时候调用?

作用

注 意 :不管这个控件能不能处理事件,也不管触摸点在不在这个控件上,事件都会先传递给这个控件,随后再调用hitTest:withEvent:方法

拦截事件的处理

事件传递给谁,就会调用谁的hitTest:withEvent:方法。

注 意 :如果hitTest:withEvent:方法中返回nil,那么调用该方法的控件本身和其子控件都不是最合适的view,也就是在自己身上没有找到更合适的view。那么最合适的view就是该控件的父控件。

所以事件的传递顺序是这样的:

产生触摸事件->UIApplication事件队列->[UIWindow hitTest:withEvent:]->返回 更合适 的view->[子控件 hitTest:withEvent:]->返回 最合适 的view

事件传递给窗口或控件的后,就调用hitTest:withEvent:方法寻找更合适的view。所以是,先传递事件,再根据事件在自己身上找更合适的view。

不管子控件是不是最合适的view,系统默认都要先把事件传递给子控件,经过子控件调用子控件自己的hitTest:withEvent:方法验证后才知道有没有更合适的view。即便父控件是最合适的view了,子控件的hitTest:withEvent:方法还是会调用,不然怎么知道有没有更合适的!即,如果确定最终父控件是最合适的view,那么该父控件的子控件的hitTest:withEvent:方法也是会被调用的。

技巧: 想让谁成为最合适的view就重写谁自己的父控件的hitTest:withEvent:方法返回指定的子控件,或者重写自己的hitTest:withEvent:方法 return self。但是, 建议在父控件的hitTest:withEvent:中返回子控件作为最合适的view!

原因 在于在自己的hitTest:withEvent:方法中返回自己有时候会出现问题。因为会存在这么一种情况:当遍历子控件时,如果触摸点不在子控件A自己身上而是在子控件B身上,还要要求返回子控件A作为最合适的view,采用返回自己的方法可能会导致还没有来得及遍历A自己,就有可能已经遍历了点真正所在的view,也就是B。这就导致了返回的不是自己而是触摸点真正所在的view。所以还是建议在父控件的hitTest:withEvent:中返回子控件作为最合适的view!

例如: whiteView有redView和greenView两个子控件。redView先添加,greenView后添加。如果要求无论点击那里都要让redView作为最合适的view(把事件交给redView来处理)那么只能在whiteView的hitTest:withEvent:方法中return selfsubViews[0];这种情况下在redView的hitTest:withEvent:方法中return self;是不好使的!

特殊情况:

谁都不能处理事件,窗口也不能处理。

只能有窗口处理事件。

return nil的含义:

hitTest:withEvent:中return nil的意思是调用当前hitTest:withEvent:方法的view不是合适的view,子控件也不是合适的view。如果同级的兄弟控件也没有合适的view,那么最合适的view就是父控件。

寻找最合适的view底层剖析之hitTest:withEvent:方法底层做法

/ hitTest:withEvent:方法底层实现/

hit:withEvent:方法底层会调用pointInside:withEvent:方法判断点在不在方法调用者的坐标系上。

pointInside:withEvent:方法判断点在不在当前view上(方法调用者的坐标系上)如果返回YES,代表点在方法调用者的坐标系上;返回NO代表点不在方法调用者的坐标系上,那么方法调用者也就不能处理事件。

屏幕上现在有一个viewA,viewA有一个subView叫做viewB,要求触摸viewB时,viewB会响应事件,而触摸viewA本身,不会响应该事件。如何实现?

1>用户点击屏幕后产生的一个触摸事件,经过一系列的传递过程后,会找到最合适的视图控件来处理这个事件2>找到最合适的视图控件后,就会调用控件的touches方法来作具体的事件处理touchesBegan…touchesMoved…touchedEnded…3>这些touches方法的默认做法是将事件顺着响应者链条向上传递(也就是touch方法默认不处理事件,只传递事件),将事件交给上一个响应者进行处理

响应者链条: 在iOS程序中无论是最后面的UIWindow还是最前面的某个按钮,它们的摆放是有前后关系的,一个控件可以放到另一个控件上面或下面,那么用户点击某个控件时是触发上面的控件还是下面的控件呢,这种先后关系构成一个链条就叫“响应者链”。也可以说,响应者链是由多个响应者对象连接起来的链条。在iOS中响应者链的关系可以用下图表示:

响应者对象: 能处理事件的对象,也就是继承自UIResponder的对象

作用: 能很清楚的看见每个响应者之间的联系,并且可以让一个事件多个对象处理。

如何判断上一个响应者

响应者链的事件传递过程:

事件处理的整个流程总结:

1触摸屏幕产生触摸事件后,触摸事件会被添加到由UIApplication管理的事件队列中(即,首先接收到事件的是UIApplication)。

2UIApplication会从事件队列中取出最前面的事件,把事件传递给应用程序的主窗口(keyWindow)。

3主窗口会在视图层次结构中找到一个最合适的视图来处理触摸事件。(至此,第一步已完成)

4最合适的view会调用自己的touches方法处理事件

5touches默认做法是把事件顺着响应者链条向上抛。

touches的默认做法:

事件的传递与响应:

1、当一个事件发生后,事件会从父控件传给子控件,也就是说由UIApplication -> UIWindow -> UIView -> initial view,以上就是事件的传递,也就是寻找最合适的view的过程。

2、接下来是事件的响应。首先看initial view能否处理这个事件,如果不能则会将事件传递给其上级视图(inital view的superView);如果上级视图仍然无法处理则会继续往上传递;一直传递到视图控制器view controller,首先判断视图控制器的根视图view是否能处理此事件;如果不能则接着判断该视图控制器能否处理此事件,如果还是不能则继续向上传 递;(对于第二个图视图控制器本身还在另一个视图控制器中,则继续交给父视图控制器的根视图,如果根视图不能处理则交给父视图控制器处理);一直到 window,如果window还是不能处理此事件则继续交给application处理,如果最后application还是不能处理此事件则将其丢弃

3、在事件的响应中,如果某个控件实现了touches方法,则这个事件将由该控件来接受,如果调用了[supertouches…];就会将事件顺着响应者链条往上传递,传递给上一个响应者;接着就会调用上一个响应者的touches…方法

如何做到一个事件多个对象处理:

因为系统默认做法是把事件上抛给父控件,所以可以通过重写自己的touches方法和父控件的touches方法来达到一个事件多个对象处理的目的。

事件的传递和响应的区别:

事件的传递是从上到下(父控件到子控件),事件的响应是从下到上(顺着响应者链条向上传递:子控件到父控件。

以上就是关于ios 使用uinavigationcontroller 作为根视图好吗全部的内容,包括:ios 使用uinavigationcontroller 作为根视图好吗、iOS心法-UIView、iOS如何pop到指定页面等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址:https://www.54852.com/web/9402713.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2023-04-28
下一篇2023-04-28

发表评论

登录后才能评论

评论列表(0条)

    保存