iOS 小知识3

UITextField限制输入长度

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
    if (textField.text.length - range.length + string.length > 9) { return NO; }
    return YES;
}

圆形进度条

我对动画一直不是很了解,今天做了一个圆形进度条的动画就搞了半天,今天记录下,以便以后再用:

//绘制底层的灰色圆环
CAShapeLayer *circleLayer = [CAShapeLayer layer];
    circleLayer.frame = CGRectMake(0, 0, 200, 200);
    circleLayer.position = CGPointMake(self.avatarImageView.centerX - 22.5, self.avatarImageView.centerY + 20);
    circleLayer.fillColor = [UIColor clearColor].CGColor;
    circleLayer.lineWidth = 5.0;
    circleLayer.strokeColor = kColorWithHex(0xe3e4e6, 1).CGColor;
    CGRect frame = CGRectMake(0, 0, 200, 200);
    UIBezierPath *circlePath = [UIBezierPath bezierPathWithOvalInRect:frame];
    circleLayer.path = circlePath.CGPath;
    [self.headerView.layer addSublayer:circleLayer];
    
    //设置外层圆环的路径
    CGFloat proportion = (CGFloat)[userInfo.diskUsed longLongValue] / [userInfo.diskSize longLongValue];
    UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter: CGPointMake(self.avatarImageView.centerX - 22.5, self.avatarImageView.centerY + 20) radius:100 startAngle:3 * M_PI / 2 endAngle:3 * M_PI / 2 + M_PI * proportion clockwise:YES];
    
    path.lineCapStyle = kCGLineCapRound;
    path.lineJoinStyle = kCGLineJoinRound;
    path.lineWidth = 5.0;
    [path stroke];
    
//绘制外层的其他颜色
    CAShapeLayer *layer = [CAShapeLayer new];
    layer.lineWidth = 5;
    layer.strokeColor = [UIColor redColor].CGColor;
    layer.fillColor = [UIColor clearColor].CGColor;
    layer.lineCap = kCALineCapRound;
    layer.path = path.CGPath;
    
    UIColor *strokeColor = UIColorBase;
    [strokeColor set];
    [self.headerView.layer addSublayer:layer];
    //执行动画
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];
    animation.removedOnCompletion = NO;
    animation.fillMode = kCAFillModeForwards;
    animation.duration = 0.5;
    animation.fromValue = @(0);
    animation.toValue = @(1);
    [layer addAnimation: animation forKey: @"animation"];

因为对动画不感兴趣,所以一直没有想着去学习这个,短期内应该也不会多放时间在这个上面,希望以后碰到做动画的少一些吧~~~

UICollectionView的坑

当我们在使用 StoryBoard 中添加 UICollectionView 构建静态界面的时候的时候,我建议大家不要用 StoryBoard 了,直接用纯代码构建控制器要更加好一些,理由如下:

1. 你不能拖自定义的 header 里面的控件,系统会提示你重复定义;也就是说你只能找到你的 header  的View 使用 viewWithTag 来 找到 header 里面的子控件,这样是真的很不方便;
2. 静态界面的cell 的 identify 不能相同,虽然一般不需要复用,但是也会导致找到此 cell 的时候一些麻烦;
3. 因为我们有更加灵活的方法,就是使用 XIB 来构建我们的头部和尾部,还有 cell ,这些其实工作量也是差不多的,或者如果你实在要用 StoryBoard ,也建议同学们不要直接在里面拖 UICollectionReusableView 控件,而是自己用代码或者 XIB 去生成  view 然后再放在 StoryBoard, 这样的话,应该会更加灵活;

其实 StoryBoard 作为苹果一直支持的一种构建 UI 的方式,我是建议大家多用的,但是还是有很多坑需要大家去填的,比如我昨天就看到有开发者碰到了使用 StoryBoard 国际化时,在 pod install 的时候,所做的国家化操作全部失效,这也算是一个大坑吧,记录一下.

