文件下载或者上传后需要使用 MD5验证文件的完整性,不可简单的根据上传或下载完成后的回调来判断是否成功。
-
tabview 和 collectionView的长按抖动模式
#pragma mark - 抖动动画
#define Angle2Radian(angle) ((angle) / 180.0 * M_PI)
- (void)shakingAnimation:(UICollectionViewCell *)cell{
CAKeyframeAnimation *anim = [CAKeyframeAnimation animation];
anim.keyPath = @"transform.rotation";
anim.values = @[@(Angle2Radian(-2)), @(Angle2Radian(2)), @(Angle2Radian(-2))];
anim.duration = 0.25;
// 动画次数设置为最大
anim.repeatCount = MAXFLOAT;
// 保持动画执行完毕后的状态
anim.removedOnCompletion = NO;
anim.fillMode = kCAFillModeForwards;
[cell.layer addAnimation:anim forKey:@"shake"];
}
-
逐行读取 txt 文件内容,将所需内容取出
#txt文件文件内容大概是这个样子的,x 和 y 的长度还不一样,但是最前面的是一样的长度,所以下面用的方式不一样
53282 X:13435840.64291;Y:3550350.6154879997
53280 X:13435846.923805503;Y:3550349.5415525
53279 X:13435853.009440003;Y:3550349.639183
53278 X:13435859.062531002;Y:3550349.5740960003
#//获取txt 文件
NSString *pathTxt = [[NSBundle mainBundle] pathForResource:@"iBeaconPoint" ofType:@"txt"];
//逐行添加到数组中
NSArray *arr = [[NSString stringWithContentsOfFile:pathTxt] componentsSeparatedByString:@"\n"];
//准备遍历数组
NSEnumerator *enmu = [arr objectEnumerator];
while (NSString *tmp = [enmu nextObject]) {
//因为取出的内容为 nextObject,所以在下面判断取到的字符串长度不得=0
if (tmp.length == 0) {
break;
}
NSString *strMinor = nil;
NSString *strX = nil;
NSString *strY = nil;
//截取字符串
strMinor = [tmp substringWithRange:NSMakeRange(0,5)];
//扫描对象
NSScanner *scanner = [NSScanner scannerWithString:tmp];
//用不同的特征获取数据
[scanner scanUpToString:@"X:" intoString:nil];
[scanner scanString:@"X:" intoString:nil];
[scanner scanUpToString:@";" intoString:&strX];
[scanner scanUpToString:@"Y:" intoString:nil];
[scanner scanString:@"Y:" intoString:nil];
[scanner scanUpToString:@";" intoString:&strY];
NSLog(@"%@,%@,%@",[strX description],[strY description],[strMinor description]);
}
-
引用下别人的总结知识点,相当全面
http://www.jianshu.com/p/1ff9e44ccc78
-
如何判断文件类型
这是链接,主要还是搜集文件头标示建立数据,以便在后面进行判断http://blog.csdn.net/yagerfgcs/article/details/51427085
-
Xcode注释快捷键
command+option+/ -> 快速注释(不同的位置不一样)
command+/ -> 双斜线
- MacOS终端可以集成了MD5加密功能。输入命令:echo "待加密字符串" | md5
- Widget 使用图片也是必不可少,然而 imageNamed: 和 imageWithContentsOfFile: 两种方式加载都不行,即使设置了文件的 target 为 Widget Extension,需要在其target 内部建立一个 .xcassets 文件即可加载图片。
- dispatch_after 设置延时操作,是进行延时提交到操作队列,并不是先提交队列再延时。
- 防止 app 审核不通过,在自定义目录数据存储的时候,需要在程序中给自定义的目录设置“do not backup”属性,防止数据会被 iCloud 备份,从而被拒上架。
-
注销登录,直接回到登录界面
/**
退出登录后需要 再获取主窗口 然后设置他的根控制器为登录界面
*/
NavController *nav = [[NavController alloc] initWithRootViewController:[[MainLoginController alloc] init]];
[UIApplication sharedApplication].keyWindow.rootViewController = nav;
/
如果要跳转的视图界面已将存在导航栏,则直接
[UIApplication sharedApplication].keyWindow.rootViewController = yourViewController;
-
多层模态视图,直接回到 root 视图,瞒天过海
UIViewController *rootVC = self.presentingViewController;
while (rootVC.presentingViewController) {
rootVC = rootVC.presentingViewController;
}
rootVC.view.alpha = 0.0;
[rootVC dismissViewControllerAnimated:YES completion:nil];
-
导航栏隐藏界面push 到导航栏显示界面的过渡方案
- 1,第一种
//当前界面隐藏
-(void)viewWillAppear(BOOL)animated{
[super viewWillAppear:animated];
[self.navigationController setNavigationBarHidden:YES animated:YES];
}
//下个界面显示
-(void)viewWillAppear(BOOL)animated{
[super viewWillAppear:animated];
[self.navigationController setNavigationBarHidden:NO animated:YES];
}
- 2,第二种 swift 版(其实 OC 也差不多)
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
navigationController?.setNavigationBarHidden(true, animated: true)
}
override func viewDidDisappear(_ animated: Bool) {
super.viewDidDisappear(true)
navigationController?.setNavigationBarHidden(false, animated: true)
}
-
push 界面后自定义返回按钮,需重写滑动手势返回代理方法
1:添加代理<UIGestureRecognizerDelegate>
2:让导航栏成为代理
//使得 nav 成为手势的代理,自定义导航 leftButtonItem 时使用,以代替系统无法在自定义时使用右划返回。
nav.interactivePopGestureRecognizer.delegate = self;
3:开始重写代理方法
//#pragma 以下是当自定义 leftButtonItem 时,需重写右划返回方法,响应原系统右划返回。
-(BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
if (self.viewControllers.count <= 1 ) {
return NO;
}
return YES;
}
//允许同时响应多个手势
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
return YES;
}
-(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
return [gestureRecognizer isKindOfClass: UIScreenEdgePanGestureRecognizer.class];
}
-
启动界面直接强转竖屏(可以自选),其他界面可以按自己要求写
- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
//set statusbar to the desired rotation position
return UIInterfaceOrientationMaskAllButUpsideDown;;
}
-
屏幕强制旋转
1: 有 tabbar 和导航栏的情况,在自定义 tabbarController 里面添加下面代码。如果是自定义 tabbar 控件的话,可以看到下面的自定义tabbar,中间添加了一个类似于微博的发布按钮,在旋转屏幕后本身不在中间了,可以重新设置 layout 方法。
需要在 tabbar 里面处理,添加全局旋转判断
BOOL __shouldAutorotate;
//再注册旋转屏幕的通知
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(autorotateInterface:) name:@"InterfaceOrientation" object:nil];
再添加方法,接收通知信息
-(void)autorotateInterface:(NSNotification *)notifition
{
__shouldAutorotate = [notifition.object boolValue];
NSLog(@"接收到的通知>> %d", __shouldAutorotate);
}
/**
* @return 是否支持旋转
*/
-(BOOL)shouldAutorotate{
NSLog(@"======>> %d", __shouldAutorotate);
return __shouldAutorotate;
}
/**
* 适配旋转的类型
* @return 类型
*/
-(UIInterfaceOrientationMask)supportedInterfaceOrientations
{
if (!__shouldAutorotate) {
return UIInterfaceOrientationMaskPortrait;
}
return UIInterfaceOrientationMaskAllButUpsideDown;
}
2只有导航栏的情况
自定义一个 navigation 类,里面添加方法,在控制器里面使用导航栏的的时候生效。
/**
*
* @return 是否支持旋转
*/
-(BOOL)shouldAutorotate
{
return NO;//这个可以仿照上面的判断添加全局之类的,我的只要竖屏,不要旋转,所以就先这样
}
/**
* 适配旋转的类型
*
* @return 类型
*/
-(UIInterfaceOrientationMask)supportedInterfaceOrientations
{
//旋转类型自己改,按需求来。
return UIInterfaceOrientationMaskPortrait;
}
-
自定义tabbar时,中间添加一个按钮-》移花接木。
1:自定义重写 tabbar
.h 继承 tabbar 重写
@interface MYtabbar : UITabBar
.m
/** 发布按钮 */
@property (nonatomic, strong) UIButton *publishButton;
- (instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
// 添加发布按钮
_publishButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, self.height, self.height)];
[_publishButton setImage:[UIImage imageNamed:@"publish"] forState:UIControlStateNormal];
_publishButton.backgroundColor = [UIColor greenColor];
[_publishButton sizeToFit];
[_publishButton addTarget:self action:@selector(publishClick) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:_publishButton];
}
return self;
}
/**
* 布局子控件
*/
- (void)layoutSubviews
{
[super layoutSubviews];
// tabBar的尺寸
CGFloat width = self.width;
CGFloat height = self.height;
// 按钮索引
int index = 0;
// 按钮的尺寸
CGFloat tabBarButtonW = width / 3;
CGFloat tabBarButtonH = height;
CGFloat tabBarButtonY = 0;
// 设置3个TabBarButton的frame
for (UIView *tabBarButton in self.subviews) {
if (![NSStringFromClass(tabBarButton.class) isEqualToString:@"UITabBarButton"]) continue;
// 计算按钮的X值
CGFloat tabBarButtonX = index * tabBarButtonW;
if (index == 1) { // 给后面2个button增加一个宽度的X值
tabBarButtonX += tabBarButtonW;
}
// 设置按钮的frame
tabBarButton.frame = CGRectMake(tabBarButtonX, tabBarButtonY, tabBarButtonW, tabBarButtonH);
// 增加索引
index++;
}
// 设置发布按钮的位置
self.publishButton.center = CGPointMake(width * 0.5, height * 0.5);
self.publishButton.width = SCREEN_WIDTH/3 ;
}
//重新布局使用,横竖屏切换时需要监听并调用此方法,不然会引起布局错误。上面的 layoutSubviews 走一次。
-(void)layoutIfNeeded{
// 设置发布按钮的位置
self.publishButton.center = CGPointMake(self.width * 0.5, self.height * 0.5);
self.publishButton.width = SCREEN_WIDTH/3 ;
}
其他控制器需要重现布局时调用
在自定义 tabbar 界面初始化重写的
[self setValue:[[MYtabbar alloc] init] forKeyPath:@"tabBar"];
///横竖屏切换时调用此方法
[self.tabBarController.tabBar layoutIfNeeded];
2:简单添加按钮到 tabbar,这个有点类似某直播的效果,按钮可以写的很大,但是触发范围需要重写才能改变。
UIButton *button = [[UIButton alloc]initWithFrame:CGRectMake(0.0,0.0,70,70];
//防止 button 的 image 被压缩变形
UIImage *buttonImage = [[UIImage imageNamed:@"publish"] resizableImageWithCapInsets:UIEdgeInsetsMake(0,0,0,0)];
[button setImage:buttonImage forState:UIControlStateNormal];
button.center = CGPointMake(SCREEN_WIDTH/2,self.tabBar.height/2);
[button addTarget:self action:@selector(publishClick) forControlEvents:UIControlEventTouchUpInside];
[self.tabBar addSubview:button];
3:投机取巧的方法
使用系统自身的 tabba ,添加他的viewControllers时,可以多添加一个,放在数组中间的位置。然后,使用上面的方法,直接自定义按钮添加上去,但是
// 选择指定的控制器视图显示,不可以选择到你写的那个假的抢位置控制器.
[self setSelectedIndex:2];//不谢默认是0
创建的方法
/**
* Tabbar创建
*/
- (void)createSystemTabbar{
MapViewController *mapView = [[MapViewController alloc] init];
DataViewController *dataView = [[DataViewController alloc] init];
PublishViewController *publish = [[PublishViewController alloc] init];#抢位子用的
self.viewControllers = [NSArray arrayWithObjects:
[self createNavWithViewController:mapView WithTitle:@"地图" image:[UIImage imageNamed:@"map_sel"] unselectImage:[UIImage imageNamed:@"map"]],
[self createNavWithViewController:publish WithTitle:@"" image:[UIImage imageNamed:@"publish"] unselectImage:[UIImage imageNamed:@""]],
[self createNavWithViewController:dataView WithTitle:@"数据" image:[UIImage imageNamed:@"data_sel"] unselectImage:[UIImage imageNamed:@"data"]],
nil];
UIButton *button = [[UIButton alloc]initWithFrame:CGRectMake(0.0,0.0,SCREEN_WIDTH/3,self.tabBar.height)];
//防止 button 的 image 被压缩变形
UIImage *buttonImage = [[UIImage imageNamed:@"publish"] resizableImageWithCapInsets:UIEdgeInsetsMake(0,0,0,0)];
[button setImage:buttonImage forState:UIControlStateNormal];
button.center = CGPointMake(SCREEN_WIDTH/2,self.tabBar.height/2);
[button addTarget:self action:@selector(publishClick) forControlEvents:UIControlEventTouchUpInside];
[self.tabBar addSubview:button];
//按钮置顶
//[self.tabBar bringSubviewToFront:button];
// 选择指定的控制器视图显示,不可以选择1.
[self setSelectedIndex:2];
}
-
计算每个月的天数
/**
计算每个月的天数
@param year 年份
@param month 月份
@return 返回天数
*/
- (NSInteger)DaysfromYear:(NSInteger)year andMonth:(NSInteger)month
{
NSInteger num_year = year;
NSInteger num_month = month;
//判断是否是闰年 整除以4、100、400 则为闰年
BOOL isrunNian = num_year%4==0 ? (num_year%100==0? (num_year%400==0?YES:NO):YES):NO;
switch (num_month) {
case 1:case 3:case 5:case 7:case 8:case 10:case 12:{
[self setdayArray:31];
return 31;
}
case 4:case 6:case 9:case 11:{
[self setdayArray:30];
return 30;
}
case 2:{
if (isrunNian) {
[self setdayArray:29];
return 29;
}else{
[self setdayArray:28];
return 28;
}
}
default:
break;
}
return 0;
}
- tabView 的 cell 重用混乱问题,两个不同的解决办法
//指定不同的 identity
NSString *ident = [NSString stringWithFormat:@"InfoCell%zd%zd",indexPath.section,indexPath.row];
InfoCell *cell = [tableView dequeueReusableCellWithIdentifier:ident];
//指定位置
InfoCell *cell = [tableView cellForRowAtIndexPath:indexPath];
-
使用系统的搜索框,自定义样式,重写。
//重写 searchBar ,继承 UIsearchBar
-(void)layoutSubviews{
for (UIView *view in self.subviews) {
for (UIView *subView in view.subviews) {
if ([subView isKindOfClass:[UITextField class]]) {
subView.frame = CGRectMake(0, 0, self.bounds.size.width, self.bounds.size.height);
}
}
}
}
-
线程问题,串行异步,一个子线程循环执行任务
dispatch_queue_t queueA = dispatch_queue_create("bufujquigj", DISPATCH_QUEUE_SERIAL);
for (NSInteger i = 1; i<nn+1; i++) {
dispatch_async(queueA, ^{
dispatch_async(dispatch_get_main_queue(), ^{
//刷新 UI
});
[NSThread sleepForTimeInterval:1.0/nn];
NSLog(@"jbfkjsdkjsdjf: %ld %@",(long)i ,[NSThread currentThread]);
if (i == nn) {
//用来判断第几次执行,不要将这个判断放在外边。
}
});
}
-
根据两点坐标计算方位角
double rads = 0;//角度
double currentX = _currentLocalPoint.x;
double nextX = nextPoint.x;
double currentY = _currentLocalPoint.y;
double nextY = nextPoint.y;
rads = sin(currentX)*sin(nextX) + cos(currentX)*cos(nextX)*cos(nextY-currentY);
rads = sqrt(1-rads*rads);
rads = cos(currentX)*sin(nextY - currentY)/rads;
rads = asin(rads) * 180 / M_PI;//夹角是正数,按需判断转换
if (_currentLocalPoint.y > nextPoint.y) {
rads = -rads;
}