导航控制器默认会给所有导航控制器下的scrollView添加44的滚动偏移量 , 可以用self.automaticallyAdjustsScrollViewInsets = NO;来让当前控制器不用自动调整UI(不添加44的滚动偏移量)
全局变量和文件加载顺序无关 程序运行时就会全部加载 extern使用
//ViewController.m
NSString *name = @"hello";
@interface ViewController ()
@end
@implementation ViewController
@end
//AppDelegate.m
//虽然其他文件定义的了全局变量 但是当前类里没有该变量 所以编译会报错 所以需要用到extern (该操作符只声明 不能用来初始化)
extern NSString* name ;
@interface AppDelegate ()
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
NSLog(@"%@",name);
return YES;
}
在子类方法中调用[super xxx]并不是拿到父类对象去调用,super这里不是指针 它是一个修饰符 本质是拿自己(当前类) 去调用父类的方法(不管本类有没有重写都是调用的父类) 所以父类方法中如果有self的话 其实现在是指向的是本类 而不是父类
加了static的全局变量(静态全局变量)只有当前类可以使用,其他类里声明了该全局变量也没法使用
全局变量可以在任何类里初始化(定义) 但是必须要在当前使用的类里进行声明 所以那个PCH篇文集里定义的全局变量(常量)是那样定义的
创建一个.h文件用来声明全局变量 然后通过PCH给所有类文件都引入该.h文件进行声明 再创建一个空的.m文件 进行全局变量定义(初始化) 并且不需要放入PCH文件中 因为在程序运行时会自动加载所有全局变量
类名调用方法 其实就是类对象调用方法 底层会把类名转换成类对象。
//一样的
[[Son class] performSelector:@selector(eat)];
[Son eat];
block中的变量都是强引用的,block作为某个类属性时会间接或者直接强引用的 如果在block中使用self就会导致循环引用 都不能释放;
//创建一个弱指针指向self的内存地址 就可以防止循环引用
__weak typeof(self) weakSelf = self;
_block= ^() {
NSLog(@"block -- %@",weakSelf.view);
};
_block();
在block中使用_成员属性也会造成强引用因为它其实就是self->xxx这样调用的,
block用作属性一定要用strong强引用
给每个导航控制器的所有栈顶对象设置一些属性时可以重写导航控制器的pushViewController方法 然后拿到将要放到栈顶的视图控制器修改它的属性,就可以使所有被该导航控制器管理的视图控制的统一修改属性
覆盖了系统的返回按钮后就不能向右滑动返回上一页下面代码是恢复滑动返回上一页
先重新设置pop手势代理为自己 然后重写shouldbegin方法 self.interactivePopGestureRecognizer.delegate = self; - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{ //不大于1的话说明只有最后一个控制器了 return self.childViewControllers.count > 1; }
layoutsubviews方法在控件的frame发生变化时调用
[$uiView sizeToFit],所有控件都有sizeToFit方法 自动计算出合适的尺寸(bounds);
控制器的view的get方法里 是调用loadView方法后调用一系列的生命周期方法
也就是说控制器的view是在loadView中赋值的 系统会自动创建一个默认的view给控制器 ,如果不需要 想要自定义的话 重写loadView在里面给self.view赋值即可
关于block
- 定义一个block类型 typedef void(^MyBlock)(...参数);
- 定义一个声明的block类型属性 @property (xx,xx) MyBlock block;
- 赋值block属性 _block = ^(...参数){...doSomeThing}
- 敲inlineBlock 可以迅速定义一个block变量
- block当做方法参数时 :(void(^)(...参数))block block名称需要拿到参数类型后面
分类中也可以使用@property声明属性的getset方法不过它不会生成成员变量 因为分类中不可以定义成员变量 并且它也不会实现getset方法 需要自己实现
imageV.transform =CGAffineTransformMakeScale(0.1, 0.1);缩放形变不能为0 为0就没动画直接消失了
事件寻找最合适的响应者(hittest)是从内向外,事件传递是从外向内。所以父控件必须能响应事件,自控件才能成为事件响应者
CGATransform和CATransform都是根据控件的layer.anchor进行形变的
UIView.center和layer.position都是指的控件anchor所在父控件的位置
绘制图片裁剪时一定需要先设置裁剪区域[path addClip]再画图片才有效
裁剪雪碧图要使用CGImageCreateWithImageInRect()宏
每个UIButton中都有一个UIImageView用来存放image属性 可以重写-
(CGRect)imageRectForContentRect:(CGRect)contentRect方法来设置控件UIImageView的大小位置
设置layer的3D矩阵转换立体效果
CATransform3D transform = CATransform3DIdentity; transform.m34 = -1 / 500.0; //后面的数值越大立体效果越小 _topImageV.layer.transform = CATransform3DRotate(transform, >-angle, 1, 0, 0);}
尽量不要使用CA动画,因为该动画保存的动画最终执行状态是假象 ,控件还在原处,所以尽量使用UIView动画
CATransform3D所形变的也是假象,CGATransform是真的移动控件
CA和CGA形变都可以使用transform = xxxIdentity进行还原形变 而不需要从新计算
UIView弹性动画
[UIView animateWithDuration:0.5 delay:0 usingSpringWithDamping:0.5 initialSpringVelocity:0 options:UIViewAnimationOptionCurveLinear animations:^{
_gradient.opacity = 0;
_topImageV.layer.transform = CATransform3DIdentity;
} completion:nil];
CAReplicatorLayer复制层的实例形变都是根据复制层的锚点进行的
手势相关
- (IBAction)move:(UIPanGestureRecognizer *)sender {
//获取每次移动的距离
NSLog(@"%@",NSStringFromCGPoint([sender translationInView:sender.view]));
//如果每次复位的话下次获取到的移动距离就是相对上次的
//如果不复位则获取到的距离是相对原来位置的(适合用来形变移动)
[sender setTranslation:CGPointZero inView:sender.view];
//获取每次移动的时所在相对父控件的坐标点
NSLog(@"%@",NSStringFromCGPoint([sender locationInView:sender.view]));
}
播放动画(gif)使用UIImageView的animation相关属性
设置按钮label颜色[self setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
自定义控件布局时可以重写该控件的layoutSubviews方法
contentmodel = UIViewContentModeCenter可以使图片在控件居中并且自适应比例
默认导航控制器的导航条translucent为YES即向上拖动时会有透明效果并且坐标从0,0开始 即内容view的大小为(375,667)
将translucent设为NO时 内容view的大小为 (375,603) 并且向上拖没有透明效果
self.navigationController.navigationBar.barTintColor = [UIColor blueColor];导航条的barTintColor可以设置导航条的背景颜色 但是不能设置颜色透明度,所以当需要设置颜色透明度时可以用[self.navigationController.navigationBar setBackgroundImage:image forBarMetrics:UIBarMetricsDefault];
// 绘制一张带颜色的图片出来
UIGraphicsBeginImageContext(CGSizeMake( 375, 64));
UIBezierPath *path=[UIBezierPath bezierPathWithRect:CGRectMake(0, 0, 375, 64)];
[[UIColor colorWithRed:122/225.0 green:22/225.0 blue:122/225.0 alpha:0.1] set];
[path fill];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
// 必须设置UIBarMetricsDefault 其他无效
[self.navigationController.navigationBar setBackgroundImage:image forBarMetrics:UIBarMetricsDefault];
导航条设置标题颜色用$vc.navigationController.navigationBar.titleTextAttributes,当你找不到哪个属性是修改控件的字体相关时就敲TextAttributes 🙂
统一设置导航条外观可以在 自定义的导航控制器中的load方法中使用[UINavigationBar appearanceWhenContainedInInstancesOfClasses:@[[MYNavigationVC class]]]获取到所有当前类所实现的导航条的外观对象(不能直接用appearance一定要用appearanceWhenContainedInInstancesOfClasses 否则会影响到其他类创建的导航条 比如默认的系统类创建的导航条) 然后直接设置样式 这样就能保证只会调用一次方法 统一一次设置外观
block中不能直接修改外面的局部变量 默认编译时是把外部的局部变量当做常量使用的 如果需要修改外部的局部变量则需要在变量前加上__block 如果是全局变量或者成员属性则可以直接修改
网友评论