目录
[TOC]
1 页面莫名被导航栏遮盖的解决办法
self.edgesForExtendedLayout = UIRectEdgeNone;
self.extendedLayoutIncludesOpaqueBars = NO;
2 收起键盘的四种方法
3 textView字数限制
//在这个代理方法无法控制键盘联想
- (BOOL)textView:(YYTextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
NSMutableString *newText = [NSMutableString stringWithString:textView.text];
[newText replaceCharactersInRange:range withString:text];
NSInteger strLength = textView.text.length - range.length + text.length;
return (strLength <= 200);
}
//在这个代理方法监测长度,超过受限长度则截取
-(void)textViewDidChange:(YYTextView *)textView
{
if (textView.text.length > 127) {
textView.text = [textView.text substringToIndex:127];
}else if(textView.text.length == 0) {
}else {
}
}
4 iOS 将自定义View添加到WebView上
要实现将self.topView放进self.webView里面随着webView的滑动一起滑动
//先创建self.topView
self.topView = [[YQZhidaoDetailTopView alloc] initWithDelegate:self WithModel:self.answer];
//使用Frame创建一个承载的View top,**注意其y坐标**
UIView *top = [[UIView alloc] initWithFrame:CGRectMake(0, -self.topView.topViewHeight, SCREEN_WIDTH, self.topView.topViewHeight)];
[self.webView.scrollView addSubview:top];
//将self.topView添加到top上,然后设置约束
[top addSubview:self.topView];
[self.topView mas_makeConstraints:^(MASConstraintMaker *make) {
make.edges.mas_equalTo(UIEdgeInsetsZero);
}];
//由于在webView上添加了一个头部,所以记得设置contentInset
self.webView.scrollView.contentInset = UIEdgeInsetsMake(self.topView.topViewHeight, 0, 0, 0);
5 xib的继承
关于xib的继承,分两种情况:1)子类无需修改xib 2)子类要在父类的xib上进行修改,下面分别说明使用方法
(1)子类无需修改xib,子类如何继承父类的样式?在子类中把initWithNibName:把此处改为父类的xib中的名字
- (instancetype)initWithNibName:(NSString )nibNameOrNil bundle:(NSBundle )nibBundleOrNil {
if (self = [super initWithNibName:@”父类的xib中的名字” bundle:nibBundleOrNil]) {
}
return self;
}
(2)子类需要在父类xib的基础上修改,子类如何既继承父类的样式,然后又能继承父类的业务逻辑处理?可以将父类的xib直接拖入到子类的xib中,直接在父类的xib中直接增加子类需要增加的UI元素(注意只能用拖入的方式,使用拷贝的方式会使得xib中的outlet失效),然后将子类xib的class文件改成对应的子类文件即可
-(void)setModel:(ZhiDaoMixDataModel *)model
{
//调用父类
[super setModel:model];
//子类需要处理的逻辑
....
}
6 数组使用 valueForKeyPath:计算求和、平均值、最大、最小
NSArray *testArray = [NSArray arrayWithObjects:@"2.0", @"2.3", @"3.0", @"4.0", nil];
NSNumber *sum = [testArray valueForKeyPath:@"@sum.floatValue"];
NSNumber *avg = [testArray valueForKeyPath:@"@avg.floatValue"];
NSNumber *max = [testArray valueForKeyPath:@"@max.floatValue"];
NSNumber *min = [testArray valueForKeyPath:@"@min.floatValue"];
如果是数据模型对象:比如数据模型对象有一个属性 finishRate
CGFloat max = [[[self datas] valueForKeyPath:@"@max.finishRate"] floatValue];
7 覆盖安装要注意的那些事
8 layoutSubviews
- init初始化不会触发layoutSubviews
- 当view的fram的值为0的时候,addSubview不会调用layoutSubviews。
- addSubview的时候。
- 当view的frame发生改变的时候。
- 直接调用setNeedsLayout方法会调用。
- 滑动UIScrollView的时候。
- 旋转Screen会触发父UIView上的layoutSubviews事件。
- 改变一个UIView大小的时候也会触发父UIView上的layoutSubviews事件。
setNeedsLayout方法的意思是: 将调用者标记为需要重新布局,然后会异步调用layoutIfNeeded刷新布局,既然异步就不立即刷新,但layoutSubviews一定会被调用
layoutIfNeeded的意思是:当我被调用且被调用者有需要刷新的标记,则立即调用被调用者的layoutSubviews方法进行布局,如果被调用者没有被标记,layoutSubviews是不会被调用的。
另外就是,如果要立即刷新,要先调用[view setNeedsLayout],把标记设为需要布局,然后马上调用[view layoutIfNeeded],实现刷新布局。
9 关于[UIBarButtonItem alloc] initWithImage:颜色被冲的解决办法
UIImage *aimage = [UIImage imageNamed:@"xxx"];
UIImage *image = [aimage imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
UIBarButtonItem *rightItem = [[UIBarButtonItem alloc] initWithImage:image style:UIBarButtonItemStylePlain target:self action:@selector(action_rightClick:)];
[self.navigationItem setRightBarButtonItem:rightItem animated:YES];
10 手写tableViewCell时应该重写的初始化方法
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
11 tableview的header下拉粘滞效果实现
//让tableView往上延展20,以免状态栏部分是空白
self.tableView.contentInset = UIEdgeInsetsMake(-20, 0, 0, 0);
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
CGFloat contentOffsetY = scrollView.contentOffset.y;
if (contentOffsetY <= 0) {
self.bgTop.constant = contentOffsetY;
CGFloat offsetWidth = rate* (-contentOffsetY); //rate = backImgWidth/backImgheight
self.bgLeading.constant = self.bgTrailing.constant = - offsetWidth / 2;
}
}
12 Failed to send request for reason:Error Domain=NSURLErrorDomain Code=-1022 "The resource could not be loaded because the App Transport Security policy requires the use of a secure connection."
苹果公司要求所有接口使用https,错误原因就是这个。具体可在Info.plist里加入以下内容。
NSAppTransportSecurity
NSAllowsArbitraryLoads
13 获取navigationController
// 假设 App 结构是 Root -> TabBar -> Navigation -> ViewController
UITabBarController *tabBarControler = (id)[UIApplication.sharedApplication.delegate.window.rootViewController;
UINavigationController *navigationController = tabBarControler.selectedViewController;
14 weak & strong self
/*
weakSelf是为了block不持有self,避免循环引用,而再声明一个strongSelf是因为一旦进入block执行,就不允许self在这个执行过程中释放。block执行完后这个strongSelf会自动释放,没有循环引用问题。
*/
__weak __typeof(self)weakSelf = self;
self.backgroundTaskIdentifier = [application beginBackgroundTaskWithExpirationHandler:^{
__strong __typeof(weakSelf)strongSelf = weakSelf;
}];
15 alertView、actionsheet修改按钮标题颜色
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:title message:nil preferredStyle:UIAlertControllerStyleActionSheet];
UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil];
UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"确认" style:UIAlertActionStyleDestructive handler:^(UIAlertAction *action){
}];
[okAction setValue:UICOLOR_WITH_RGBINT(0xFF3B30) forKey:@"_titleTextColor"]; //主要是这句设置颜色
[alertController addAction:cancelAction];
[alertController addAction:okAction];
[weakSelf presentViewController:alertController animated:YES completion:nil];
16 更改状态栏颜色
重写方法:
//设置字体颜色
- (UIStatusBarStyle)preferredStatusBarStyle{
return UIStatusBarStyleLightContent;//白色
}
然后在viewWillAppear里调用:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
[self preferredStatusBarStyle];
}
17 分类里增加属性
OC的分类允许给分类添加属性,但不会自动生成getter、setter方法。有没有解决方案呢?有,通过运行时建立关联引用。接下来以添加一个这样的属性为例,整体代码如下:
在匿名分类或者头文件中添加属性。区别是:匿名分类中添加的是私有属性,只在本类中可以使用,类的实例中不可以使用。头文件中添加的在类的实例中也可以使用。
//分类的头文件
@interface ClassName (CategoryName)
@property (nonatomic, strong) NSString *str;
@end
在实现里面写要添加属性的getter、setter方法。在setStr:方法中使用了一个objc_setAssociatedObject的方法,这个方法有四个参数,分别是:源对象,关联时的用来标记是哪一个属性的key(因为你可能要添加很多属性),关联的对象和一个关联策略。用来标记是哪一个属性的key常见有三种写法,但代码效果是一样的,如下:
//利用静态变量地址唯一不变的特性
1、static void *strKey = &strKey;
2、static NSString *strKey = @"strKey";
3、static char strKey;
关联策略是个枚举值,解释如下:
enum {
OBJC_ASSOCIATION_ASSIGN = 0, //关联对象的属性是弱引用
OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, //关联对象的属性是强引用并且关联对象不使用原子性
OBJC_ASSOCIATION_COPY_NONATOMIC = 3, //关联对象的属性是copy并且关联对象不使用原子性
OBJC_ASSOCIATION_RETAIN = 01401, //关联对象的属性是copy并且关联对象使用原子性
OBJC_ASSOCIATION_COPY = 01403 //关联对象的属性是copy并且关联对象使用原子性
};
//实现文件
#import "ClassName + CategoryName.h"
#import
static void *strKey = &strKey;
@implementation ClassName (CategoryName)
-(void)setStr:(NSString *)str {
objc_setAssociatedObject(self, & strKey, str, OBJC_ASSOCIATION_COPY);
}
-(NSString *)str {
return objc_getAssociatedObject(self, &strKey);
}
@end
18 MJRefreshGifHeader
更换普通MJRefreshHeader的最简单的一个方式就是用一组图实现gif的效果:
MJRefreshGifHeader *header = [MJRefreshGifHeader headerWithRefreshingTarget:self refreshingAction:@selector(refreshData)];
//隐藏时间
header.lastUpdatedTimeLabel.hidden = YES;
//隐藏状态
header.stateLabel.hidden = YES;
NSMutableArray *idleImages = [NSMutableArray array];
for (NSInteger i=1; i<=6; i++) {
UIImage *image = [UIImage imageNamed:[NSString stringWithFormat:@"ic_loading_0%li",(long)i]];
[idleImages addObject:image];
}
//给MJRefreshStateIdle状态设置一组图片,可以是一张,idleImages为数组
[header setImages:idleImages duration:1 forState:MJRefreshStatePulling];
[header setImages:idleImages duration:1 forState:MJRefreshStateRefreshing];
_tableView.mj_header = header;
还可以使用自己定义动画来实现:
具体参看利用MJRefresh定制自己的刷新动画
19 禁用textField出现复制粘贴剪切等操作
有时候我们需要禁用UITextField的双击出现copy、paste的功能,然而UITextField本身没有直接设置禁止用户复制粘贴剪切操作等方法,但是可以重载新建一个类继承UITextField,然后实现canPerformAction方法,只需覆盖canPerformAction:withSender方法就可以,canPerformAction:withSender属于UIResponder类的。
-(BOOL)canPerformAction:(SEL)action withSender:(id)sender {
UIMenuController *menuController = [UIMenuController sharedMenuController];
if (menuController) {
[UIMenuController sharedMenuController].menuVisible = NO;
}
if (action == @selector(paste:))
return NO;
if (action == @selector(select:))
return NO;
if (action == @selector(selectAll:))
return NO;
if (action == @selector(cut:))
return NO;
if (action == @selector(copy:))
return NO;
return NO;
}
20 pragma 处理警告 clang diagnostic 的使用
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-相关命令"
// 你自己的代码
#pragma clang diagnostic pop
常用相关命令有:
"-Wdeprecated-declarations" //方法弃用告警
"-Wincompatible-pointer-types" //不兼容指针告警
"-Warc-retain-cycles" //循环引用告警
"-Wunused-variable" //未使用变量告警
"-Wcovered-switch-default" //未使用Default
pragma 处理警告 clang diagnostic 的使用
21 semanticContentAttribute
UIView下的一个属性,9.0系统及以上适用。用于页面RTL/LTR布局。
@property (nonatomic) UISemanticContentAttribute semanticContentAttribute NS_AVAILABLE_IOS(9_0);
typedef NS_ENUM(NSInteger, UISemanticContentAttribute) {
UISemanticContentAttributeUnspecified = 0,
UISemanticContentAttributePlayback, // for playback controls such as Play/RW/FF buttons and playhead scrubbers
UISemanticContentAttributeSpatial, // for controls that result in some sort of directional change in the UI, e.g. a segmented control for text alignment or a D-pad in a game
UISemanticContentAttributeForceLeftToRight,
UISemanticContentAttributeForceRightToLeft
} NS_ENUM_AVAILABLE_IOS(9_0);
@property (nonatomic) UISemanticContentAttribute semanticContentAttribute NS_AVAILABLE_IOS(9_0);
平常我们常用的按钮是图标在左,标题在右。直接使用此属性便可更改左右位置。再借助于titleEdgeInsets
和imageEdgeInsets
便可轻松搞定布局。
_addBtn.semanticContentAttribute = UISemanticContentAttributeForceRightToLeft;
_addBtn.titleEdgeInsets = UIEdgeInsetsMake(0, -30, 0, 0);
_addBtn.imageEdgeInsets = UIEdgeInsetsMake(0, 30, 0, 0);
22 UICollectionView的悬浮header
sectionHeadersPinToVisibleBounds
同样是iOS9之后推出的特性。如果iOS9之前要实现UICollectionView的悬浮header需自定义layout。
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
layout.scrollDirection = UICollectionViewScrollDirectionVertical;
layout.sectionHeadersPinToVisibleBounds = YES;
@property (nonatomic) BOOL sectionHeadersPinToVisibleBounds NS_AVAILABLE_IOS(9_0);
@property (nonatomic) BOOL sectionFootersPinToVisibleBounds NS_AVAILABLE_IOS(9_0);
23 UIScrollview偏移问题
iOS11之前:
//在vc里写上
self.automaticallyAdjustsScrollViewInsets = NO;
iOS11之后:
if (@available(iOS 11.0, *)) {
_tabelView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
} else {
self.automaticallyAdjustsScrollViewInsets = NO;
}
大神写的:
#define adjustsScrollViewInsets_NO(scrollView,vc)\
do { \
_Pragma("clang diagnostic push") \
_Pragma("clang diagnostic ignored \"-Warc-performSelector-leaks\"") \
if ([UIScrollView instancesRespondToSelector:NSSelectorFromString(@"setContentInsetAdjustmentBehavior:")]) {\
[scrollView performSelector:NSSelectorFromString(@"setContentInsetAdjustmentBehavior:") withObject:@(2)];\
} else {\
vc.automaticallyAdjustsScrollViewInsets = NO;\
}\
_Pragma("clang diagnostic pop") \
} while (0)
24 判断是否X以后的手机
判断是否为 iPhoneXS Max,iPhoneXS,iPhoneXR,iPhoneX
#define KIsiPhoneX ((int)((SCREEN_HEIGHTL/SCREEN_WIDTHL)*100) == 216)?YES:NO
25 UITableView上添加手势,与didSelect冲突
- (void)viewDidLoad {
[self initTableView];
}
- (void) initTableView {
UITableView *tableView = [[UITableView alloc] init];
tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
tableView.delegate = self;
tableView.dataSource = self;
tableView.backgroundColor = GCOLOR;
tableView.showsVerticalScrollIndicator = NO;
[self.view addSubview:tableView];
[tableView mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.right.mas_equalTo(0);
make.top.mas_equalTo(0);
make.bottom.mas_equalTo(iPhoneX ? @-84 : @-50);
}];
self.tableView = tableView;
//区头高度
if (@available(iOS 11.0, *)) {
self.tableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever;
// est和代理 可选1个
self.tableView.estimatedSectionHeaderHeight = 10;
} else {
self.automaticallyAdjustsScrollViewInsets = NO;
}
//table添加手势点击
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] init];
tap.delegate = self;
[tableView addGestureRecognizer:tap];
}
#pragma mark - 手势代理
//table添加手势
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
if ([NSStringFromClass([touch.view class]) isEqualToString:@"UITableViewCellContentView"]) {
return NO;
} else {
self.cxHelpV.hideView = YES;
return YES;
}
26 将button的点击区域限定在selectView里
//将button的点击区域限定在selectView里
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
//首先调用父类的方法确定点击的区域确实在按钮的区域中
BOOL res = [super pointInside:point withEvent:event];
if (res) {
//绘制一个圆形path
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:self.selectView.bounds];
if ([path containsPoint:point]) {
//如果在path区域内,返回YES
return YES;
}
return NO;
}
return NO;
}
27 放大
weakSelf.countDown.transform = CGAffineTransformMakeScale(1.5, 1.5);//放大值
weakSelf.aphView.transform = CGAffineTransformMakeScale(10, 10);//放大值
28 pod使用某个分支
pod 'SDJGCommunityProject',:git=>'http://192.168.0.224/iosenterprise/staffApp_sdjgcommunityproject.git',:branch=>'br_fix_SWHomePageAdPopViews_1.2.5'
29 cocoapods的卸载和安装
卸载cocoapods
sudo gem uninstall cocoapods
安装
sudo gem install -n /usr/local/bin cocoapods -v 1.7.5
安装最新版本
sudo gem install -n /usr/local/bin cocoapods --pre
30 iOS 13tabbar隐藏黑线、隐藏背景等
https://blog.csdn.net/Goods_boy/article/details/102862642
31 Button 标题和icon位置互换
_moreButton.semanticContentAttribute = UISemanticContentAttributeForceRightToLeft;
32 自定义字体库
ios - 添加自定义字体库
NSArray *arr = [UIFont familyNames];
NSInteger i = 0;
for (NSString *str in arr) {
NSArray *arr_01 = [UIFont fontNamesForFamilyName:str];
for (NSString *str_01 in arr_01) {
NSLog(@"%i:%@",i,str_01);
i++;
}
}
33 安装了conda后,前面会有一个(base)
mac安装了conda后,前面会有一个(base),很烦人,终于找到最佳解决方案了:
$ conda config --set auto_activate_base false
原因:
安装conda后,每次启动终端,都会自动启动conda的base环境,conda的环境可以用 conda env list 查看
只要设置conda不要自动启动base环境就可以了。