弃用 .pch

关于 pch 文件,我是不建议在工程中使用的,Apple 也是如此,不建议在工程中使用;原因如下:
1、使用 pch 文件会使得编译速度变慢,因为会在每个头文件中添加 pch 文件中包括的头文件;
2、使用 pch 会有一些隐患,比如使用 C++ 混编的时候,要注意 pch 中添加 #ifdef __OBJC__ #endif

所以,如果你已经使用了 pch 文件或者是你一定要用这个,那么请你注意使用 #ifdef __OBJC__ #endif
#ifdef __cpluscplus #endif 这样会在编译的时候,避免一些麻烦的事情,不然这些问题真的不好找到出问题的原因。

bounds和frame

有时候你会发现子控件与你设置的 initWithFrame 或者之后你再设置 x,y,origin,center 等等感觉有差别的时候,看下该控件的父控件是那个,然后打印出来这两个控件的 frame,最重要的是搞清楚 boundsframe 的区别,这个时候,你会立马发现问题出现在哪里,然后你就 solve your problem 了。

自定义拍照界面

iPhone 的摄像头缩拍到的画面是4:3比例的。所以拍摄预览界面默认也是这个比例。当你设置的预览界面不是这个比例时,会缩小拍摄预览界面或截取一部分摄像头拍到的界面来显示。(一般截取的事靠近底部的部分)。
如:设置 AVLayerVideoGravityResizeAspectFill 后,在 iPhone5 及其之前都是正常的。但是在 iPhone5 之后,拍摄预览界面就比真实拍出来的照片要小了。

错误的分割线====================
设置 AVLayerVideoGravityResizeAspect 后,可能你设置预览拍摄的界面有一部分是黑屏的。(self.captureSession.sessionPreset = AVCaptureSessionPresetPhoto)
链接1
链接2
错误的分割线====================

其实在经过测试后发现,使用AVCaptureSessionPresetPhoto拍出来的照片会非常的大,多拍几张的话,如果直接用数组保存图片,会导致memory暴涨,但是使用AVCaptureSessionPresetHigh,图片会小很多,但是会导致一个问题就是上述的,你拍出来的照片会比你设置的layer看到的真实场景要大一些(即比例并不是你设置的layer的比例),这个时候其实正确处理的姿势如下:

[self.stillImageOutput captureStillImageAsynchronouslyFromConnection:stillImageConnection completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) {
        NSData *jpegData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];
        UIImage *image = [UIImage imageWithData: jpegData];
        image = [image imageByScalingAndCroppingForSize:CGSizeMake(kScreenWidth * 2, (kScreenHeight - 120) * 2)];
        NSData *data = UIImageJPEGRepresentation(image, 0.5);

        ScanModel *model = [[ScanModel alloc] init];
        model.originData = data;
        [self.data addObject: model];
        self.imageView.image = [image see_scaleAspectImageWithSize: CGSizeMake(100, 100)];
        [self checkPhotos];
        button.enabled = YES;
    }];

就是在我们将二进制数据转为图片的时候,将图片进行 resize 操作一次,这次我们设置的 layer 的大小为 CGSizeMake(kScreenWidth, (kScreenHeight - 120)),我 resize image 的大小为两倍的 layer 大小,此时神奇的事情出来了,就是所得到的图片比例正好为我们 layer 设置的比例,这个应该是 apple 自己的问题,但是用这个就解决了问题;

补充:但是AVCaptureSessionPresetPhoto不支持拍视频。用AVCaptureSessionPreset640x480之类的就可以了。

修改status bar的颜色

1、检查 Info.plist 里面,把 UIViewControllerBasedStatusBarAppearance 设置为 NO.(没有的话则添加)
2、在需要改变状态栏颜色的时候用下面的语句:

UIApplication.sharedApplication().setStatusBarStyle(UIStatusBarStyle.Default, animated: true)

你可能感兴趣的:(iOS 小知识3)