阅读870 返回首页    go 阿里云 go 技术社区[云栖]


《iOS6 application development》学习之路:No.5: __bridge,NSTimer和圆角

关于__bridge,第一次碰到类型转换的时候,没有注意到前面是两个_的。废话不多说,进入正题:

由于ARC不能管理Core Foundation Object的生命周期,所以在Core Foundation和ARC之间,我们需要使用到__bridge,__bridge_retained和__bridge_transfer三个转换关键字。

根据苹果官方的文档(https://developer.apple.com/library/ios/#releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html):
__bridge只做类型转换,但是不修改对象(内存)管理权;
__bridge_retained(也可以使用CFBridgingRetain)将Objective-C的对象转换为Core Foundation的对象,同时将对象(内存)的管理权交给我们,后续需要使用CFRelease或者相关方法来释放对象;

__bridge_transfer(也可以使用CFBridgingRelease)将Core Foundation的对象转换为Objective-C的对象,同时将对象(内存)的管理权交给ARC。

NSTimer

API里面NSTimer 是木有暂停继续的方法的,只有fire和invalidate,前者是开工的意思,后者是废掉的意思,如果用废掉来代替暂停的功能?显然是不对的。那肿么办呢?其实NSTimer 有一个属性叫 fireDate ,啥意思呢?fireDate么,就是fire 的开始时间所以我们就有了思路了。

暂停: [timer setFireDate:[NSDate distantFuture]]; 

distantFuture,就是问你未来有多远呢?好远好远就是无法到达的时间,所以 timer就一直等待不 fire了。也就是暂停了。

继续: [timer setFireDate:[NSDate date]]; 

这个当然就是把fire 的时间设置为当前时刻,所以timer就立刻开工啦!

圆角按钮

在做开发的过程中,发现XCode5.x和iOS7.x中的按钮没有以前的圆角模式了,google了一下发现了正解:

在Xcode 4的圆形按钮...似乎已被替换...”.

确认它肯定 有 被取代:

圆角矩形按钮被弃用的iOS 7.相反,使用
  系统按钮,也就是说,类型UIButtonTypeSystem的一个UIButton对象.

7的iOS系统的按钮不包括边框或背景的外观.
  系统按钮可以包含一个图形符号或文字标题,它
  可以指定一个色调的颜色或接受其父的颜色.

...

如果你需要显示一个按钮,包括边框,使用一个按钮
  输入UIButtonTypeCustom并提供一个自定义的背景图片.

Apple iOS 7 Transition Guide 号码. 45,“圆角矩形按钮”

所以,苹果公司的建议是使用一个背景图像.

但是不是说我们就真的没有办法使用圆角的按钮了,虽然在IB中没法设定按钮为圆角,但是我们仍然可以通过在程序中手动更改按钮的形状,位置,背景颜色等等:

self.goButton.backgroundColor = [UIColor greenColor];
    [self.goButton.layer setMasksToBounds:YES];
    [self.goButton.layer setCornerRadius:10.0];
    [self.goButton.layer setBorderWidth:2.0];
    [self.goButton.layer setBorderColor:(__bridge CGColorRef)([UIColor redColor])];
    [self.goButton setTitleColor:[UIColor redColor] forState:UIControlStateHighlighted];
之前google了一下, 说setMasksToBounds是必须的,不然会改掉后面的背景,但是我实际中发现设置成YES和NO都没有反应。

setCornerRadius 就是指定圆角的弧度,如果你设置成了90°,呵呵,自己试验下是什么效果吧。

setBorderwidth和color是设置边框的颜色和宽度。注意颜色需要用到CGColorRef,这里需要使用开篇介绍的__Bridge做类型转化。不过值得一提的是,这个转换是XCode的错误纠正机制提示我完成的,赞一个。


一个程序:

程序截图我就不放了,很简单,一个label,两个按钮,让点击go的时候,开始数数,0.1秒+1, 显示在label上,然后go按钮变成stop,点击后暂停计时,再点一下继续;另一个按钮是restart。直接上代码。

.h

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController

@property (weak, nonatomic) IBOutlet UILabel *theCount;
@property (weak, nonatomic) IBOutlet UIButton *goButton;
@property (weak, nonatomic) IBOutlet UIButton *restartButton;

- (void)countUp;
- (IBAction)click:(id)sender;
- (IBAction)reStart:(id)sender;

@end

.m

#import "ViewController.h"

@interface ViewController (){
    int _count;
    UIBackgroundTaskIdentifier _counterTask;
    NSTimer* _theTimer;
}

@end

@implementation ViewController
- (void)viewDidLoad
{
    [super viewDidLoad];
	// Do any additional setup after loading the view, typically from a nib.
    _counterTask = [[UIApplication sharedApplication]
                    beginBackgroundTaskWithExpirationHandler:^{
                        //
                    }];
    _count = 0;
    
    //set the button's style
//    self.goButton.frame = CGRectMake(40, 400, 50, 30);
    self.goButton.backgroundColor = [UIColor greenColor];
    [self.goButton.layer setMasksToBounds:YES];
    [self.goButton.layer setCornerRadius:10.0];
    [self.goButton.layer setBorderWidth:2.0];
    [self.goButton.layer setBorderColor:(__bridge CGColorRef)([UIColor redColor])];
    [self.goButton setTitleColor:[UIColor redColor] forState:UIControlStateHighlighted];
    

}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (void)countUp{
    if (_count ==1000) {
        [_theTimer invalidate];
        _theTimer = nil;
        [[UIApplication sharedApplication] endBackgroundTask:_counterTask];
    } else {
        _count++;
        NSString* currentCount;
        currentCount = [[NSString alloc] initWithFormat:@"%d",_count];
        self.theCount.text = currentCount;
    }
}

- (IBAction)click:(id)sender {
    if ([self.goButton.titleLabel.text isEqualToString:@"Go"]) {
        [self.goButton setTitle:@"Stop" forState:UIControlStateNormal];
        if (_count == 0) {
            _theTimer =[NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(countUp) userInfo:nil repeats:YES];
        }else{
            [_theTimer setFireDate:[NSDate date]];
        }
    } else {
        [self.goButton setTitle:@"Go" forState:UIControlStateNormal];
        //Pause;
        [_theTimer setFireDate:[NSDate distantFuture]];
    }
    
}

- (IBAction)reStart:(id)sender {
    [_theTimer invalidate];
    _count = 0;
    _theTimer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(countUp) userInfo:nil repeats:YES];
}


@end

最后说个小插曲,之前想试验一个程序,就是在地图上显示一个图钉坐标,但是怎么试都不行,各种崩溃。。。后来研究了半天发现。。。是坐标给错了,然后在wiki上研究了半天坐标系,经度的范围是【-180,180】,纬度的范围是[-85.xxxx , 85.xxx]为什么纬度不是[-90,90],因为是坐标系都是用的正方形盖过去的,可以想象,南北极这种地方肯定盖不住了,就忽略了。。。于是,企鹅和北极熊表示强烈抗议。。。。

最后更新:2017-04-03 05:38:55

  上一篇:go 从产品角度考虑优秀员工的评定
  下一篇:go C#读书笔记