从0总结iOS开发(二)

篇头

很久以前看到一个故事,大概就是一位程序员编程
第一年写程序是 print(“hello,world”);
第二年 try{print(“hello,world”); } catch{}
第五年 封装了成了一个XXprint的类,写了多以的方法
第十年 回到了print(“hello,world”);

简单点的说,我们从学会代码的实现,到学会断言抓异常,到学会优化,最后看到了本质。有点像山里的和尚,小和尚,和尚,老和尚,僧生。

一、项目文件中的规范及内容

1、以Controller文件为例(直接贴代码)

#import "DetailViewController.h"
#import "TestModel.h"
#import "PopView.h"
#import "TestCell.h"


//----->扩展的类
@interface UDDHeadView : UIView

@property (nonatomic,strong) UIImageView *iconImageView;
@property (nonatomic,strong) UILabel *titleLabel;
@property (nonatomic,strong) UIControl *control;

@end

@implementation UDDHeadView

- (instancetype)initWithFrame:(CGRect)frame{

    if (self = [super initWithFrame:frame]) {

        _iconImageView = [[UIImageView alloc]init];
        _iconImageView.contentMode = UIViewContentModeScaleToFill;
        _iconImageView.clipsToBounds = YES;
        [self addSubview:_iconImageView];

        _titleLabel = [[UILabel alloc]init];
        _titleLabel.font = [UIFont systemFontOfSize:14];
        _titleLabel.textAlignment = NSTextAlignmentCenter;
        [self addSubview:_titleLabel];

        _control = [[UIControl alloc]init];
        [self addSubview:_control];

    }
    return self;
}


@end

@interface DetailViewController ()<UITableViewDelegate,UITableViewDataSource,PopViewDelegate>

@property (nonatomic,strong) UILabel *titleLabel;

@property (nonatomic,strong) UILabel *contentLabel;

@property (nonatomic,strong) UITableView *tableView;

@property (nonatomic,strong) NSMutableArray *dataSource;

@property (nonatomic,strong) PopView *popView;

@end

@implementation DetailViewController


//----->这个地方放懒加载
- (UILabel *)titleLabel{
    if (!_titleLabel) {
        _titleLabel = [[UILabel alloc]initWithFrame:CGRectMake(0, 100,[UIScreen mainScreen].bounds.size.width,40)];
    }
    return _titleLabel;
}

- (PopView *)popView{
    if (_popView) {
        _popView = [[PopView alloc]initWithFrame:self.view.bounds];
        _popView.delegate = self;
    }
    return _popView;
}

//------>这个是数据初始化
- (id)init{
    self = [super init];
    if (self) {

    _dataSource = [[NSMutableArray alloc]init];
    }
    return self;
}

//------>固定视图的初始化
- (void)loadView{
    [super loadView];
    [self initView];
}

- (void)initView{
    self.title = @"详情页面";
    self.view.backgroundColor = [UIColor whiteColor];
    [self.view addSubview:self.titleLabel];

    _contentLabel = [[UILabel alloc]initWithFrame:CGRectMake(0, 160,[UIScreen mainScreen].bounds.size.width,40)];
    [self.view addSubview:_contentLabel];
    self.edgesForExtendedLayout = UIRectEdgeNone;
    self.view.backgroundColor = [UIColor whiteColor];
    _tableView = [[UITableView alloc]initWithFrame:[UIScreen mainScreen].bounds style:UITableViewStylePlain];
    [_tableView registerClass:[TestCell class] forCellReuseIdentifier:@"testCellId"];
    _tableView.dataSource = self;
    _tableView.delegate = self;
    [self.view addSubview:_tableView];
    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc]initWithTitle:@"地图" style:UIBarButtonItemStylePlain target:self action:@selector(mapView)];
}

//------>就近原则,放试图或者navbar的点击方法
-(void)mapView{
    NSLog(@"-----地图------");
}

//------> 放系统的的协议代理方法

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    return _dataSource.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{

    TestCell *cell = [tableView dequeueReusableCellWithIdentifier:@"testCellId" forIndexPath:indexPath];
    if (indexPath.row < [_dataSource count]) {
        cell.model = [_dataSource objectAtIndex:indexPath.row];
    }
    return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
}


- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
    return [TestCell heighforTestCell];
}


//------>  放自定义的代理方法

//手机号的监听
- (void)popView:(PopView *)view changeValue:(NSString *)phoneTextFiled{
}

