//load方法只会调用一次,所以把设置富文本放在load方法里性能更好
+ (void)load
{
// 获取哪个类下面的导航条
UINavigationBar *bar = [UINavigationBar appearanceWhenContainedIn:self, nil];
[bar setBackgroundImage:[UIImage imageNamed:@"NavBar64"] forBarMetrics:UIBarMetricsDefault];
// 设置导航条标题颜色
NSMutableDictionary *titleAttr = [NSMutableDictionary dictionary];
titleAttr[NSForegroundColorAttributeName] = [UIColor blueColor];
titleAttr[NSFontAttributeName] = [UIFont boldSystemFontOfSize:20];
[bar setTitleTextAttributes:titleAttr];
}
- (void)viewDidLoad {
[super viewDidLoad];
/**
自定导航控制的滑动手势
handleNavigationTransition:方法是通过打印
interactivePopGestureRecognizer导航卡滑动手势得到
*/
UIPanGestureRecognizer * pan = [[UIPanGestureRecognizer alloc]initWithTarget:self.interactivePopGestureRecognizer.delegate action:@selector(handleNavigationTransition:)];
[self.view addGestureRecognizer:pan];
//监控手势什么时候出发,只有非根控制器才需要触发手势
pan.delegate = self;
//禁止之前的手势
self.interactivePopGestureRecognizer.enabled =NO;
};
//决定是否触发手势
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
return self.childViewControllers.count > 1;
}
-(void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
/**
统一设置返回按钮,只要用了XCNavigationController的push方法就会自动生成一个自定义的返回按钮,比单个页面去设置节省代码量
*/
if (self.childViewControllers.count >0) {
viewController.navigationItem.leftBarButtonItem = [UIBarButtonItem backItemWithImage:[UIImage imageNamed:@"navigationButtonReturn"] hlghImage:[UIImage imageNamed:@"navigationButtonReturnClick"] target:self action:@selector(back) title:@"返回"];
}
//真正跳转的方法是父类做的
[super pushViewController:viewController animated:animated];
}
- (void)setFrame:(CGRect)frame
{
frame.size.height -= 1;
// 才是真正去给cell赋值
[super setFrame:frame];
}
#import "XCFastLoginButton.h"
@implementation XCFastLoginButton
-(void)layoutSubviews
{
[super layoutSubviews];
self.imageView.XC_y = 0;
self.imageView.XC_CenterX = self.XC_width * 0.5;
self.titleLabel.XC_y = self.XC_height - self.titleLabel.XC_height;
[self.titleLabel sizeToFit];
self.titleLabel.XC_CenterX = self.XC_width * 0.5;
}
@end
#import "UITextField+Placeholder.h"
#import <objc/message.h>
@implementation UITextField (Placeholder)
+(void)load
{
Method setPlaceholderMethod = class_getInstanceMethod(self, @selector(setPlaceholder:));
Method setXc_PlaceholderMethod = class_getInstanceMethod(self, @selector(setXc_Placeholder:));
//添加交换方法把系统的方法换成自定义的方法
method_exchangeImplementations(setPlaceholderMethod, setXc_PlaceholderMethod);
}
-(void)setPlaceholderColor:(UIColor *)placeholderColor
{
//添加成员属性
objc_setAssociatedObject(self, @"placeholderColor", placeholderColor, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
// 快速设置占位文字颜色 => 文本框占位文字可能是label => 验证占位文字是label => 拿到label => 查看label属性名(1.runtime 2.断点)
/**
通过断点调试找到placeholderLabel属性,用kvc修换占位文字颜色
如果单纯的使用kvc修改占位文字颜色,会产生bug
如果先设置占位文字,在设置占位文字颜色会没有占位文字颜色,
所以需要用runtime给textFild添加自定义的属性,然后添加交换方法
*/
UILabel *placeholderLabel = [self valueForKey:@"placeholderLabel"];
placeholderLabel.textColor = placeholderColor;
}
-(UIColor *)placeholderColor
{
return objc_getAssociatedObject(self, @"placeholderColor");
}
// 设置占位文字
// 设置占位文字颜色
- (void)setXc_Placeholder:(NSString *)placeholder
{
[self setXc_Placeholder:placeholder];
self.placeholderColor = self.placeholderColor;
}
@end
// tableView分组样式,有额外头部和尾部的间距
self.tableView.sectionFooterHeight = 10;
self.tableView.sectionHeaderHeight = 0;
//解决tableView分组样式往下走了一段距离问题
self.tableView.contentInset = UIEdgeInsetsMake(-25, 0, 0, 0);
-
-
- 1 除开UIControlStateHighlighted、UIControlStateDisabled、UIControlStateSelected以外的其他情况,都是normal状态
- 2 这种状态下的按钮【可以】接收点击事件
-
- 1 【当按住按钮不松开】或者【highlighted = YES】时就能达到这种状态
- 2 这种状态下的按钮【可以】接收点击事件
-
- 1 【button.enabled = NO】时就能达到这种状态
- 2 这种状态下的按钮【无法】接收点击事件
-
- 1 【button.selected = YES】时就能达到这种状态
- 2 这种状态下的按钮【可以】接收点击事件
-
-
-
- #####【会】进入UIControlStateDisabled状态
-
-
// 控件按钮内部子控件之间的间距
// btn.contentEdgeInsets = UIEdgeInsetsMake(10, 0, 0, 0);
// btn.titleEdgeInsets = UIEdgeInsetsMake(0, 10, 0, 0);
// btn.imageEdgeInsets = UIEdgeInsetsMake(0, 10, 0, 0);
-
#####1 后面带有NS_DESIGNATED_INITIALIZER的方法,就是特定构造方法
-
#####2 子类如果重写了父类的【特定构造方法】,那么必须用super调用父类的【特定构造方法】,不然会出现警告
-
tableView属性分析
这种情况只能针对数据比较小的时候 parameters[@"page"] = @(self.page +1); //请求成功后对操作 self.page = [parameters [@"page"] integerValue]; //或者在请求前对page++,但是失败后要对page-- 如果数据量大或者经常更新就要考虑,发送当前数据的最后一条,比如当前数据id是35请求新的数据就需要请求35以后所有的数据
第一种: 解决这种问题最简单的方法就是定义一个BOOL属性,开始刷新的状态是YES,结束刷新为No,然后去判断状态如果正在上拉或下拉直接返回。这种方法最直接 第二种:直接处理请求 [self.manager.tasks makeObjectsPerformSelector:@selector(cancel)]; 在请求完成后在失败的block中判断NSURLError的状态 if (error.code != NSURLErrorCancelled) { // 并非是取消任务导致的error,其他网络问题导致的error [SVProgressHUD showErrorWithStatus:@"网络繁忙,请稍后再试!"]; }
-
/**
这个方法特点:
- 1.默认情况下(没有设置estimatedHeight)每次刷新表格时,这个方法就一次性调用多少次,每次reloadData时,这个方法就会调用
- 2.每次有cell进入屏幕范围内,就会调用一次
针对以上的特点思考:如果每次都要调用这个方法都要去计算cell的高度,这样写不严谨,所以就要考虑如果以前如果算过cell的高度,就直接返回
*/
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return self.topics[indexPath.row].cellHeight;
}
/**
估算高度的好处:用到哪个cell才会调用这个方法计算cell的高度,降低heightForRowAtIndexPath方法的调用频率
缺点:滚动条的长度是假的,不稳定,甚至卡顿
*/
-(CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 200;
}