通用记录
状态栏
- 状态栏留白问题
if (@available(iOS 11.0, *)) {
self.scrollView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
} else {
self.automaticallyAdjustsScrollViewInsets = NO;
}
导航栏
- 导航栏遮挡问题
//UIRectEdgeBottom从导航栏的底部开始布局
self.edgesForExtendedLayout = UIRectEdgeBottom;
//在viewDidLoad里的self.view高度是屏幕的高度
//此时高度会超出屏幕,因为布局是从导航栏底部开始的,在以下方法中重新赋值
- (void)viewWillLayoutSubviews {
[super viewWillLayoutSubviews];
self.payView.frame = self.view.bounds;
}
UIScrollView
if (@available(iOS 11.0, *) ) {
self.tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
} else {
self.automaticallyAdjustsScrollViewInsets = NO;
}
加载xib文件
NSArray *nibArray = [[NSBundle mainBundle]loadNibNamed:NSStringFromClass([HomeClientBottomView class]) owner:self options:nil];
HomeClientBottomView *bottomview =[nibArray lastObject];
返回到指定的VC
for (UIViewController *vc in self.navigationController.viewControllers) {
if ([vc isKindOfClass:[MyVC class]]) {
MyVC *popVC = (MyVC *)vc;
[self.navigationController popToViewController:popVC animated:YES];
}
}
UITextFiled相关设置
- 设置placeholder字体颜色等
NSAttributedString *placeholderAttributed = [[NSAttributedString alloc]initWithString:placeholder attributes:@{
NSForegroundColorAttributeName:Color_Hex(@"#999999"),
NSFontAttributeName:[UIFont font_fontPingFangSCMedium:14],
}];
self.textField.attributedPlaceholder = placeholderAttributed;
plist配置
麦克风权限:Privacy - Microphone Usage Description 是否允许此App使用你的麦克风?
相机权限:Privacy - Camera Usage Description 是否允许此App使用你的相机?
相册权限: Privacy - Photo Library Usage Description 是否允许此App访问你的媒体资料库?
通讯录权限: Privacy - Contacts Usage Description 是否允许此App访问你的通讯录?
蓝牙权限:Privacy - Bluetooth Peripheral Usage Description 是否许允此App使用蓝牙?
语音转文字权限:Privacy - Speech Recognition Usage Description 是否允许此App使用语音识别?
日历权限:Privacy - Calendars Usage Description 是否允许此App使用日历?
- 定位权限:
Privacy - Location When In Use Usage Description 我们需要通过您的地理位置信息获取您周边的相关数据
Privacy - Location Always Usage Description 我们需要通过您的地理位置信息获取您周边的相关数据
- HTTP配置:
添加key:App Transport Security Settings,字典类型
在下面添加key:Allow Arbitrary Loads,Boolean类型,值为YES
多手势支持
- 下面这个方法支持多手势,当滑动子控制器中的scrollView时,MyTableView也能接收滑动事件,比如在VC里面有一个scrollView,scrollView上有tableView,这时候自定义一个MyTableView类,重写下面的方法即可
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
return [gestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]] && [otherGestureRecognizer isKindOfClass:[UIPanGestureRecognizer class]];
}
isa理解
背景:
实例方法:Person类继承于NSObject类,Person类中如果有一个实例方法,但是没有实现,在NSObject类中如果有这个方法,使用Person对象调用这个实例方法不会导致报错,这个比较好理解,如果Person类中没有该方法,会查找父类是否实现了该方法。
对比isa走位图,查找流程为:
Subclass(class)->Superclass(class)->Root class(class)
类方法:Person类继承于NSObject类,Person类中如果有一个类方法,但是没有实现,在NSObject类中如果有这个方法,使用Person类调用这个类方法也不会导致报错,因为类方法存储在元类中,如果元类没有,会按照父类查找流程查找元类的父类,最终会查找到NSObject类中。
对比isa走位图,查找流程为:
Subclass(meta)->Superclass(meta)->Root class(meta)->Root class(class)
打印
- 事例
文件名:MyVC
方法名:viewDidLoad
打印:userID 结果为14
行号:28行
- 第一种
#ifndef __OPTIMIZE__
#define FLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)
#else
#define FLog(...)
#endif
打印结果
-[MyVC viewDidLoad] [Line 28] 14
- 第二种
#ifdef DEBUG
# define SLog(fmt, ...) NSLog((@"[文件名:%s]\n" "[函数名:%s]\n" "[行号:%d] \n" fmt), __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__);
#else
# define SLog(...);
#endif
打印结果
[文件名:/Users/kz/wicep/project/sjgj_ios/TimeInternational/my_module/MyVC.m]
[函数名:-[MyVC viewDidLoad]]
[行号:28]
14
- 第三种
#ifdef __OBJC__ //保证代码只会在OC中引用
#ifdef DEBUG
#define TLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__)
#else
#define TLog(...)
#endif
#endif
打印结果
-[MyVC viewDidLoad] [Line 28] 14
- 解释:
- OPTIMIZE:在Debug模式下,才会有此宏定义。意思就是在优化的过程中,即Debug模式。
- PRETTY_FUNCTION:通过PRETTY_FUNCTION可以打印出Log所在类名-函数。
- LINE:标识符LINE的内容是当前被编译代码行的行号。
- TIME:时间 %s接收
消除系统警告
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
代码部分
#pragma clang diagnostic pop
_cmd
_cmd为隐式参数,表示当前方法
- (void)viewDidLoad {
[super viewDidLoad];
SEL sel = @selector(test:);
[self test:sel];
}
- (void)test:(SEL)sel {
NSLog(@"%@ - %@",NSStringFromSelector(sel),NSStringFromSelector(_cmd));
if (sel == _cmd) {
NSLog(@"equal");//true
} else {
NSLog(@"not equal");//false
}
//验证结果 _cmd就是sel
}
打印结果
2021-11-03 10:05:48.965761+0800 KZOC[2398:324112] test: - test:
2021-11-03 10:05:48.966005+0800 KZOC[2398:324112] equal
Runtime应用
分类增加属性
背景:有一个Person类,新建一个Person类的分类Person+House(简称PH类),在PH类中增加一个属性houseName,这种情况下需要在PH.m文件中手动加上setter和getter方法,否则赋值和调用的时候会报错
- PH.h类中声明属性
@property(nonatomic, copy) NSString *houseName;
- getter方法实现
·- (NSString *)houseName {
return objc_getAssociatedObject(self, _cmd);
}
- setter方法实现
·- (void)setHouseName:(NSString *)houseName {
objc_setAssociatedObject(self, @selector(houseName), houseName, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
消息转发
<font color = #E0616F> Note:对实例方法进行举例说明 </font>
背景:Person.h声明了一个eat方法和一个drink方法,Person.m实现了eat方法,但是没有实现drink方法,调用drink方法的时候会导致程序奔溃
- 1、实例方法决议
+(BOOL)resolveInstanceMethod:(SEL)sel;
在Person.m中实现上述方法,将drink的imp指向eat,当调用drink的时候会实现eat的方法体
Person.h
@interface Person : NSObject
- (void)eat;//实现
- (void)drink;//未实现
@end
Person.m
+ (BOOL)resolveInstanceMethod:(SEL)sel {
if (sel == @selector(drink)) {
IMP drinkImp = class_getMethodImplementation(self, @selector(eat));
Method drinkMethod = class_getInstanceMethod(self, @selector(eat));
const char *drinkType = method_getTypeEncoding(drinkMethod);
return class_addMethod(self, sel, drinkImp, drinkType);
}
return [super resolveInstanceMethod:sel];
}
-
2、快速查找
如果1步骤没有实现,会查询是否实现了2步骤中的方法
背景:Student类(继承于NSObject),声明了eat方法,但是没有实现,Person中有eat方法的实现,在下面这个方法中交给Person进行处理
-(id)forwardingTargetForSelector:(SEL)aSelector;
Student.h
@interface Student : NSObject
- (void)eat;//未实现
@end
Student.m
- (id)forwardingTargetForSelector:(SEL)aSelector {
if (aSelector == @selector(eat)) {
return [Person alloc];
}
return [super forwardingTargetForSelector:aSelector];
}
-
3、慢速查找
背景:如果1步骤和2步骤都没有实现,会进入3步骤进行处理
3.1、首先会进入
-(NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector;
方法实现方法签名的返回
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
if (aSelector == @selector(eat)) {
return [NSMethodSignature signatureWithObjCTypes:"v@:"];
}
return [super methodSignatureForSelector:aSelector];
}
3.2、实现下面的方法,交给可以处理的对象进行处理,不写内容的话也不会导致崩溃
-(void)forwardInvocation:(NSInvocation *)invocation;
- (void)forwardInvocation:(NSInvocation *)invocation {
SEL aSelector = [invocation selector];
Person *per = [[Person alloc]init];
if ([per respondsToSelector:aSelector])
[invocation invokeWithTarget:per];
else
[super forwardInvocation:invocation];
}
CocoaPods使用
pod 相关写法
pod 'AFNetworking'//不显式指定依赖库版本,表示每次都获取最新版本
pod 'AFNetworking', '~> 0.1.2'//使用大于等于0.1.2但小于0.2的版本
pod 'AFNetworking', '~>0.1'//使用大于等于0.1但小于1.0的版本
pod 'AFNetworking', '2.0'//只使用2.0版本
pod 'AFNetworking', '> 2.0'//使用高于2.0的版本
pod 'AFNetworking', '>= 2.0'//使用大于或等于2.0的版本
pod 'AFNetworking', '< 2.0'//使用小于2.0的版本
pod 'AFNetworking', '<= 2.0'//使用小于或等于2.0的版本
pod 'AFNetworking', :git => 'http://gitlab.xxxx.com/AFNetworking.git', :branch => 'R20161010'//指定分支
pod 'AFNetworking', :path => '../AFNetworking'//指定本地库