//验证码的监听
- (void)popView:(PopView *)view valiteCodechange:(NSString *)valiteCode{
}

//点击按钮
- (void)popView:(PopView *)view didClickButton:(kClickType)clickType{
}

//------> 动态试图的加载以及网络请求等(耗时操作)
- (void)viewDidLoad {
    [super viewDidLoad];
    _titleLabel.text = _model.title;
    _contentLabel.text = _model.valueString;
    [self.popView show];
}

//------> 剩下用到的生命周期

- (void)viewDidAppear:(BOOL)animated{
    [super viewDidAppear:animated];
}

- (void)viewWillAppear:(BOOL)animated{
    [super viewWillAppear:animated];
}

- (void)viewWillDisappear:(BOOL)animated{
    [super viewWillDisappear:animated];
}





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


@end

这里面会包含一些比较基础的地方。

比如在初始化的时候用new 还是用alloc init,这里简单讲下,new 一般就是创建一个内存片段,然后把这个指针指向这个内存片段,但是alloc init  呢,需要先根据就近原则创建一块内存,然后将这个对象初始化了一下,然后指向那个对象。这里主要有两点,一是内存就近,二是拆分,alloc init 是先创建内存,再初始化。

什么情况下使用lazy load ,这里也做简单的解释。

首先我们做懒加载一个是内存相邻,但是这个优化极其细微。

其二,这个对象有可能不需要创建,就像某个点击某个button 出现一个view ,但是这个view 有可能不出现,不被创建。

其三,重复点击的效果,某个自定义的alert 弹框,我们点击之后出现,然后消失了,再点击又出现了。省去不必要的重复创建某个对象。

再解释下为什么在loadView中创建视图

这个就比较基础,特别了解生命周期的同学都知道loadview是在试图开始加载的时候允许的,那loaddidview呢,这个其实是在nib开始加载的时候运行的,是在loadview之后的。所以我们会在loadView里面创建去初始化一些固定试图,在viewdidload 里面去做逻辑操作。

其他就不一一叙述,每个生命周期里面都有对应的方法。

二、自定义的view 类

typedef enum {
    kClickCancleType = 0,//取消
    kClickConfirmTyoe = 1,//确定
    kClickValiteCodeType = 2,// 获取验证码

}kClickType;

#import <UIKit/UIKit.h>

@protocol  PopViewDelegate;

@interface PopView : UIView

@property (nonatomic,strong) UITextField *phoneFiled;

@property (nonatomic,strong) UITextField *valitedCode;

//验证码view 
@property (nonatomic,strong) UIView *valiteView;

@property (nonatomic,strong) NSString *title;


@property (nonatomic)id <PopViewDelegate>delegate;

- (void)show;

- (void)dismiss;

@end

@protocol  PopViewDelegate<NSObject>

//手机号的监听
- (void)popView:(PopView *)view changeValue:(NSString *)phoneTextFiled;

//验证码的监听
- (void)popView:(PopView *)view valiteCodechange:(NSString *)valiteCode;

//点击按钮

- (void)popView:(PopView *)view didClickButton:(kClickType)clickType;

@end

这里的是一个自定义的弹框。有时候,如何在block和代理里面选择,这也是一个值得思考的问题。代理更偏向于对群体点击事件的一个代理,可以在Controller文件中操作。

block 一个用于点击某button吗,然后将view 中的数据回调回去,而代理更偏向于点击view 里面某个button ,然后告诉代理点击的是那个button 。这里,我把控件全部暴露在.h文件中。可以,实现点击和回调的结合,其实还有是一个字,懒,这个其实是不好的习惯,我们应该在.h文件中展示更少的东西。
还有一个问题就是在预加载文件中写入 你的枚举类型,规范方法。当然如果你要写成轮子的话,就需要写在.h文件中了。

#import "PopView.h"
#import "AppDelegate.h"

#define kAppDelegate (AppDelegate*)[UIApplication sharedApplication].delegate

#define WEAKSELF typeof(self) __weak weakSelf = self;

#define SCREEN_WIDTH    [UIScreen mainScreen].bounds.size.width
#define SCREEN_HEIGHT    [UIScreen mainScreen].bounds.size.height

@interface PopView ()

@property (nonatomic,strong)UIView *bgView;

@property (nonatomic,strong)UIView *pushView;


@property (nonatomic,strong,readonly) UILabel *titleLabel;

@property (nonatomic,strong) UIButton *cancleButton;

@property (nonatomic,strong) UIButton *confirmButton;

