1、纯代码创建UI,和XIB创建UI(limitedFree TopicView)
//手写代码实例化对象时调用此方法
-(instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
[self createUI];
}
return self;
}
//使用xib资源文件初始化时调用此方法
-(instancetype)initWithCoder:(NSCoder *)aDecoder
{
if (self = [super initWithCoder:aDecoder]) {
[self createUI];
}
return self;
}
3、保存图片到本地相册和消息弹框
-(void)longPressImageView:(UILongPressGestureRecognizer *)sender
{
UIAlertController *controller = [UIAlertController alertControllerWithTitle:@"操作图片" message:@"image" preferredStyle:UIAlertControllerStyleActionSheet];
[controller addAction:[UIAlertAction actionWithTitle:@"保存" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
//保存到相册
UIImageView *imgView = (UIImageView *)sender.view;
//第一个参数是要保存的图片对象,第二个参数是操作后由self调用第3个参数的方法,第4个参数是传递给回调方法的信息
UIImageWriteToSavedPhotosAlbum(imgView.image, self, @selector(image:finishedSaveWithError:contextInfo:), nil);
}]];
[controller addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
}]];
[self presentViewController:controller animated:YES completion:nil];
}
//保存图片到相册的回调方法 (UIAlertView iOS8之后就不推荐使用)
-(void)image:(UIImage *)image finishedSaveWithError:(NSError *)error contextInfo:(void *)contextInfo{
if (error) {
NSLog(@"保存失败:%@",error.localizedDescription);
}else{
UIAlertView *alerView = [[UIAlertView alloc]initWithTitle:@"提示" message:@"保存成功" delegate:nil cancelButtonTitle:nil otherButtonTitles:@"ok", nil];
[alerView show];
}
}
4、分栏控制器设置按钮
for (int i = 0; i < array.count;i++) {
Class cls = NSClassFromString(array[i]);
UIViewController *viewController = [[cls alloc]init];
UINavigationController *nc = [[UINavigationController alloc]initWithRootViewController:viewController];
UIImage *image1 = [UIImage imageNamed:defaultImages[i]];
UIImage *image2 = [[UIImage imageNamed:selectedImages[i]]imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
//设置分栏按钮的选中图片和常态图片
nc.tabBarItem = [[UITabBarItem alloc]initWithTitle:nameArray[i] image:image1 selectedImage:image2];
//设置导航栏背景颜色
[nc.navigationBar setBarTintColor:[UIColor colorWithRed:34 /255.0 green:115 / 255.0 blue:193 / 255.0 alpha:1]];
nc.tabBarItem.imageInsets = UIEdgeInsetsMake(7, 0, -7, 0);
[controllerArray addObject:nc];
}
5.设置label特殊的字体(一大一小),每个字的颜色
NSMutableAttributedString *str = [[NSMutableAttributedString alloc]initWithString:[model.ratingFinal stringValue]];
[str addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:20] range:NSMakeRange(0, 1)];
[str addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:13] range:NSMakeRange(1, 2)];
//设置颜色
[str addAttribute:NSForegroundColorAtrributeName value:[UIFont systemFontOfSize:13] range:NSMakeRange(1, 2)];
self.rateLabel.attributedText = str;
6.数据名称与关键字重名的时候,
1)重写setter方法
@property (nonatomic,copy,setter=setDescription:)NSString *myDescription;
2)使用JSON ,映射
+(JSONKeyMapper *)keyMapper{
return [[JSONKeyMapper alloc] initWithDictionary:@{@"GregorianCalendar":@"gregorianCalendar",@"LunarCalendar":@"lunarCalendar",@"ChineseZodiacYear":@"chineseZodiacYear",@"HeavenlyStemsAndEarthlyBranches":@"heavenlyStemsAndEarthlyBranches",@"SolarTerms":@"solarTerms"}];
}
7.关于数据下载的时候强引用的问题
//弱引用
__weak ViewController *weakSelf = self;
[manager GET:kLimitUrl parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
id result = [NSJSONSerialization JSONObjectWithData:responseObject options:NSJSONReadingMutableContainers error:nil];
if ([result isKindOfClass:[NSDictionary class]]) {
NSDictionary *dict = result;
for (NSDictionary *appDict in dict[@"applications"]) {
LimitModel *model = [[LimitModel alloc]init];
[model setValuesForKeysWithDictionary:appDict];
[weakSelf.dataArray addObject:model];
}
}
8.懒加载
//重新实现了getter方法
//在实际使用这个成员变量的时候,才会给它分配内存
-(NSMutableArray *)dataArray{
if (_dataArray==nil) {
_dataArray = [NSMutableArray array];
}
return _dataArray;
}
9.判断系统版本(iOS7 中会对selected的图片进行渲染为蓝色)
#define iOS7 [[UIDevice currentDevice].systemVersion doubleValue] >= 7.0
10.当前所有显示的BarButton
UIBarButtonItem *appearance = [UIBarButtonItem appearance];
11.部分代码只需执行一次,例如全局修改标题的颜色
+(void)initialize;
当第一次使用这个类的时候调用1次
12.UITextField 自定义搜索框
//一定要设置,不然不显示
textField.leftViewMode = UITextFieldViewModeAlways;
textField.clearButtonMode = UITextFieldViewModeAlways;
13.取消选中的按钮,不用循环
//UI的修改
//1)取消前面选中的按钮
UIButton *lastBtn = (UIButton *)[_myTabView viewWithTag:300+self.selectedIndex];
lastBtn.selected = NO;
UILabel *lastLabel = (UILabel *)[lastBtn viewWithTag:400];
lastLabel.textColor = [UIColor whiteColor];
-------------------------------------------
//控制按钮的状态(self.selectedButton 属性)
self.selectedButton.selected = NO;
btn.selected = YES;
self.selectedButton = btn;
15.自动计算文本的宽度
- 自动计算宽度
第一个参数显示:文字显示的最大范围
第二个参数:文字显示的方式
第三个参数:文字的属性
第四个参数:上下文nil
NSDictionary *dict = @{NSFontAttributeName:[UIFont systemFontOfSize:14]};
CGFloat fitW = [hDateModel.alertInfoFitting boundingRectWithSize:CGSizeMake(CGFLOAT_MAX, 20) options:NSStringDrawingUsesLineFragmentOrigin attributes:dict context:nil].size.width;
16.日期计算
NSDate *date = [NSDate date];
NSCalendar *cal = [NSCalendar currentCalendar];
unsigned int unit = NSCalendarUnitYear | NSCalendarUnitMonth |NSCalendarUnitDay;
NSDateComponents *dc = [cal components:unit fromDate:date];
NSString *urlString = [NSString stringWithFormat:kHomeInfoUrl,hostIp,[dc year],[dc month],[dc day]];
17.isKindOfClass判断子视图是否为某个类型,如果是则删除
for (UIView *oldSub in self.subviews) {
if ([oldSub isKindOfClass:[SearchGridCell class]]) {
[oldSub removeFromSuperview];
}
}
19.提示弹框+保存图片到本地
-(void)saveImageToLocal:(UILongPressGestureRecognizer *)sender{
//创建提示控制器
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"保存到相册" message:nil preferredStyle:UIAlertControllerStyleActionSheet];
[alertController addAction:[UIAlertAction actionWithTitle:@"保存" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
//保存到相册
UIImageView *imgView = (UIImageView *)sender.view;
//第一个参数是要保存的图片对象,第二个参数是操作后由self调用第3个参数的方法,第4个参数是传递给回调方法的信息
UIImageWriteToSavedPhotosAlbum(imgView.image, self, @selector(image:finishedSaveWithError:contextInfo:), nil);
}]];
//添加提示动作
[alertController addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
}]];
//让代理执行展示的方法
[self.delegate presentAlertCotroller:(alertController)];
}
20.处理网址中不易识别的中文字符
url = [url stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
21.EGO刷新,非arc(上拉加载更多不需要协议方法)
//上拉加载更多
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
[self.refreshView egoRefreshScrollViewDidScroll:scrollView];
if (_tableView.frame.size.height+_tableView.contentOffset.y > _tableView.contentSize.height+44&&self.isLoadMore==NO) {
self.pageNum++;
self.isLoadMore = YES;
[self addData];
}
}
-(void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{
[self.refreshView egoRefreshScrollViewDidEndDragging:scrollView];
}
#pragma mark - EGORefreshView的协议方法
-(NSDate *)egoRefreshTableHeaderDataSourceLastUpdated:(EGORefreshTableHeaderView *)view{
return [NSDate date];
}
-(BOOL)egoRefreshTableHeaderDataSourceIsLoading:(EGORefreshTableHeaderView *)view{
return _isRefresh;
}
//执行刷新操作
-(void)egoRefreshTableHeaderDidTriggerRefresh:(EGORefreshTableHeaderView *)view{
_currentPage = 1;
_isRefresh = YES;
[self requestDataFromUrl];
}
22.自定义单例类(LimiteFree)
+ (CacheManager *)shareManager{
static CacheManager *manager = nil;
@synchronized(self) {
if (manager==nil) {
manager = [[CacheManager alloc]init];
}
}
return manager;
}
23.图片转二进制数据(存储,缓存,收藏)
//图片对象转化为二进制数据
NSData *data = UIImagePNGRepresentation(model.image);
if (data==nil) {
data = UIImageJPEGRepresentation(model.image, 1);
}
24.枚举类型
#import "BaseViewController.h"
#import "MenuModel.h"
typedef enum{
SearchTypeCategory,//分类搜索
SearchTypeChoose//智能选菜
}SearchType;
@interface SearchResultController : BaseViewController
//搜索条件
@property (nonatomic,strong)NSArray *conditionArray;
//第一页的列表数据
@property (nonatomic,strong)HomeModel *hModel;
//类型
@property (nonatomic,assign)SearchType type;
if (self.type == SearchTypeCategory) {
title = @"搜索结果";
}else{
title = @"智能选菜";
}
25.Label自动适应大小
//自动适应大小
self.nameLabel.adjustsFontSizeToFitWidth = YES;
26.枚举
typedef enum{
SearchTypeCategory,//分类搜索
SearchTypeChoose//智能选菜
}SearchType;
@interface SearchResultController : BaseViewController
//搜索条件
@property (nonatomic,strong)NSArray *conditionArray;
//第一页的列表数据
@property (nonatomic,strong)HomeModel *hModel;
//类型
@property (nonatomic,assign)SearchType type;
27.自动获取label的最大高度
NSDictionary *dict = @{NSFontAttributeName:[UIFont systemFontOfSize:16]};
CGFloat height = [model.fittingRestriction boundingRectWithSize:CGSizeMake(280, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin attributes:dict context:nil].size.height;
h = 10 + height +10;
28.QQ折叠效果,刷新固定组
//刷新界面
//以动画的形式刷新某组的数据,第一个参数是组号的集合对象,第二个参数是刷新的动画样式
//NSIndexSet:索引集合,其中存放的都是索引
[self.tableView reloadSections:[NSIndexSet indexSetWithIndex:section] withRowAnimation:UITableViewRowAnimationFade];
29.关于导航栏UINavgationController
1)尽量使用系统自带的,自定义会丢失状态栏隐藏功能
- (BOOL)prefersStatusBarHidden{
return YES;
}
2) 自定义会丢失左侧拖动返回上个页面的功能
3)关于设置标题
//无效
self.navigationController.navigationItem.title = @"首页";
//有效
self.navigationItem.title = @"首页";
4)拦截所有push进来的Controller
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated{
if (self.viewControllers.count > 0) { // 如果现在push的不是栈底控制器(最先push进来的那个控制器)
viewController.hidesBottomBarWhenPushed = YES;
// 设置导航栏按钮
viewController.navigationItem.leftBarButtonItem = [UIBarButtonItem itemWithImageName:@"navigationbar_back" highImageName:@"navigationbar_back_highlighted" target:self action:@selector(back)];
viewController.navigationItem.rightBarButtonItem = [UIBarButtonItem itemWithImageName:@"navigationbar_more" highImageName:@"navigationbar_more_highlighted" target:self action:@selector(more)];
}
[super pushViewController:viewController animated:animated];
}
30.关于super,子类重新父类方法,父类调用方法
当子类进行方法的重写时,父类的方法内容会被覆盖掉,这时是运行子类重写的方法。但有时还是要从子类里使用父类的原来的那个方法,这时可以使用super关键字。
31.init内部会调用initWithFrame
32.GCD多线程操作
总结:
同步(sync)函数,在当前线程中执行
(1、并发队列:不会开线程
(2、串行队列:不会开线程
异步(async)函数,具备开线程能力!!但是不一定开(放到主队列的时候),在另一条线程中执行
(1、并发队列:开多条线程
(2、串行队列:开一条线程
1)用得最多的操作
//获取全局队列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//异步执行
dispatch_async(queue, ^{
//下载图片
dispatch_async(dispatch_get_main_queue(), ^{
//回到主线程更新UI
});
});
2)延时执行
1-调用NSObject方法
[Self performSelector:@seletor(run) withObject:nil afterDelay:2.0];
2-GCD(更好用,不用重新生成方法)
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"2222");
});
3)保证方法在整个程序只执行一次
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
});
单例单例单例单例单例
+(SchoolManager *)sharedInstance
{
static SchoolManager *sharedManager;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedManager = [[SchoolManager alloc] init];
});
return sharedManager;
}
4)组操作,多个请求,请求完成后再执行操作
//创建一个组,
dispatch_group_t group = dispatch_group_create();
//开启一个任务下载图片1
__block UIImage *image1 = nil;
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//image1 = [];
});
__block UIImage *image2 = nil;
dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//image2 = [];
});
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
//image1
//image2
});
33.高性能切圆角
UIImageView *imageView = [[UIImageView alloc]initWithFrame:CGRectMake(100, 100, 100, 100)];
UIImage *image = [UIImage imageNamed:@"3.jpg"];
UIGraphicsBeginImageContextWithOptions(imageView.bounds.size, NO, 1.0);
[[UIBezierPath bezierPathWithRoundedRect:imageView.bounds cornerRadius:50] addClip];
[image drawInRect:imageView.bounds];
imageView.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
[self.view addSubview:imageView];
34.cocoapods导入头文件没有自动提示
选择Target -> Build Settings 菜单,找到\”User Header Search Paths\”设置项
新增一个值"${SRCROOT}",并且选择\”Recursive\”,这样xcode就会在项目目录中递归搜索文件
35.形变
//缩放比例
CGFloat navH = [UIScreen mainScreen].bounds.size.height - 2 * 60;
CGFloat scale = navH / [UIScreen mainScreen].bounds.size.height;
//菜单左边的间距
CGFloat leftMenuMargin = [UIScreen mainScreen].bounds.size.width * (1 - scale) * 0.5;
CGFloat translateX = 200 - leftMenuMargin;
CGFloat topMargin = [UIScreen mainScreen].bounds.size.height * (1 - scale)* 0.5;
CGFloat translateY = topMargin - 60;
//缩放
CGAffineTransform scaleForm = CGAffineTransformMakeScale(scale, scale);
//平移
CGAffineTransform translateForm = CGAffineTransformTranslate(scaleForm, translateX/scale, -translateY/scale);
************************************************************************************
取消形变
self.showingNavigationContronller.view.transform = CGAffineTransformIdentity;
36.阴影
//显示新的控制器
NavigationController *newNav = self.childViewControllers[toIndex];
//设置新的控制器和旧的控制器一样
newNav.view.transform = oldNav.view.transform;
//设置阴影
newNav.view.layer.shadowColor = [UIColor blackColor].CGColor;
newNav.view.layer.shadowOffset = CGSizeMake(-3, 0);
newNav.view.layer.shadowOpacity = 0.2;
[self.view addSubview:newNav.view];
一个导航控制器的view第一次显示到它的父控件上时,如果transform的缩放值被改了,上面的20高度是不会出来
// 0.移除旧控制器的view
HMNavigationController *oldNav = self.childViewControllers[fromIndex];
[oldNav.view removeFromSuperview];
// 1.显示新控制器的view
HMNavigationController *newNav = self.childViewControllers[toIndex];
// 设置新控制的transform跟旧控制器一样
newNav.view.transform = oldNav.view.transform;
[self.view addSubview:newNav.view];
//修改
HMNavigationController *oldNav = self.childViewControllers[fromIndex];
[oldNav.view removeFromSuperview];
// 1.显示新控制器的view
HMNavigationController *newNav = self.childViewControllers[toIndex];
[self.view addSubview:newNav.view];
// 设置新控制的transform跟旧控制器一样
newNav.view.transform = oldNav.view.transform;
38.启动广告页面
(默认启动为storyboard的控制器,设置id,新建广告控制器为启动控制器),代码取出默认的控制器,两秒后跳转
//3.2s后调到下一个控制器
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
UIWindow *window = [UIApplication sharedApplication].keyWindow;
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
window.rootViewController = [storyboard instantiateViewControllerWithIdentifier:@"Main"];
});
39.UIView与layer的形变
UIView是2D,CG
layer是3D,CA
40.转场动画(网易头像翻转)
[UIView transitionWithView:self.iconView duration:1.0 options:UIViewAnimationOptionTransitionFlipFromLeft animations:^{
self.iconView.image = [UIImage imageNamed:@"user_defaultgift"];
} completion:^(BOOL finished) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[UIView transitionWithView:self.iconView duration:1.0 options:UIViewAnimationOptionTransitionFlipFromRight animations:^{
self.iconView.image = [UIImage imageNamed:@"default_avatar"];
} completion:^(BOOL finished) {
nil;
}];
});
}];
41.根据颜色生成图片
+ (UIImage *)imageWithColor:(UIColor *)color{
CGFloat imageW = 100;
CGFloat imageH = 100;
// 1.开启基于位图的图形上下文
UIGraphicsBeginImageContextWithOptions(CGSizeMake(imageW, imageH), NO, 0.0);
// 2.画一个color颜色的矩形框
[color set];
UIRectFill(CGRectMake(0, 0, imageW, imageH));
// 3.拿到图片
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
// 4.关闭上下文
UIGraphicsEndImageContext();
return image;
}
- 设置阴影
newNav.view.layer.shadowColor = [UIColor blackColor].CGColor;
newNav.view.layer.shadowOffset = CGSizeMake(-3, 0);
newNav.view.layer.shadowOpacity = 0.2;
43.NSInteger
NSInteger没有星号,因为NSInteger根据系统是64位还是32位来判断自身是long还是int类型,并且它也不是一个标准Objective-C对象。
45.tableView优化
tableView 滑动卡的问题主要是因为:从缓存中或者是从本地读取图片给UIImage的时候耗费的时间。需要把下面的两句话放到子线程里面:
NSData *imgData = [NSData dataWithContentsOfURL:[NSURL URLWithString:app.icon]]; //得到图像数据
UIImage *image = [UIImage imageWithData:imgData];
把UIImage赋值给图片的时候在主线程。
子线程不能更新UI 所有的UI跟新都是主线程执行了。手指滑动屏幕了。或者屏幕的某个方法执行了。
46.new和alloc/init区别
概括来说,new和alloc/init在功能上几乎是一致的,分配内存并完成初始化。
差别在于,采用new的方式只能采用默认的init方法完成初始化,
采用alloc的方式可以用其他定制的初始化方法。
47.array与alloc init区别
array这两个方式都是建立一个空的Array
[NSArray array]不需要release,使用autoreleasepool机制。
[[NSArray alloc] init]需要自己手动release
48.layout中动画,要声明约束的属性
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *redCon;
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
self.redCon.constant += 100;
[UIView animateWithDuration:1.0 animations:^{
[self.view layoutIfNeeded];
}];
}
49.[[[UIDevice currentDevice]systemVersion]floatvalue]为系统版本
50.加载大图的时候使用,会自动释放内存
NSString *path = [[NSBundle mainBundle]pathForResource:@"3" ofType:@"jpg"];
imageView.image = [UIImage imageWithContentsOfFile:path];
51.NSTimer放到NSRunloop里面,相当于放到子线程,不会阻塞主线程
[[NSRunLoop currentRunLoop]addTimer:self.timer forMode:NSRunLoopCommonModes];
52.tableView右滑删除
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
[_dataArray removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath, nil] withRowAnimation:UITableViewRowAnimationTop];
}
53.UITextField:检测值改变
[_textField addTarget:self action:@selector(valueChange) forControlEvents:UIControlEventEditingChanged];
54.SDWebImage三方库使用注意点,在AppDelegate中设置
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application
{
// 赶紧清除所有的内存缓存
[[SDImageCache sharedImageCache] clearMemory];
// 赶紧停止正在进行的图片下载操作
[[SDWebImageManager sharedManager] cancelAll];
}
55.监控网络状态,在AppDelegate中设置
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
// 4.监控网络
AFNetworkReachabilityManager *mgr = [AFNetworkReachabilityManager sharedManager];
// 当网络状态改变了,就会调用
[mgr setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
switch (status) {
case AFNetworkReachabilityStatusUnknown: // 未知网络
case AFNetworkReachabilityStatusNotReachable: // 没有网络(断网)
HMLog(@"没有网络(断网)");
[MBProgressHUD showError:@"网络异常,请检查网络设置!"];
break;
case AFNetworkReachabilityStatusReachableViaWWAN: // 手机自带网络
HMLog(@"手机自带网络");
break;
case AFNetworkReachabilityStatusReachableViaWiFi: // WIFI
HMLog(@"WIFI");
break;
}
}];
// 开始监控
[mgr startMonitoring];
56.NSUserDefault存储到本地,会默认存成一个plist文件,所有的操作都存储到这个plist文件中
57.登陆页面判断是否登陆过
// 3.设置窗口的根控制器
HMAccount *account = [HMAccountTool account];
if (account) {
[HMControllerTool chooseRootViewController];
} else { // 没有登录过
self.window.rootViewController = [[HMOAuthViewController alloc] init];
}
+ (void)chooseRootViewController
{
// 如何知道第一次使用这个版本?比较上次的使用情况
NSString *versionKey = (__bridge NSString *)kCFBundleVersionKey;
// 从沙盒中取出上次存储的软件版本号(取出用户上次的使用记录)
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *lastVersion = [defaults objectForKey:versionKey];
// 获得当前打开软件的版本号
NSString *currentVersion = [NSBundle mainBundle].infoDictionary[versionKey];
UIWindow *window = [UIApplication sharedApplication].keyWindow;
if ([currentVersion isEqualToString:lastVersion]) {
// 当前版本号 == 上次使用的版本:显示HMTabBarViewController
[UIApplication sharedApplication].statusBarHidden = NO;
window.rootViewController = [[HMTabBarViewController alloc] init];
} else { // 当前版本号 != 上次使用的版本:显示版本新特性
window.rootViewController = [[HMNewfeatureViewController alloc] init];
// 存储这次使用的软件版本
[defaults setObject:currentVersion forKey:versionKey];
[defaults synchronize];
}
}
58.撤销形变,前提之前的形变也就是采用的transform
self.showingNavigationController.view.transform = CGAffineTransformIdentity;
59.UITextField与UITextView
UITextField:单行,可以有placeholder
UITextView: 多行,没有placeholder
60.[self setNeedsLayout];重新布局控件,控件初始化的时候调用一次,后面如果要改变控件,自己手动还要再调用一次(Neteasy)
61.tableView刷新具体某行某个cell
//刷新某一个section
NSIndexSet *indexSet=[[NSIndexSet alloc] initWithIndex:2];
[tableview reloadSections:indexSet
withRowAnimation:UITableViewRowAnimationNone];
//刷新某一个cell
NSIndexPath *indexPath=[NSIndexPath indexPathForRow:1 inSection:0];
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath,nil]
withRowAnimation:UITableViewRowAnimationNone];
63.打印不要用NSLog
#if DEBUG
#define LLog(fmt, ...) NSLog((@"%s [Line %d] " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__);
#else
#define LLog(fmt, ...)
#endif
64.tableView分割线距离
if ([self.tableView respondsToSelector:@selector(setSeparatorInset:)]) {
[self.tableView setSeparatorInset:UIEdgeInsetsMake(0, 15, 0, 15)];
};
65.tabelView删除cell动画
//自定义cell的代理方法,点击cell上的按钮
- (void)tableViewDeleteCell:(ContactCell *)cell{
//通过cell拿到索引
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
[self.dataArray[indexPath.section] removeObjectAtIndex:indexPath.row];
//通过组数和行数创建array
NSArray *array = @[[NSIndexPath indexPathForRow:indexPath.row inSection:indexPath.section]];
//删除动画
[self.tableView deleteRowsAtIndexPaths:array withRowAnimation:UITableViewRowAnimationFade];
}
66.UIView的半透明优化性能
往每个cell中添加了6个subView,而且每个subView都是半透明(UIView默认是半透明的),这个时候滑动起来明显就可以感觉到有点颤抖,不是很流畅。当把每一个subView的opaque属性设置成YES的时候,滑动会比之前流畅一些,不过还是有点儿卡。
67.常量指针,指针常量
常量指针:就是指向常量的指针,关键字 const 出现在 * 左边,表示指针所指向的地址的内容是不可修改的,但指针自身可变。
指针常量:指针自身是一个常量,关键字 const 出现在 * 右边,表示指针自身不可变,但其指向的地址的内容是可以被修改的。
68.UIView与Layer关系
“平行的层级关系
每一个UIview都有一个CALayer实例的图层属性,也就是所谓的backing layer,视图的职责就是创建并管理这个图层,以确保当子视图在层级关系中添加或者被移除的时候,他们关联的图层也同样对应在层级关系树当中有相同的操作”
“CALayer是UIView内部实现细节”
Excerpt From: 钟声. “ios核心动画高级技巧.” iBooks.
69.iOS图片占内存过大的问题完美解决
func useImage(image: UIImage) -> NSData {
//实现等比例缩放
let hfactor = image.size.width / screnWidth;
let vfactor = image.size.height / screnHeight;
let factor = fmax(hfactor, vfactor);
//画布大小
let newWith: CGFloat = image.size.width / factor
let newHeigth: CGFloat = image.size.height / factor
let newSize = CGSize(width: newWith, height: newHeigth)
UIGraphicsBeginImageContext(newSize)
image.drawInRect(CGRect(x: 0, y: 0, width: newWith, height: newHeigth))
let newImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
//图像压缩
let newImageData = UIImageJPEGRepresentation(newImage, 0.5)
return newImageData!
}
- iOS6 不推荐你将 view 置为 nil 的原因
iOS6 不推荐你将 view 置为 nil 的原因(链接打开需要翻墙), 翻译过来如下:
UIView 有一个 CALayer 的成员变量,CALayer 是具体用于将自己画到屏幕上的。如下图所示:
CALayer 是一个 bitmap 图象的容器类,当 UIView 调用自身的 drawRect 时,CALayer 才会创建这个 bitmap 图象类。
具体占内存的其实是一个 bitmap 图象类,CALayer 只占 48bytes, UIView 只占 96bytes。而一个 iPad 的全屏 UIView 的 bitmap 类会占到 12M 的大小!
在 iOS6 时,当系统发出 MemoryWarning 时,系统会自动回收 bitmap 类。但是不回收 UIView 和 CALayer 类。这样即回收了大部分内存,又能在需要 bitmap 类时,通过调用 UIView 的 drawRect: 方法重建。
63.自定义了leftBarbuttonItem左滑返回手势失效了怎么办?
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc]
initWithImage:img
style:UIBarButtonItemStylePlain
target:self
action:@selector(onBack:)];
self.navigationController.interactivePopGestureRecognizer.delegate = (id
64.怎么像Safari一样滑动的时候隐藏navigationbar?
navigationController.hidesBarsOnSwipe = Yes
65.多用类型常量,少用#define预处理
如果只在本类使用的常量,使用static const关键字来定义常量。
如果多个类都需使用到某一常量,则需将常量定义成公开的,具体方式是在类的声明文件中使用extern const关键字声明常量,在类的实现文件中使用const关键字定义常量,这样任何类只要导入了声明常量的头文件就可以直接使用定义好的常量了。
在.h文件中声明
extern NSString *const XFExternalConst;
在.m文件中描述
NSString *const XFExternalConst = @"ko";
为避免冲突,一般都用类名做前缀。
50.禁止横屏方法
- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
return UIInterfaceOrientationMaskPortrait;
}
49.一行代码解决改变展位图文本颜色代码
[_userName setValue:[UIColor whiteColor] forKeyPath:@"_placeholderLabel.textColor"];
48.修改状态栏颜色
iOS7默认状态栏文字颜色为黑色,项目需要修改为白色。
1在Info.plist中设置UIViewControllerBasedStatusBarAppearance 为NO
2 在需要改变状态栏颜色的 AppDelegate中在 didFinishLaunchingWithOptions 方法中增加:
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
如果需要在单个ViewController中添加,在ViewDidLoad方法中增加:
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
47.判断程序是否第一次启动
if(![[NSUserDefaults standardUserDefaults] boolForKey:@"firstLaunch"]){
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"firstLaunch"];
NSLog(@"第一次启动");
[[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"isLogin"];
}else{
NSLog(@"已经不是第一次启动了");
}
46.iPhone尺寸规格
iPhone尺寸规格.png
45.模糊效果
// 模糊效果
// UIBlurEffect *effect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];
// UIVisualEffectView *test = [[UIVisualEffectView alloc] initWithEffect:effect];
// test.frame = self.view.bounds;
// test.alpha = 0.5;
// [self.view addSubview:test];
43.添加每个cell出现时的3D动画
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath{
// 动画1
// CATransform3D rotation;//3D旋转
// rotation = CATransform3DMakeRotation( (90.0*M_PI)/180, 0.0, 0.7, 0.4);
// //逆时针旋转
// rotation.m34 = 1.0/ -600;
//
// cell.layer.shadowColor = [[UIColor blackColor]CGColor];
// cell.layer.shadowOffset = CGSizeMake(10, 10);
// cell.alpha = 0;
//
// cell.layer.transform = rotation;
//
// [UIView beginAnimations:@"rotation" context:NULL];
// //旋转时间
// [UIView setAnimationDuration:0.8];
// cell.layer.transform = CATransform3DIdentity;
// cell.alpha = 1;
// cell.layer.shadowOffset = CGSizeMake(0, 0);
// [UIView commitAnimations];
// 动画2
cell.alpha = 0.5;
CGAffineTransform transformScale = CGAffineTransformMakeScale(0.3,0.8);
CGAffineTransform transformTranslate = CGAffineTransformMakeTranslation(0.5, 0.6);
cell.transform = CGAffineTransformConcat(transformScale, transformTranslate);
[tableView bringSubviewToFront:cell];
[UIView animateWithDuration:.4f
delay:0
options:UIViewAnimationOptionAllowUserInteraction
animations:^{
cell.alpha = 1;
//清空 transform
cell.transform = CGAffineTransformIdentity;
} completion:nil];
// 动画3
/*
// 从锚点位置出发,逆时针绕 Y 和 Z 坐标轴旋转90度
CATransform3D transform3D = CATransform3DMakeRotation(M_PI_2, 0.0, 1.0, 1.0);
// 定义 cell 的初始状态
cell.alpha = 0.0;
cell.layer.transform = transform3D;
cell.layer.anchorPoint = CGPointMake(0.0, 0.5); // 设置锚点位置;默认为中心点(0.5, 0.5)
// 定义 cell 的最终状态,执行动画效果
// 方式一:普通操作设置动画
[UIView beginAnimations:@"transform" context:NULL];
[UIView setAnimationDuration:0.5];
cell.alpha = 1.0;
cell.layer.transform = CATransform3DIdentity;
CGRect rect = cell.frame;
rect.origin.x = 0.0;
cell.frame = rect;
[UIView commitAnimations];
// 方式二:代码块设置动画
// [UIView animateWithDuration:0.5 animations:^{
// cell.alpha = 1.0;
// cell.layer.transform = CATransform3DIdentity;
// CGRect rect = cell.frame;
// rect.origin.x = 0.0;
// cell.frame = rect;
// }];
*/
}
42.强制横屏代码
#pragma mark - 强制横屏代码
- (BOOL)shouldAutorotate
{
//是否支持转屏
return NO;
}
- (UIInterfaceOrientationMask)supportedInterfaceOrientations
{
//支持哪些转屏方向
return UIInterfaceOrientationMaskLandscape;
}
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
return UIInterfaceOrientationLandscapeRight;
}
- (BOOL)prefersStatusBarHidden
{
return NO;
}
41.将window上的显示在最外层
[[[[UIApplication sharedApplication] delegate] window] addSubview:topImgView];
40.监测网络状态
只要网络状态发生了变化,在任何一个视图控制器都会给出相应的提示
说明: 这里需要导入第三方库,1. MBProgressHUD 2. AFNetworking
导入头文件 MBProgressHUD.h, AFNetworking.h
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// 应用程序加载完成
UIWindow *window = ((AppDelegate *) [UIApplication sharedApplication].delegate).window;
AFNetworkReachabilityManager *manager = [AFNetworkReachabilityManager sharedManager];
[manager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
// 使用MBProgressHUD三方库创建弹框,给出相应的提示
MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:window animated:YES];
hud.mode = MBProgressHUDModeText;
switch (status) {
case AFNetworkReachabilityStatusNotReachable:
// 弹框提示的内容
hud.labelText = @"世界上最遥远的距离就是没网";
break;
case AFNetworkReachabilityStatusReachableViaWWAN:
hud.labelText = @"2G/3G/4G";
break;
case AFNetworkReachabilityStatusReachableViaWiFi:
hud.labelText = @"WiFi在线";
default:
break;
}
dispatch_async(dispatch_get_global_queue(0, 0), ^{
// 显示时间2s
sleep(2);
dispatch_async(dispatch_get_main_queue(), ^{
// 让弹框消失
[MBProgressHUD hideHUDForView:window animated:YES];
});
});
}];
[manager startMonitoring];
return YES;
}
39.在状态栏显示有网络请求的提示器
//- (void)webViewDidStartLoad:(UIWebView *)webView {
// [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
//}
//- (void)webViewDidFishLoad:(UIWebView *)webView {
// [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
//}
//接收响应
// 在状态栏显示有网络请求的提示器
//- (void)connection:(NSURLConnection*)connection didReceiveResponse:(NSURLResponse*)response{
//
// //网络活动指示器
//
// [UIApplication sharedApplication].networkActivityIndicatorVisible=YES;
//
//}
//隐藏状态栏
//- (BOOL)prefersStatusBarHidden
//
//{
//
// return YES;
//
//}
38.模糊效果
// 模糊效果
UIBlurEffect *effect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];
UIVisualEffectView *test = [[UIVisualEffectView alloc] initWithEffect:effect];
test.frame = self.view.bounds;
test.alpha = 0.5;
[self.view addSubview:test];
35.相对路径
$(SRCROOT)/
34.在storyboard上添加ScrollView
32.返回cell高度
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *string = self.lrcArr[indexPath.row];
CGRect frame = [string boundingRectWithSize:CGSizeMake([UIScreen mainScreen].bounds.size.width, 10000) options:(NSStringDrawingUsesLineFragmentOrigin) attributes:[NSDictionary dictionaryWithObject:[UIFont systemFontOfSize:17] forKey:NSFontAttributeName] context:nil];
return frame.size.height;
}
- UIImageView
NSArray *animationImages; // 把图片赋值给动画数组【帧动画】
NSInteger animationRepeatCount; // 默认是0,无限循环
NSTimeInterval animationDuration; // 执行一轮图片的时间
26.视图是否自动(只是把第一个自动)向下挪64
self.automaticallyAdjustsScrollViewInsets = NO; // 不让系统帮咱们把scrollView及其子类的视图向下调整64
25.问题处理:有时候self是加在parentViewController(父ViewController)上的,self上面是没有navigationController的,但是这时还想使用self父类的navigationController,那么,此时需要第二种方法push过去
[self.navigationController pushViewController:detailViewController animated:YES];
[self.parentViewController.navigationController pushViewController:detailViewController animated:YES];
24.问题处理:cell是有重用机制的,但有时候,我们的cell是自适应高度,但是所有cell的标识都是一个,那么,在重用的时候会出现 有的单元格高,有的单元格矮的情况,和本身想要的frame不匹配,这个时候,只需要给cell上面的视图在懒加载的时候,重新赋frame值就好了。也就是在if判断外,再赋值一次frame。(例如,豆瓣项目电影院列表)
- 容器视图控制器
把一个视图控制器作为容器视图控制器,在这个容器视图控制器上添加多个其他视图控制器,并把其他控制器的视图添加上来
TableViewController *tableViewController = [[TableViewController alloc] init];
[self addChildViewController:tableViewController]; // self在这里就是容器视图控制器
[self.view addSubView:tableViewController.tableView];
使用场景:当我们某个视图控制器要使用多个子界面,并且多个子界面的处理事务的逻辑比较复杂,我们就可以通过这种方式将不同的逻辑处理拆分开,在各自的视图控制器中处理自己的逻辑,而不是所有逻辑都在当前视图控制器中处理。
.22. 程序的退出【了解】
【特别注意】iOS的应用程序在应用程序内部是不允许被退出的,只能通过连击两次HOME键的时候进入程序管理界面 通过上滑退出。如果在应用程序中写了下面的代码,那么在提交程序的时候是不能被审核通过的。所以下面的代码是不允许写的。在这里只是作了解。
exit(0); // 只要执行这个语句,程序就会直接退出
.21. 隐藏手机的状态栏
-(BOOL)prefersStatusBarHidden {
return YES;
}
.20. 代理的安全保护【断是否有代理,和代理是否执行了代理方法】
if (self.delegate && [self.delegate respondsToSelector:@selector(passValueWithArray:)]) {
}
19.按照文字计算高度
- (void)descHeightWithDesc:(NSString *)desc{
CGRect rect = [desc boundingRectWithSize:CGSizeMake(240, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName:self.descLabel.font} context:nil];
//按照文字计算高度
float textHeight = rect.size.height;
CGRect frame = self.descLabel.frame;
frame.size.height = textHeight;
self.descLabel.frame = frame;
}
18.网络请求图片
// NSURL *url = [NSURL URLWithString:urlString];
// NSURLRequest *request = [NSURLRequest requestWithURL:url];
// NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
// UIImage *image = [UIImage imageWithData:data];
//此种写法和上面的操作是一致的,都是同步请求数据。
UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:urlString]]];
return image;
17.substringWithRange: 专门截取字符串的一块肉
NSMakeRange(4,2) 从第4个字符开始截取,长度为2个字符,(字符串都是从第0个字符开始数的哦~!)
self.begin_time = dic[@"begin_time"];
self.end_time = dic[@"end_time"];
NSRange range = NSMakeRange(5, 11);
self.time = [[self.begin_time substringWithRange:range] stringByAppendingString:[@" -- "stringByAppendingString:[self.end_time substringWithRange:range]]];
13.UITextField的字数限制
// viewDidLoad中
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(textFiledEditChanged:)
name:@"UITextFieldTextDidChangeNotification" object:myTextField];
-(void)textFiledEditChanged:(NSNotification *)obj
{
UITextField *textField = (UITextField *)obj.object;
NSString *toBeString = textField.text;
//获取高亮部分
UITextRange *selectedRange = [textField markedTextRange];
UITextPosition *position = [textField positionFromPosition:selectedRange.start offset:0];
// 没有高亮选择的字,则对已输入的文字进行字数统计和限制
if (!position)
{
if (toBeString.length > MAX_STARWORDS_LENGTH)
{
NSRange rangeIndex = [toBeString rangeOfComposedCharacterSequenceAtIndex:MAX_STARWORDS_LENGTH];
if (rangeIndex.length == 1)
{
textField.text = [toBeString substringToIndex:MAX_STARWORDS_LENGTH];
}
else
{
NSRange rangeRange = [toBeString rangeOfComposedCharacterSequencesForRange:NSMakeRange(0, MAX_STARWORDS_LENGTH)];
textField.text = [toBeString substringWithRange:rangeRange];
}
}
}
}
12.处理标签字符串中的空格,换行,/t(制表符)等
- (NSString *)replaceStringWithString :(NSMutableString *)string
{
NSString *string1 = [string stringByReplacingOccurrencesOfString:@"\n" withString:@""] ;
NSString *string2 = [string1 stringByReplacingOccurrencesOfString:@" " withString:@""] ;
NSString *string3 = [string2 stringByReplacingOccurrencesOfString:@"\r" withString:@""] ;
NSString *string4 = [string3 stringByReplacingOccurrencesOfString:@"\t" withString:@""] ;
return string4 ;
}
11.通过2D仿射函数实现小的动画效果(变大缩小) --可用于自定义pageControl中.
[UIView animateWithDuration:0.3 animations:^{
imageView.transform = CGAffineTransformMakeScale(2, 2);
} completion:^(BOOL finished) {
imageView.transform = CGAffineTransformMakeScale(1.0, 1.0);
}];
10.当有多个导航控制器时,一次设置多个导航控制器
UINavigationBar *navBar = [UINavigationBar appearance] ;
// 所有导航条颜色都会改变 -- 一键设置
//navBar.barTintColor = [UIColor yellowColor] ;
[navBar setBackgroundImage:[UIImage imageNamed:@"bg_nav.png"] forBarMetrics:UIBarMetricsDefault] ;
9.UIImage与字符串互转
//图片转字符串
-(NSString *)UIImageToBase64Str:(UIImage *) image
{
NSData *data = UIImageJPEGRepresentation(image, 1.0f);
NSString *encodedImageStr = [data base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
return encodedImageStr;
}
//字符串转图片
-(UIImage *)Base64StrToUIImage:(NSString *)_encodedImageStr
{
NSData *_decodedImageData = [[NSData alloc] initWithBase64Encoding:_encodedImageStr];
UIImage *_decodedImage = [UIImage imageWithData:_decodedImageData];
return _decodedImage;
}
8.UITableViewCell可移动,需要打开的代理方法以及移动过程中调用的代理方法
// tableView可移动 移动完成之后会调用此代理方法
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath
{
}
// 移动过程中调用的代理方法 -- 示例为不能跨区移动
/**
* <#Description#>
*
* @param tableView
* @param sourceIndexPath 所要移动单元格的原始位置
* @param proposedDestinationIndexPath 将要移动到的位置
*
* @return return value description
*/
- (NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath
{
// 移动位置在同一分区
if (sourceIndexPath.section == proposedDestinationIndexPath.section)
{
// 这时允许单元格移动
return proposedDestinationIndexPath ;
}
// 不在同一分区 不让单元格移动,返回原始的indexPath
else
{
return sourceIndexPath ;
}
}
8.隐藏状态栏 修改状态栏风格
-(UIStatusBarStyle)preferredStatusBarStyle
{
return UIStatusBarStyleLightContent; // 暗背景色时使用
}
- (BOOL)prefersStatusBarHidden
{
return YES; // 是否隐藏状态栏
}
6.取消图片的渲染
[button setImage:[[UIImage imageNamed:@"1.jpg" ] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal] forState:UIControlStateNormal] ;
- NSNumber
a.是数字的NS对象的表达形式,如果要把数字添加到数组或者字典中,必须要进行转换,同时要使用数组中的数字,还需要转换成对应的数字。
b.要转换数字可以使用OC提供的包装方法:@(int)
c.要把NSNumber转换成字符串,需要使用stringValue方法
- NSTimer计时器
使用实例代码如下:
// 第一个参数:多长时间会触发一次,以秒为单位
// 第二个参数:如果看到函数的参数有target,一般情况下,都用self
// 第三个参数:SEL,需要调用其他的方法,就是每次时钟被触发的时候,去执行的方法
// 最多可以带一个参数,就是时钟本身
// 第四个参数,暂时不用考虑,设置成nil
// 第五个参数:是否重复,通常会设置YES
_gameTimer = [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:@selector(updateTimer:) userInfo:nil repeats:YES];
a.在时钟触发方法中,可以使用sender.fireDate获取到时钟被触发的时间
b.注意:使用NSTimer的时候,千万不要忘记调用invalidate方法关闭时钟。
c.NSTimer可能不会是及时相应触发时间的,它的执行优先级相对较低,因此,不要使用NSTimer去做实时响应需求较高的周期性操作。
2.根据UILabel里的内容自适应高度
NSString *contentString = [dic objectForKey:@"content"] ; //从字典中提取字符串
CGRect rect = [contentString boundingRectWithSize:CGSizeMake(tableView.bounds.size.width, MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName :[UIFont systemFontOfSize:15]} context:nil] ;
// 内容的自适应高度方法
* @param CGSize 规定文本显示的最大范围
@param options 按照何种设置来计算范围
@param attributes 文本内容的一些属性,例如字体大小,字体类型等 (字体不一样,高度也不一样)
@parma context 上下文 可以规定一些其他的设置 但是一般都是nil
*/
// 枚举值中的 " | " 意思是要满足所有的枚举值设置.
1.根据汉字字符串获取该字符串的拼音然后取得首字母
分享资源 汉字转换为 拼音 获取首字母
//获取拼音首字母(传入汉字字符串, 返回大写拼音首字母)
/*
- (NSString *)firstCharactor:(NSString *)aString
{
//转成了可变字符串
NSMutableString *str = [NSMutableString stringWithString:aString];
//先转换为带声调的拼音
CFStringTransform((CFMutableStringRef)str,NULL, kCFStringTransformMandarinLatin,NO);
//再转换为不带声调的拼音
CFStringTransform((CFMutableStringRef)str,NULL, kCFStringTransformStripDiacritics,NO);
//转化为大写拼音
NSString *pinYin = [str capitalizedString];
//获取并返回首字母
return [pinYin substringToIndex:1];
}
*/
NSString *string = @"" ;
if ([string length])
{
NSMutableString *mutableString = [NSMutableString stringWithString:string] ;
/**
* 由于此方法是在coreFoundation框架下,咱们平时所使用的类型都是Foundation框架下的,所以需要转换类型.
*
* @param string#> string 所需要转换的原字符#>
* @param range#> range 所需要转换字符的范围.如果为0或者是NULL意思是所有字符都转换#>
* @param transform#> transform 转换方式#>
* @param reverse#> reverse 如果为YES,返回原字符串;如果为NO,返回转换之后的字符串#>
*
* @return return value description
*/
// 将所有非英文的字符转换为拉丁字母,并且带声调和重音标识
// __bridge :只改变当前对象的类型,但是不改变对象内存的管理权限
CFStringTransform((__bridge CFMutableStringRef)mutableString , 0,kCFStringTransformToLatin , NO) ;
// 去掉声调
CFStringTransform((__bridge CFMutableStringRef)mutableString , 0,kCFStringTransformStripDiacritics , NO) ;
// 每个单词的首字母大写 后再截取字符串
NSString *str = [[mutableString capitalizedString] substringToIndex:1];
}
100.afnetworking上传图片
[manager POST:url parameters:param constructingBodyWithBlock:^(id _Nonnull formData) {
for (int i = 0; i < data_arr.count; i++) {
//拿当前时间拼接字符串做文件名
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setTimeZone:[NSTimeZone systemTimeZone]];
[formatter setDateFormat:@"yyyyMMddHHmmss"];
NSString* dateString = [formatter stringFromDate:[NSDate date]];
dateString = [NSString stringWithFormat:@"%@_%du.png",dateString,(int)data_arr.count + 1];
// data 转文件流
NSData* data = [[data_arr objectAtIndex:i] objectForKey:@"picData"];
// data = [data_arr objectAtIndex:i];
// NSString *path = NSHomeDirectory();
// DEF_DEBUG(@"path:%@",path);
// NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
// NSString* documentsDirectory = [paths objectAtIndex:0];
// NSString* fullPathToFile = [documentsDirectory stringByAppendingPathComponent:dateString];
//写入文件
//[data writeToFile:fullPathToFile atomically:NO];
// NSString* name = [NSString stringWithFormat:@"file_%d",i + 1];
[formData appendPartWithFileData:data name:@"contract_photo_list[]" fileName:dateString mimeType:@"image/png"];
}
} progress:^(NSProgress * _Nonnull uploadProgress) {
101.强弱引用
/**
Synthsize a weak or strong reference.
Example:
@weakify(self)
[self doSomething^{
@strongify(self)
if (!self) return;
...
}];
*/
#ifndef weakify
#if DEBUG
#if __has_feature(objc_arc)
#define weakify(object) autoreleasepool{} __weak __typeof__(object) weak##_##object = object;
#else
#define weakify(object) autoreleasepool{} __block __typeof__(object) block##_##object = object;
#endif
#else
#if __has_feature(objc_arc)
#define weakify(object) try{} @finally{} {} __weak __typeof__(object) weak##_##object = object;
#else
#define weakify(object) try{} @finally{} {} __block __typeof__(object) block##_##object = object;
#endif
#endif
#endif
#ifndef strongify
#if DEBUG
#if __has_feature(objc_arc)
#define strongify(object) autoreleasepool{} __typeof__(object) object = weak##_##object;
#else
#define strongify(object) autoreleasepool{} __typeof__(object) object = block##_##object;
#endif
#else
#if __has_feature(objc_arc)
#define strongify(object) try{} @finally{} __typeof__(object) object = weak##_##object;
#else
#define strongify(object) try{} @finally{} __typeof__(object) object = block##_##object;
#endif
#endif
#endif
102.关于属性非空的判断
我们通常用nonnull来限定属性的非空状态:
@property (strong, nonatomic, nonnull) NSString *str;
然而很多个属性的情况下,每次都写比较坑爹,所以可以用苹果给我们准备好的宏:
NS_ASSUME_NONNULL_BEGIN
@property (strong, nonatomic) NSString *str1;
@property (strong, nonatomic) NSString *str2;
@property (strong, nonatomic, nullable) NSString *str3;
NS_ASSUME_NONNULL_END
其中nullable设置该参数可以赋值为空
103.UUID
+ (NSString *)UUID {
//MARK:此处的 @"5CKSJSE23P.com.haodf.mainGroup" 字串不能动,否则会导致获取的值错误或者 nil
KeychainItemWrapper *wrapper = [[KeychainItemWrapper alloc] initWithIdentifier:@"HuangyibiaoAppID" accessGroup:@"com.huangyibiao.test.group"];
NSString *UUID = [wrapper objectForKey:(__bridge id)kSecValueData];
if (UUID.length == 0) {
UUID = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
[wrapper setObject:UUID forKey:(__bridge id)kSecValueData];
}
return UUID;
}
104、消除tableView组之间的细线
UIView * headview =[[UIViewalloc]initWithFrame:CGRectMake(0, 0, 0, CGFLOAT_MIN)];
tableView.tableHeaderView = headview;
self.tableView.contentInset = UIEdgeInsetsMake(0.0f, 0.0f, 0.0f, 0.0f);
- (CGFloat) tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
return 0.0f;
}
UIView * headview =[[UIView alloc]initWithFrame:CGRectMake(0, 0, 0, CGFLOAT_MIN)];
_tableview.tableHeaderView = headview;
1000、UIScrollView 滚动收起键盘
keyboardDismissMode
设置为:UIScrollViewKeyboardDismissModeOnDrag
1001、导航栏设置(透明)
//全透明,一般在viewWillAppear
+ (void)createCompletelyTransparentNavigationBar:(UIViewController *)sender
{
[sender.navigationController.navigationBar setBackgroundImage:[UIImage new]
forBarMetrics:UIBarMetricsDefault];
sender.navigationController.navigationBar.shadowImage = [UIImage new];
sender.navigationController.navigationBar.translucent = YES;
sender.navigationController.view.backgroundColor = [UIColor clearColor];
sender.navigationController.navigationBar.backgroundColor = [UIColor clearColor];
}
//恢复成默认,一般在viewWillDisappear
+ (void)createDefaultNavigationBar:(UIViewController *)sender
{
[sender.navigationController.navigationBar setBackgroundImage:nil
forBarMetrics:UIBarMetricsDefault];
}
#pragma mark -
#pragma mark - 自定义导航栏按钮 返回按钮 或者其他按钮
- (void)createCustomNavigationBackOrOtherButton
{
UIButton *backBtn = [UIButton buttonWithType:UIButtonTypeCustom];
backBtn.frame = CGRectMake(0, 0, 32, 32);
[backBtn addTarget:self action:@selector(navCustomBackButtonPressed) forControlEvents:UIControlEventTouchUpInside];
[backBtn setImage:[UIImage imageNamed:@"NavBackCustomImg"] forState:UIControlStateNormal];
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:backBtn];
// self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"NavBackCustomImg"] style:UIBarButtonItemStyleBordered target:self action:@selector(navCustomBackButtonPressed)];
//解决自定义了leftBarbuttonItem左滑返回手势失效了的问题
self.navigationController.interactivePopGestureRecognizer.delegate = (id)self;
}
- (void)navCustomBackButtonPressed
{
[self.navigationController popViewControllerAnimated:YES];
}