swift封装打印函数
1 | let dateFormatter = DateFormatter() |
打印对象地址
1 | extension String { |
使用
1 | DLog(self) |
打印如下:
1 | 2019-02-27 11:58:57.378 |
1 | let dateFormatter = DateFormatter() |
1 | extension String { |
1 | DLog(self) |
打印如下:
1 | 2019-02-27 11:58:57.378 [ViewController.swift:30][viewDidAppear]<demo.ViewController: 0x1059c2170> |
方法说明:
该方法在iOS 5.1及更低版本上不执行任何操作。 否则,该方法将使用你设置的约束来确定子视图的大小和位置。
该方法由layoutIfNeeded
自动调用,所以我们不能手动去调用它.在需要重新布局子视图时,可以调用[self layoutIfNeeded]
或[self setNeedLayout];
调用[self layoutIfNeeded]
或[self setNeedLayout];
layoutIfNeeded
与setNeedLayout
的区别:
调用 layoutIfNeeded
会马上执行 layoutSubviews
方法,立即更新视图的布局。但是调用setNeedLayout
并不会马上执行layoutSubviews
,而是等到runloop结束时调用.
如果一个viewA还没有被添加到父视图上面去,那么无论你对它进行什么操作(设置frame,添加子视图等等),它的layoutSubviews
方法始终是不会被调用的.
动画-layoutIfNeeded
父控制器的self.view,子控制器的子视图如果重写了-layoutSubviews
也将动画布局.
需求:导航栏根据子VC的tableview的位移动画.
1 | if (contentOffsetY > 0) { |
由于需要动画的改变父控制器里的view位移,又因为使用了xib,所以动画时需要在动画block里写[self.view layoutIfNeeded];
但这句代码导致了子控制器的视图的-layoutSubviews
方法被调用.于是子控制器的视图在布局时也会动画的进行(而这种效果不是你需要的从而变成了bug.)
这里的bug就是:子控制器里的tableViewCell因为重写了-layoutSubviews
,而cell上的子控件KDGMatchDetailItemView
也重写了-layoutSubviews
.所以KDGMatchDetailItemView
在布局时出现动画的往右移动.
解决办法:当导航栏收缩后,就不要执行[self.view layoutIfNeeded];
加个判断条件:
1 | if (contentOffsetY > 0 && self.contentScrollView.contentInset.top != -endY) { |
系统的-layoutIfNeeded
的实现应该是调用了视图的-layoutSubviews
方法.父视图-layoutSubviews
方法的调用可能会引起子视图-layoutSubviews
方法的调用.
NexT is a high quality elegant Jekyll theme ported from Hexo Next. It is crafted from scratch, with love.
之前做过一个视频信息列表展示的模块,cell很简单就是左边图片,右边文字信息。当时用的SDWebImage加载图片并没有看到图片错乱的情况。但是,如果是自己写的图片下载器,不注意处理是会导致图片错乱的。
今天写了个Demo,验证及解决这个问题。
实验环境:cell依然是左边图片,右边文字信息。图片两张,一张大图片A(风景),一张小图片B(人物),采用自己实现的原始图片下载器异步下载,block里回调设置cell的图片。要求偶数行的图片是风景,奇数行的图片是人物。
整个界面期望如下:
但实际可能出现bug,如下图:
cell上的数据错乱显然是由于cell的重用导致的。由于图片是异步下载的,下载完成才给cell设置,但是在这个过程中用户可能会上下滑动,滑动的时候会导致cell的重用,比如第0行是设置大图片的,第11行是设置小图片的,用户在滑动的过程中,因为cell的重用第11行的cell可能使用的是第0行的cell,这时第0行的block回调设置的cell和第11行的block回调设置的cell是同一个,即cell的重用导致两个block回调时设置的其实是同一个cell上的imageView。这就是问题的关键。
因为图片是异步下载的,你也不知道哪个block会先回调,如果小图片的block先回调那么这个cell的图片就先被设置为小图片,如果后来大图片的block回来了,那么你会看到图片被替换成大图片,这种情况还算比较好,但如果大图片下载失败或者小图片的block最后回调,那么你看到的将是小图片加大图片的文字信息,这时数据就错乱了。
如果不重用cell,当然是可以解决该问题的,但是内存肯定会浪费不少。
解决的方案有两种:
方案一:在下载完成的回调里进行区分,如果不一致则不设置imageView。
OC的变量:
OC有4种基本数据类型:char,int,float,double。它们又有一些限定词:signed,unsigned,short,long,long long。
实例变量和成员变量是一个概念。
@property指令作用:声明了一个属性及属性的两个访问器方法。
如果在@implementation块里@synthesize和@dynamic都没写,那么编译器会帮你自动添加@syntheszie property = _property;有一种情况除外:子类属性和父类属性同名.此时会报警告:
“Auto property synthesis will not synthesize property ‘delegate’; it will be implemented by its superclass, use @dynamic to acknowledge intention”
这个时候就需要自己实现属性了.两种常用解决办法:
1 | 1.@dynamic delegate; //表示使用父类的实现,此时子类内部将无法访问_delegate. |