@property (nonatomic,strong) UIButton *receiveCheckNumButton;

@end

@implementation PopView

- (instancetype)initWithFrame:(CGRect)frame{


    if (self = [super initWithFrame:frame]) {

        _bgView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)];
        UIControl *control = [[UIControl alloc]initWithFrame:CGRectMake(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT)];
        [_bgView addSubview:control];
        [control addTarget:self action:@selector(clickScreen) forControlEvents:UIControlEventTouchUpInside];
        _bgView.alpha = 0.0;
        _bgView.backgroundColor = [UIColor blackColor];
        [self addSubview:_bgView];


        _pushView = [[UIView alloc]initWithFrame:CGRectMake(50,SCREEN_HEIGHT,SCREEN_WIDTH-100,130)];
        _pushView.backgroundColor = [UIColor whiteColor];
        _pushView.layer.cornerRadius = 8;
        _pushView.layer.masksToBounds = YES;
        [self addSubview:_pushView];

        _titleLabel = [[UILabel alloc]initWithFrame:CGRectMake(0, 10, SCREEN_WIDTH-100, 20)];
        _titleLabel.font = [UIFont systemFontOfSize:15.f];
        [_pushView addSubview:_titleLabel];
        _titleLabel.textAlignment = NSTextAlignmentCenter;

        _cancleButton = [[UIButton alloc]init];
        [_cancleButton setTitle:@"取消" forState:UIControlStateNormal];
        _cancleButton.titleLabel.font = [UIFont systemFontOfSize:14.f];
        [_cancleButton addTarget:self action:@selector(actionButton:) forControlEvents:UIControlEventTouchUpInside];
        [_cancleButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];

        [_pushView addSubview:_cancleButton];

        _confirmButton = [[UIButton alloc]init];
        [_confirmButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
        [_confirmButton setTitle:@"确认" forState:UIControlStateNormal];
        _confirmButton.titleLabel.font = [UIFont systemFontOfSize:14.f];
        [_confirmButton addTarget:self action:@selector(actionButton:) forControlEvents:UIControlEventTouchUpInside];
        [_pushView addSubview:_confirmButton];

        UIView *line = [[UIView alloc]initWithFrame:CGRectMake(0,CGRectGetHeight(_pushView.frame)-40, CGRectGetWidth(_pushView.frame), 1)];
        line.backgroundColor = [UIColor groupTableViewBackgroundColor];
        [_pushView addSubview:line];

        UIView *line1 = [[UIView alloc]initWithFrame:CGRectMake(CGRectGetWidth(_pushView.frame)/2,CGRectGetHeight(_pushView.frame)-40,1, 40)];
        line1.backgroundColor = [UIColor groupTableViewBackgroundColor];
        [_pushView addSubview:line1];


        _phoneFiled =  [[UITextField alloc]initWithFrame:CGRectMake(20,_titleLabel.frame.origin.y+CGRectGetHeight(_titleLabel.frame),CGRectGetWidth(_pushView.frame)-20,30)];
        _phoneFiled.placeholder = @"请输入手机号";
        _phoneFiled.font = [UIFont systemFontOfSize:14.f];
        _phoneFiled.keyboardType = UIKeyboardTypeNumberPad;
        [_phoneFiled addTarget:self action:@selector(valueChange:) forControlEvents:UIControlEventEditingChanged ];
        [_pushView addSubview:_phoneFiled];


        _valiteView = [[UIView alloc]initWithFrame:CGRectMake(0,_phoneFiled.frame.origin.y+CGRectGetHeight(_phoneFiled.frame),CGRectGetWidth(_pushView.frame),30)];
        [_pushView addSubview:_valiteView];


        _valitedCode =  [[UITextField alloc]initWithFrame:CGRectMake(20,0,60,30)];
        _valitedCode.placeholder = @"验证码";
        _valitedCode.font = [UIFont systemFontOfSize:14.f];
        _valitedCode.keyboardType = UIKeyboardTypeNumberPad;
        [_valitedCode addTarget:self action:@selector(ValiteCode:) forControlEvents:UIControlEventEditingChanged];
        [_valiteView addSubview:_valitedCode];


        self.receiveCheckNumButton = [[UIButton alloc]initWithFrame:CGRectMake(100,0,80, 30)];
        [self.receiveCheckNumButton addTarget:self action:@selector(receiveCheckNum) forControlEvents:UIControlEventTouchUpInside];
        [_receiveCheckNumButton setTitle:@"获取验证码" forState:UIControlStateNormal];
        [_receiveCheckNumButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
        [self.receiveCheckNumButton setContentHorizontalAlignment:UIControlContentHorizontalAlignmentRight];
        self.receiveCheckNumButton.titleLabel.font = [UIFont systemFontOfSize:15];
        [_valiteView addSubview:self.receiveCheckNumButton];


    }

    return self;
}



