CoreAnimation示例
CABasicAnimation* folat = [CABasicAnimation animationWithKeyPath:@"opacity"];
folat.fillMode = kCAFillModeBackwards;
folat.duration = 0.5;
folat.beginTime = CACurrentMediaTime()+1.1;
folat.fromValue = @(0);
folat.toValue = @(1);
[v1.layer addAnimation:folat forKey:nil];
-(void)animateLocate:(UIImageView*)view{
float speed = 10.0/self.view.bounds.size.width;
float dur = (self.view.bounds.size.width-view.frame.origin.x)*speed;
[UIView animateWithDuration:dur delay:0.1 options:UIViewAnimationOptionCurveEaseOut animations:^{
CGRect rc = view.frame;
rc.origin.x = self.view.bounds.size.width;
view.frame = rc;
} completion:^(BOOL fin){
CGRect rc = view.frame;
rc.origin.x = 0;
view.frame = rc;
[self animateLocate:view];
}];
}
Masonry的使用
我希望两个等宽高的红色方块能够在屏幕旋转的时候,间距等比例缩放,它们的相对位置是固定的,绝对位置随着屏幕的宽改变而改变
//代码中View的顺序与图中从左到右的View的顺序一致
//例子中,唯一不确定的就是灰色View的宽度,我们先把确定的约束给一个一个的添加上来
//灰1左间距、高度、垂直位置(因为和红1底部对齐)是确定的,添加约束
[gray1 mas_makeConstraints:^(MASConstraintMaker *make{
make.height.mas_equalTo(20); make.leading.equalTo(self.view.mas_leading).offset(0);
make.bottom.equalTo(red1.mas_bottom); }];
//红1,宽高、左间距、底间距是确定的,添加约束
[red1 mas_makeConstraints:^(MASConstraintMaker *make) {
make.width.mas_equalTo(100); make.height.mas_equalTo(50); make.left.equalTo(gray1.mas_right);
make.bottom.equalTo(self.view.mas_bottom).offset(-50); }];
//灰2,左间距、高度、垂直位置是确定的,宽度要与灰1一致,是为了能均匀填充,添加约束
[gray2 mas_makeConstraints:^(MASConstraintMaker *make) {
make.height.and.width.equalTo(gray1); make.leading.equalTo(red1.mas_right);
make.bottom.equalTo(red1.mas_bottom); }];
//红2,宽高、左间距、底间距是确定的,添加约束
[red2 mas_makeConstraints:^(MASConstraintMaker *make) {
make.height.and.width.equalTo(red1); make.leading.equalTo(gray2.mas_right);
make.bottom.equalTo(red1.mas_bottom); }];
//灰3,左间距、右间距、高度、垂直位置是确定的,添加约束
[gray3 mas_makeConstraints:^(MASConstraintMaker *make) {
make.height.and.width.equalTo(gray1); make.leading.equalTo(red2.mas_right);
make.trailing.equalTo(self.view.mas_right); make.bottom.equalTo(red1.mas_bottom); }];
其中 ,make.left.equalTo(redView.mas_right).offset(20).priority(250);
priority设置优先级,默认是1000,此场景用于中间的控件可能被隐藏或移除的情况
Runloop Mode
NSDefaultRunLoopMode
UITrackingRunLoopModes
NSRunLoopCommonModes
performSelector关于内存管理的执行原理是这样的执行 [self performSelector:@selector(method1:) withObject:self.tableLayer afterDelay:3]; 的时候,系统会将tableLayer的引用计数加1,执行完这个方法时,还会将tableLayer的引用计数减1,由于延迟这时tableLayer的引用计数没有减少到0,也就导致了切换场景dealloc方法没有被调用,出现了内存泄露。
利用如下函数:[NSObject cancelPreviousPerformRequestsWithTarget:self]
A repeating timer reschedules itself based on the scheduled firing time, not the actual firing time. For example, if a timer is scheduled to fire at a particular time and every 5 seconds after that, the scheduled firing time will always fall on the original 5 second time intervals, even if the actual firing time gets delayed. If the firing time is delayed so far that it passes one or more of the scheduled firing times, the timer is fired only once for that time period; the timer is then rescheduled, after firing, for the next scheduled firing time in the future.
注意:NSTimer使用最好加到主线程runloop中去,并且使用NSRunLoopCommonModes
关于library ,framework & CocoaPod
You may be wondering, “What’s the difference between a library, a framework and a CocoaPod?” And trust me, it’s okay if you find the whole thing a touch confusing!
A CocoaPod, or “pod” for short, is a general term for either a library or framework that’s added to your project by using the CocoaPods tool.
iOS 8 introduced dynamic frameworks, and these allow code, images and other assets to be bundled together. Prior to iOS 8, CocoaPods were created as static libraries, which are just “fat” binaries. This means they contain several code instruction sets (e.g. i386 for the simulator, armv7 for devices, etc.), but they aren’t allowed to contain any resources such as images or assets.
Another important difference is dynamic frameworks have namespace classes and static libraries don’t. So, if you had two classes called MyTestClass in different static libraries within a single project, Xcode would not be able to build the project because it would fail to link correctly citing duplicate symbols. However, Xcode is perfectly happy building a project that has two classes with the same name in different frameworks.
Why does this matter? Unlike Objective-C, the standard Swift runtime libraries aren’t included in iOS! This means your framework must include the necessary Swift runtime libraries. As a consequence, pods written in Swift must be created as dynamic frameworks. If Apple allowed Swift static libraries, it would cause duplicate symbols across different libraries that use the same standard runtime dependencies.
Alcatraz
在xcode8+安装如下:
sudo gem install update_xcode_plugins
update_xcode_plugins 先备份xcode 然后
update_xcode_plugins --unsign 得到unsigned xcode
安装Alcatraz后,推荐使用插件
FuzzyAutoComplete 编码提示
VVDocumenter-Xcode 快速注释
KSImageNamed imagenamed 快捷找到图片资源
instruments使用time profiler注意事项
1.当点击Time Profiler应用程序开始运行后.就能获取到整个应用程序运行消耗时间分布和百分比.为了保证数据分析在统一使用场景真实行有如下点需要注意:
在开始进行应用程序性能分析的时候,一定要使用真机,模拟器运行在Mac上,然而Mac上的CPU往往比iOS设备要快。相反,Mac上的GPU和iOS设备的完全不一样,模拟器不得已要在软件层面(CPU)模拟设备的GPU,这意味着GPU相关的操作在模拟器上运行的更慢,尤其是使用CAEAGLLayer来写一些OpenGL的代码时候. 这就导致模拟器性能数据和用户真机使用性能数据相去甚远.
2.另外在开始性能分析前另外一件重要的事情是,应用程序运行一定要发布配置 而不是调试配置.
在发布环境打包的时候,编译器会引入一系列提高性能的优化,例如去掉调试符号或者移除并重新组织代码.另iOS引入一种"Watch Dog"[看门狗]机制.不同的场景下,“看门狗”会监测应用的性能。如果超出了该场景所规定的运行时间,“看门狗”就会强制终结这个应用的进程.开发者可以crashlog看到对应的日志.但Xcode在调试配置下会禁用"Watch Dog"
几种配置可选项:
Separate by Thread(建议选择):通过线程分类来查看那些线程占用CPU最多。
Invert Call Tree(不建议选择):调用树倒返过来,将习惯性的从根向下一级一级的显示,如选上就会反过来从最底层调用向一级一级的显示。如果想要查看那个方法调用为最深时使用会更方便些。
Hide Missing Symbols(建议选择):隐藏丢失的符号,比如应用或者系统的dSYM文件找不到的话,在详情面板上是看不到方法名的,只能看一些读不懂的十六进值,所以对我们来说是没有意义的,去掉了会使阅读更清楚些。
Hide System Libraries(建议选择):选上它只会展示与应用有关的符号信息,一般情况下我们只关心自己写的代码所需的耗时,而不关心系统库的CPU耗时。
Flatten Recursion(一般不选):选上它会将调用栈里递归函数作为一个入口。
Top Functions(可选):选上它会将最耗时的函数降序排列,而这种耗时是累加的,比如A调用了B,那么A的耗时数是会包含B的耗时数。