上海市2019春季招生考试完美落幕,今天不写代码,抽点时间跟这个世界谈谈自己。

创建博客这个念头来自于我初二时候的灵光一现,对于那个时候没见过世面的中学生来说,拥有个人网站是一件多么酷的事情。从那时起,我就开始折腾个人网站。

我仍然记得我当时的个人网站是 http://cuffer.com/ 经过一年的折腾后,博客正式关闭了,虚拟主机与域名也都被服务商回收。

没错,一个没有采用 SSL 加密的博客,充满着未知风险,尽管博客并没有什么实质性的东西,纯粹是为了满足内心的虚荣心。

如果你问我,写个人博客有什么意义,QQ空间或者微信朋友圈难道不也可以拥有相同的作用吗?如果你这么想,那便错了。

写博客的好处:

  1. 高度自由的撰写平台
  2. 优雅的个人页面展示
  3. 数据自我保管,不怕丢失
  4. 一个高度自由的情感回忆载体
  5. 增加公司求职成功几率,在同类脱颖而出

最后一点听起来很功利是吧?但是又何尝不是这样的呢?一个好的技术博客能够带给不只是知识的积累,也完美得诠释了互联网分享精神。博客上每一篇技术博文,都是在为互联网做贡献,甚至能够指引技术小白少走弯路。这也便是我为什么要坚持写博客,而不是去朋友圈或者其他社交平台分享自我,因为只有自己的博客,才是一片自由的、属于自己的空间。

因为项目有需求要写卡片效果,就自己动手了写一个,发现效果还不错。打算以 “PYCardView” 的名字开源。

Usage:

//1. 引入头文件
#import "PYCardView.h"
//2. 创建对象
PYCardView *cView = [PYCardView alloc]initWithFrame:CGRectMake(x,y,w,h)];

若使用 nib ,使用 registerNib:注册,dequeue 时会调用 cell 的 -(void)awakeFromNib

-(void)awakeFromNib
{
    //重写初始化方法
}

不使用 nib ,使用 registerClass: 注册, dequeue时会调用 cell 的 - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier

#pragma mark - 重写初始化方法
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self) {
       //重写初始化方法
    }
    return self;
}

当你使用 SDAutoLayout 对一个 UIImageView 进行宽高布局的时候,会出现与 CornerRadius 冲突的情况。

- (UIImageView *)userAvatarImageView{
    
    if (!_userAvatarImageView) {
        _userAvatarImageView = [[UIImageView alloc]init];
        //圆角设置
        _userAvatarImageView.layer.cornerRadius = _userAvatarImageView.frame.size.width / 2;
        _userAvatarImageView.layer.masksToBounds = YES;//enable imageView to take effect
    }
    return _userAvatarImageView;
}

因为 SDAutoLayout 进行了宽高布局,导致圆角失效。

self.userAvatarImageView.sd_layout
.topSpaceToView(self.contentView, 12)
.leftSpaceToView(self.contentView, 12)
.widthIs(self.frame.size.height - 2 * 12)//因为在这里进行了宽高设置
.heightIs(self.frame.size.height - 2 * 12);

解决方案:调用 sd_cornerRadiusFromHeightRatio 的 getter 方法进行设置

self.userAvatarImageView.sd_cornerRadiusFromHeightRatio = @(0.5); //解决头像不是圆角的 BUG

假设我们需要达成的需求:在 View 文件中包含一个 UIButton 控件且包含 selector 方法,需求:在 Controller 中对其调用。

准备文件:

  • SpecificView.h & SpecificView.m
  • UIViewController.h & UIViewController.m

解决方法:

  • 通过暴露属性的方式来达到目的(这里就不谈了,自行百度
  • 采用代理模式。代理模式用大白话说就是:委托方让代理方代替自己执行一定的动作

代理模式:

首先,在 SpecificView.h 中声明 Delegate 代理:

@protocol ScuserLoginContainerDelegate <NSObject>
- (void)onBtnClick:(UIButton *)sender;
@end
@interface SpecificView : UIView
@property (nonatomic, weak)id<ScuserLoginContainerDelegate> delegate;
@end

Delegate 的声明方法如下:

@protocol 协议名称 <NSObject>
- (void)协议方法;

注意:在这里,务必使用 weak 修饰符,防止出现“循环引用”。

@propery (nonatomic, weak)id<协议名称> delegate;

然后,在 SpecificView.m 中实现相关方法:

@interface SpecificView ()
//声明在.m中的按钮对外部不可见
@property (strong, nonatomic) UIButton *myBtn;

@end

@implementation MyView
//初始化
- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self)
    {
        _myBtn = [[UIButton alloc] initWithFrame:CGRectMake(140, 100, 100, 50)];
        _myBtn.backgroundColor = [UIColor redColor];
        //为按钮设置目标-动作,其中目标是self即包含该按钮的view自身,动作是有目标(view)提供的myBtnClick:方法
        [_myBtn addTarget:self
                   action:@selector(myBtnClick:) forControlEvents:UIControlEventTouchUpInside];
        [self addSubview:_myBtn];
    }
    
    return self;
}
// view 中按钮的事件
- (void)myBtnClick:(UIButton *)btn
{
    NSLog(@"Method in view");
    //在回调代理方法时,首先判断自身的代理是否实现了代理方法,否则会导致崩溃
    //如果自身代理实现了代理方法,在该方法中回调代理实现的具体的代理方法
    if ( [self.delegate respondsToSelector:@selector(onBtnClick:)] )
    {
        [self.delegate onBtnClick:btn];
    }
    else
    {
        NSLog(@"BtnClick: haven't found in delegate.");
    }
}
@end

接着,在 UIViewController.m 中遵循协议,创建 SpecificView 对象并且设置代理为 self ,在这里即是 UIViewController 。

SpecificView *container = [[SpecificView alloc]initWithFrame:self.view.bounds];
container.delegate = self;

最后,直接调用协议方法。

- (void)onBtnClick:(UIButton *)sender{
    //TODO 完成点击按钮后的方法
}

总结:采用代理模式能够实现 view 和 controller 之间的解耦。这是因为由于按钮事件是在 view 中绑定的,而不是在 controller 中绑定的,因此使用该 view 的类只需要实现相应的代理方法就可以定制按钮点击后的事件了,这也更加方便了 view 的复用,体现了 view 与 controller 解耦合的优势。