- (void)layoutSubviews{
    [super layoutSubviews];
    _cancleButton.frame = CGRectMake(0,CGRectGetHeight(_pushView.frame)-40,CGRectGetWidth(_pushView.frame)/2,40);
    _confirmButton.frame = CGRectMake(CGRectGetWidth(_pushView.frame)/2,CGRectGetHeight(_pushView.frame)-40,CGRectGetWidth(_pushView.frame)/2,40);
}

- (void)valueChange:(UITextField *)textFiled{


    if ([_delegate respondsToSelector:@selector(popView:changeValue:)]) {
        [_delegate popView:self changeValue:textFiled.text];
    }

    if (textFiled.text.length > 11) {
        textFiled.text = [textFiled.text substringToIndex:11];
    }

}

- (void)ValiteCode:(UITextField *)textFiled{
    if ([_delegate respondsToSelector:@selector(popView:valiteCodechange:)]) {
        [_delegate popView:self valiteCodechange:textFiled.text];
    }
}




- (void)setTitle:(NSString *)title{

    if (_title !=title ) {
        _title = title;
    }
    _titleLabel.text =_title;
}

- (void)show{

    self.frame = [kAppDelegate window].bounds;
    [[kAppDelegate window] addSubview:self];

    WEAKSELF
    [UIView animateWithDuration:0.25 animations:^{
        weakSelf.pushView.frame = CGRectMake(0, 0, SCREEN_WIDTH-100,130);
        weakSelf.pushView.center = self.center;
        weakSelf.bgView.alpha = 0.5f;
    }];
}

- (void)dismiss{

    WEAKSELF
    [UIView animateWithDuration:0.25 animations:^{
        weakSelf.bgView.alpha = 0.0;
        weakSelf.pushView.frame =CGRectMake(50,SCREEN_HEIGHT,SCREEN_WIDTH-100,130);
    } completion:^(BOOL finished) {
        [self removeFromSuperview];
    }];
}

- (void)clickScreen{
    [self dismiss];
}

//获取验证码倒计时
- (void)receiveCheckNum{

    if ([_delegate respondsToSelector:@selector(popView:didClickButton:)]) {
        [_delegate popView:self didClickButton:2];
    }

    __block int timeout=60; //倒计时时间
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_source_t _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0,queue);
    dispatch_source_set_timer(_timer,dispatch_walltime(NULL, 0),1.0*NSEC_PER_SEC, 0); //每秒执行
    dispatch_source_set_event_handler(_timer, ^{
        if(timeout<=0){ //倒计时结束,关闭
            dispatch_source_cancel(_timer);
            dispatch_async(dispatch_get_main_queue(), ^{
                //设置界面的按钮显示 根据自己需求设置
                [self.receiveCheckNumButton setTitle:@"重新获取" forState:UIControlStateNormal];
                self.receiveCheckNumButton.userInteractionEnabled = YES;

            });
        }else{
            int seconds = timeout;
            NSString *strTime = [NSString stringWithFormat:@"%.2d", seconds];
            dispatch_async(dispatch_get_main_queue(), ^{
                //让按钮变为不可点击的灰色

                self.receiveCheckNumButton.userInteractionEnabled = NO;
                //设置界面的按钮显示 根据自己需求设置
                [UIView beginAnimations:nil context:nil];
                [UIView setAnimationDuration:1];
                [self.receiveCheckNumButton setTitle:[NSString stringWithFormat:@"%@秒后重发",strTime] forState:UIControlStateNormal];
                [UIView commitAnimations];
            });
            timeout--;
        }
    });
    dispatch_resume(_timer);
}


- (void)actionButton:(UIButton *)button{

    if (button == _cancleButton) {
        if ([_delegate respondsToSelector:@selector(popView:didClickButton:)]) {
            [_delegate popView:self didClickButton:0];
        }
    }else{
        if ([_delegate respondsToSelector:@selector(popView:didClickButton:)]) {
            [_delegate popView:self didClickButton:1];
        }
    }



}


@end

这里没有使用 masonry 是因为还是有很多项目中没有使用masonry 的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值