自动化测试 ios 怎么找到代码写的控件

自动化测试 ios 怎么找到代码写的控件,第1张

我知道自己可以用xcode建立一个工程。然后运行就好了 UIButton butt = [UIButton buttonWithType:UIButtonTypeCustom]; buttframe = CGRectMake(100, 100, 50, 50); [butt setTitle:@"哈哈哈" forState:UIControlStateNormal]; [butt setTitle

第一种:通过人为的办法改变viewtransform的属性。

具体办法:

viewtransform一般是View的旋转,拉伸移动等属性,类似viewlayertransform,区别在于 Viewtransform是二维的,也就是使用仿射的办法通常就是带有前缀CGAffineTransform的类(可以到API文档里面搜索这个前 缀的所有类),而viewlayertransform可以在3D模式下面的变化,通常使用的都是前缀为CATransform3D的类。

这里要记住一点,当你改变过一个viewtransform属性或者viewlayertransform的时候需要恢复默认状态的话,记得先把他 们重置可以使用viewtransform = CGAffineTransformIdentity,或者viewlayertransform = CATransform3DIdentity,假设你一直不断的改变一个viewtransform的属性,而每次改变之前没有重置的话,你会发现后来 的改变和你想要的发生变化了,不是你真正想要的结果。

好了,上面介绍了旋转的属性,接下来就是关键了。官方提供了一个办法就是查看当前电池条的状态UIInterfaceOrientation orientation = [UIApplication sharedApplication]statusBarOrientation;通过这个办法,你可以知道当前屏幕的电池条的显示方向,而且你还可以 强制设置他的显示方向,通过设置这个属性就OK了,可以选择是否动画改变电池条方向。有了这两个那我们就可以任意的改变我们想要的显示方式了。

1获取当前电池条的方向UIInterfaceOrientation orientation = [UIApplication sharedApplication]statusBarOrientation

2获取当前屏幕的大小CGRect frame = [UIScreen mainScreen]applicationFrame;

3设置我们的View的中心点

CGPoint center = CGPointMake(frameoriginx + ceil(framesizewidth/2), frameoriginy + ceil(framesizeheight/2));

4根据当前电池条的方向,获取需要旋转的角度的大小。通常

if (orientation == UIInterfaceOrientationLandscapeLeft) {

return CGAffineTransformMakeRotation(M_PI15);

} else if (orientation == UIInterfaceOrientationLandscapeRight) {

return CGAffineTransformMakeRotation(M_PI/2);

} else if (orientation == UIInterfaceOrientationPortraitUpsideDown) {

return CGAffineTransformMakeRotation(-M_PI);

} else {

return CGAffineTransformIdentity;

}

5可以动画的改变我们view的显示方式了

[[UIApplication sharedApplication] setStatusBarOrientation:UIDeviceOrientationLandscapeRight animated:YES];

CGFloat duration = [UIApplication sharedApplication]statusBarOrientationAnimationDuration;(获取当前电池条动画改变的时间)

[UIView beginAnimations:nil context:nil];

[UIView setAnimationDuration:duration];

//在这里设置viewtransform需要匹配的旋转角度的大小就可以了。

[UIView commitAnimations];

第二种:通过setOrientation:的办法强制性的旋转到一个特定的方向。

注意:Apple在30以后都不支持这个办法了,这个办法已经成为了私有的了,但是要跳过App Stroe的审核,需要一点巧妙的办法。

不要直接调用[[UIDevice currentDevice] setOrientation: UIInterfaceOrientationLandscapeRight]这样的办法来强制性的横屏,这样导致你的程序是很难通过App Store审核的。但是你可以选择使用performSelector的办法来调用它。具体就几行代码如下:

//强制横屏

if ([[UIDevice currentDevice] respondsToSelector:@selector(setOrientation:)]) {

[[UIDevice currentDevice] performSelector:@selector(setOrientation:)

withObject:(id)UIInterfaceOrientationLandscapeRight];

}

总结:如果第一种办法可以满足你需要的话,最好使用第一种办法,因为那个上 App Store肯定没问问题,但是第二种的话是需要冒风险的,但是如果你的结构太复杂了,导致使用第一种办法人为很难控制的话,可以尝试简单的使用第二种办 法。我在有米提供的sample里面就看到他使用了第二种简单的办法来显示横屏竖式的广告条。

因为初学iOS开发,对于layoutSubviews、drawRect等方法何时调用并不是了解得很透彻

所以在此记录一下,每当有新的发现都会在此更新,相信假以时日

这篇记录文能够产生丰富的内容以供我日后开发时的参考

本文章不设大小标题,仅以序号作为排版

iOS layout机制相关方法

- (CGSize)sizeThatFits:(CGSize)size

- (void)sizeToFit

——————-

- (void)layoutSubviews

- (void)layoutIfNeeded

- (void)setNeedsLayout

——————–

- (void)setNeedsDisplay

- (void)drawRect

--------------------

layoutSubviews在以下情况下会被调用:

1、init初始化不会触发layoutSubviews

但是是用initWithFrame 进行初始化时,当rect的值不为CGRectZero时,也会触发

2、当使用[self setNeedsDisplay]时会调用drawRect

3、当使用[self addSubview]会触发layoutSubviews

4、设置view的Frame会触发layoutSubviews,当然前提是frame的值设置前后发生了变化

5、改变一个UIView大小的时候也会触发父UIView上的layoutSubviews事件

6、滚动一个UIScrollView会触发layoutSubviews

7、旋转Screen会触发父UIView上的layoutSubviews事件

刷新子对象布局

-layoutSubviews方法:这个方法,默认没有做任何事情,需要子类进行重写

-setNeedsLayout方法: 标记为需要重新布局,异步调用layoutIfNeeded刷新布局,不立即刷新,但layoutSubviews一定会被调用

-layoutIfNeeded方法:如果,有需要刷新的标记,立即调用layoutSubviews进行布局(如果没有标记,不会调用layoutSubviews)

如果要立即刷新,要先调用[view setNeedsLayout],把标记设为需要布局,然后马上调用[view layoutIfNeeded],实现布局

在视图第一次显示之前,标记总是“需要刷新”的,可以直接调用[view layoutIfNeeded]

---------------------------------------

重绘

-drawRect:(CGRect)rect方法:重写此方法,执行重绘任务

-setNeedsDisplay方法:标记为需要重绘,异步调用drawRect

-setNeedsDisplayInRect:(CGRect)invalidRect方法:标记为需要局部重绘

sizeToFit会自动调用sizeThatFits方法;

sizeToFit不应该在子类中被重写,应该重写sizeThatFits

sizeThatFits传入的参数是receiver当前的size,返回一个适合的size

sizeToFit可以被手动直接调用

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

----------------------------------------

layoutSubviews对subviews重新布局

layoutSubviews方法调用先于drawRect

setNeedsLayout在receiver标上一个需要被重新布局的标记,在系统runloop的下一个周期自动调用layoutSubviews

layoutIfNeeded方法如其名,UIKit会判断该receiver是否需要layout根据Apple官方文档,layoutIfNeeded方法应该是这样的

layoutIfNeeded遍历的不是superview链,应该是subviews链

drawRect是对receiver的重绘,能获得context

setNeedDisplay在receiver标上一个需要被重新绘图的标记,在下一个draw周期自动重绘,iphone device的刷新频率是60hz,也就是1/60秒后重绘

1发生触摸事件后,系统会将该事件加入到一个由UIApplication管理的队列事件中

2UIApplication会从事件队列中取出最前面的事件,并将事件分发下去以便处理,通常会先发送事件给应用程序的主窗口(keyWindow)

3主窗口会在视图层次结构中找到一个最合适的视图来处理触摸事件

事件的具体传递过程,如图:

一般事件的传递是从父控件传递到子控件的

例如:

点击了绿色的View,传递过程如下:UIApplication->Window->白色View->绿色View

点击蓝色的View,传递过程如下:UIApplication->Window->白色View->橙色View->蓝色View

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

应用如何找到最合适的控件来处理事件?有以下准则

详述:

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

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

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

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

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

寻找最合适的view过程,如图:

这里点击了橙色的那块区域,事件传递判断过程如下:

1UIApplication从事件队列中取出事件分发给UIWindow

2UIWindow判断自己是否能接受触摸事件,可以

3UIWindow判断触摸点是否在自己身上,是的。

4UIWindow从后往前便利自己的子控件,取出白1(aUIWindow的子控件只有一个,那就是白1)

5白1都满足最上面两个条件,遍历子控件橙2

特别说明:

( a白1的子控件有两个,绿2和橙2 )

( b添加顺序是,先添加绿2,后添加橙2 )

( c根据后添加的子控件先遍历的原则,肯定是先遍历橙2子控件 )

6橙2都满足最上面两个条件,遍历子控件,先取出红3

( a橙2的子控件有两个,蓝3和红3,注意黄4不属于橙2的子控件而是蓝3的子控件 )

( b添加顺序是,先添加蓝3,后添加红3 )

( c根据后添加的子控件先遍历的原则,肯定是先遍历红3子控件 )

7红3不满足条件2,取出蓝3

8蓝3也不满足条件2,最后最合适的控件是橙2

寻找合适的View用到两个重要方法:

什么时候调用?

只要事件一传递给一个控件,这个控件就会调用他自己的hitTest:withEvent:方法寻找合适的View

作用

寻找并返回最合适的view(能够响应事件的那个最合适的view)

注 意:不管这个控件能不能处理事件,也不管触摸点在不在这个控件上,

事件都会先传递给这个控件,随后再调用hitTest:withEvent:方法

hitTest:withEvent:底层调用流程:

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

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

以上是事件传递的顺序:

上文介绍了事件的传递过程,找到合适的View之后就会调用该view的touches方法要进行响应处理具体的事件,找不到最合适的view,就不会调用touches方法进行事件处理。

这里先介绍一下响应者链条:响应者链条其实就是很多响应者对象(继承自UIResponder的对象)一起组合起来的链条称之为响应者链条

一般默认做法是控件将事件顺着响应者链条向上传递,将事件交给上一个响应者进行处理 (即调用super的touches方法)。

那么如何判断当前响应者的上一个响应者是谁呢?有以下两个规则:

1判断当前是否是控制器的View,如果是控制器的View,上一个响应者就是控制器

2如果不是控制器的View,上一个响应者就是父控件

响应过程如下图:

touch响应:

如果控制器也不响应响应touches方法,就交给UIWindow。如果UIWindow也不响应,交给UIApplication,如果都不响应事件就作废了。

最后总结来说一次完整的触摸事件的传递响应过程为:

UIApplication-->UIWindow-->递归找到最合适处理的控件-->控件调用touches方法-->判断是否实现touches方法-->没有实现默认会将事件传递给上一个响应者-->找到上一个响应者-->找不到方法作废

一句话总结整个过程是:触摸或者点击一个控件,然后这个事件会从上向下(从父->子)找最合适的view处理,找到这个view之后看他能不能处理,能就处理,不能就按照事件响应链向上(从子->父)传递给父控件

额外添加:

有了响应网为基础,事件的传递就比较简单,只需要选择其中一条响应链,但是选择那一条响应链来传递呢?为了弄清真个过程,我们先来查看一下从触摸硬件事件转化为UIEvent消息。

首先用户触摸屏幕,系统的硬件进程会获取到这个点击事件,将事件简单处理封装后存到系统中,由于硬件检测进程和当前运行的APP是两个进程,所以进程两者之间传递事件用的是端口通信。硬件检测进程会将事件放入到APP检测的那个端口。

其次,APP启动主线程RunLoop会注册一个端口事件,来检测触摸事件的发生。当时事件到达,系统会唤起当前APP主线程的Runloop。唤起原因就是端口触摸事件,主线程会分析这个事件。

最后,系统判断该次触摸是否导致了一个新的事件, 也就是说是否是第一个手指开始触碰,如果是,系统会先从响应网中 寻找响应链。如果不是,说明该事件是当前正在进行中的事件产生的一个Touch message, 也就是说已经有保存好的响应链。

ios 怎么获取一个view的位置

打开appstore进入应用,右上角的分享按钮(从右往左数第二个),拷贝连接即可。如下图:

如何获取一个view在布局中的位置

public View getViewByPosition(int pos, ListView listView) {

final int firstListItemPosition = listViewgetFirstVisiblePosition();

final int lastListItemPosition = firstListItemPosition + listViewgetChildCount() - 1;

if (pos < firstListItemPosition || pos > lastListItemPosition ) {

return listViewgetAdapter()getView(pos, null, listView);

} else {

final int childIndex = pos - firstListItemPosition;

return listViewgetChildAt(childIndex);

}

} 已解决,通过这个方法就可以实现了获取item中的view

如何获取一个uicollectionviewcell的位置

UICollectionViewCell cell = (UICollectionViewCell )[collectionView

cellForItemAtIndexPath:indexPath];一句话就能获取到点击cell的frame,十分好用,同样适用于tableView。

ios中怎么获取collectionview中cell的位置

你在点击cell的时候调用 - (void)performSegueWithIdentifier:(NSString )identifier sender:(id)sender ;

那不是有个sender嘛,你可以给它传值。

然后在-(void)prepareForSegue:(UIStoryboardSegue )segue sender:(id)sender 里的sender,就是你刚传的那个值。

Flash中怎么通过代码来获取一个左上、右下的位置,_x和_y只能获取图像原点的位置。

设左上坐标(x1,y1),右下坐标(x2,y2),原点坐标(x0,y0),元件名称为mcPic,则:

x1 = mcPicx - mcPicwidth/2

y1 = mcPicy - mcPicheight/2

x2 = mcPicx + mcPicwidth/2

y2 = mcPicy + mcPicheight/2

x0 = mcPicx

y0 = mcPicy

怎样通过qq获取一个人的位置信息

除了使用者本人定位,其他人无法获取,这属于隐私保护

android 怎么获取ActionBar上某个menu的位置

Android 30以上的手机默认是不显示溢出菜单的,那如何强制在Android 44以下的手机显示溢出菜单呢?可以使用以下方法:

[java] view plaincopy在CODE上查看代码片派生到我的代码片

强制actionbar显示overflow菜单

适配类似魅族手机无法显示溢出菜单的解决方案

上面已经解决了如何在Android 44以下的手机强制显示溢出菜单,下面来解决一些奇葩手机无法显示溢出菜单的问题。为什么魅族手机无法显示,了解到的是魅族没有所谓的actionbar,它们称为 artbar,看来是魅族的工程师把官方的actionbar进行了修改。一个字,坑!不过小巫想到了一个解决办法,我们每部手机都有自己的手机品牌,我们可以针对这些奇葩手机进行适配,溢出菜单我们就使用popupwindow来替代。

MATLAB中,怎么获取一个向量中最大的N个元素,并获取它们所在的位置

v=rand(1,5)

[mv mi]=max(v)

%mv为最大值,mi为最大值索引,v(mi)=mv

[sv si]=sort(v,2,'descend')

%si为从大到小的序列,比如要去最大的3个数就是v(si(1:3))

ios地图定位怎么获取两个点之间的位置

通常我们在手机端打开百度地图后,客户端会自动对我们所处的位置进行定位的。如果没有进行定位的话,你可以点击地图页面的左下角的圆形图标,见下图红色框中所示,点击之后会自动更新,并且显示定位的地址信息。

VBS中如何获取一个数组中最大值的位置

以下VBS脚本可以实现这个功能:

Public Function getArrMaxValueIndex(ByVal arr)

Dim ix, ixMax

ixMax = 0

For ix = 1 To UBound(arr)

If ( arr(ixMax) < arr(ix) ) Then

ixMax = ix

End If

Next

getArrMaxValueIndex = ixMax

End Function

'Define array and index for max entry

Dim arr, ixMax

'Initialize the array

arr = Array(4, 1, 8, 6, 3,6)

'Get the index of the max value

ixMax = getArrMaxValueIndex(arr)

'Print result

MsgBox "Max value: " & arr(ixMax) & " was found at " & ixMax & " index"

查了一下, 觉得既然是statusBar在接受事件, 那么, 我们想在程序里实现, 肯定也要从statusBar这个对象入手, 可是API里没有地方下手 于是, 我就觉得, 这个功能是不是iOS系统提供的 但是对开发者隐藏了呢

在什么地方d出的alertView? 你有此一问,应该不是在appDelegate中吧。如果是那样的话,只能是递归遍历来找了

UIAlertView myAlert;

-(void)findAlertView:(UIView view) {

NSArray subViews = [view subViews];

for (UIView sView in subViews) {

if ([sView isKindOfClass:[UIAlertView class]]) {

myAlert =(UIAlertView )sView;

break;

}else {

[self findAlertView:sView];

}

}

}

在AppDelegate 中调用

[self findAlertView:selfwindow];

BOOL值 isShow直接标记,添加到superView时,isShow = YES,从superView移除时,isShow = NO。

某些情况下,需判断当前ViewController是否正在显示,比如后台网络请求报错,我们可能只希望在发起请求的页面d窗提示用户,当用户已经跳转到其他界面,不做d窗,减少对用户的干扰。

假如一个UIView对象当前正在显示,那么它的window属性肯定为非空值。虽然官方文档未说明UIView未显示时window属性的取值, 但是经过简单的测试,大部分情况下UIView未显示时,window的值为空,因此依据此判断当前UIViewController是否正在显示。

其原理是将两个view的坐标convert 到相对于同一个view的坐标,再对比

以上就是关于自动化测试 ios 怎么找到代码写的控件全部的内容,包括:自动化测试 ios 怎么找到代码写的控件、ios开发xcode6 ipad横竖屏怎么判断,怎么自适应控件、关于iOS自定义控件调用回显方法的一些记录(持续更新)等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

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

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

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

发表评论

登录后才能评论

评论列表(0条)

    保存