phphub_iOS客户端源码剖析

1.架构概览


2.EssentialListViewController (精华控制器)


2.1 MVC之控制器Controller

block回调:



与服务器交互获取数据,并通过block回调 回传数据



block回调模式详解:
代码是通过下面的方法一层一层调用下去的,而数据是通过block回调从最后一层一层 回调 回传 过来的

#pragma mark 与服务器交互获取数据然后 回调block callback处理从服务器获得的数据

    [selffetchDataSource:callbackatPage:1];


- (void)fetchDataSource:(BaseResultBlock)callback atPage:(NSUInteger)atPage {

    [[TopicModelInstance]getExcellentTopicList:callbackatPage:atPage];

}


- (id)getExcellentTopicList:(BaseResultBlock)block atPage:(NSInteger)pageIndex {

    return [_apigetExcellentTopicList:blockatPage:pageIndex];

}


- (id)getExcellentTopicList:(BaseResultBlock)block atPage:(NSInteger)pageIndex {

    NSString *urlPath = [selfgetUrlPathWithFilter:@"excellent"atPage:pageIndex];

    

    return [selfgetTopicListByUrlPath:urlPathblock:block];

}


- (id)getTopicListByUrlPath:(NSString *)urlPath block:(BaseResultBlock)block{

    BaseRequestSuccessBlock successBlock = ^(NSURLSessionDataTask *__unused task,id rawData) {

        NSMutableDictionary *data = [(NSDictionary *)rawDatamutableCopy];

        data[@"entities"] = [TopicEntityarrayOfEntitiesFromArray:data[@"data"]];

        data[@"pagination"] = [PaginationEntityentityFromDictionary:data[@"meta"][@"pagination"]];

        if (block) block(data, nil);

    };

    

    BaseRequestFailureBlock failureBlock = ^(NSURLSessionDataTask *__unused task,NSError *error) {

        if (block) block(nil, error);

    };

    

    return [[BaseApiclientGrantInstance]GET:urlPath

                                   parameters:nil

                                      success:successBlock

                                      failure:failureBlock];

}



- (NSURLSessionDataTask *)GET:(NSString *)URLString

                   parameters:(id)parameters

                      success:(void (^)(NSURLSessionDataTask *task,id responseObject))success

                      failure:(void (^)(NSURLSessionDataTask *task,NSError *error))failure

{

    NSURLSessionDataTask *dataTask = [selfdataTaskWithHTTPMethod:@"GET"URLString:URLStringparameters:parameters success:success failure:failure];


    [dataTask resume];


    return dataTask;

}



2.2MVC之视图


下面是精华控制器用到的表格和cell


cell的封装剖析(见我在源码中添加的注释)
//
//  TopicListCell.m
//  PHPHub
//
//  Created by Aufree on 9/21/15.
//  Copyright (c) 2015 ESTGroup. All rights reserved.
//

#import "TopicListCell.h"
#import "BaseView.h"
#import "UserProfileViewController.h"

#import "Masonry.h"
#import "NSDate+DateTools.h"

static CGFloat topicListCellAvatarHeight = 38;

@interface TopicListCell ()
@property (nonatomic, strong) BaseView *baseView;
@property (nonatomic, strong) UIImageView *avatarImageView;
@property (nonatomic, strong) UIImageView *circleImageView;
@property (nonatomic, strong) UILabel *topicTitleLabel;
@property (nonatomic, strong) UILabel *topicInfoLabel;
@property (nonatomic, strong) UILabel *topicRepliesCountLabel;
@property (nonatomic, assign) BOOL didSetupConstraints;
@end

@implementation TopicListCell
#pragma mark 模型set方法
- (void)setTopicEntity:(TopicEntity *)topicEntity {
    _topicEntity = topicEntity;
    
    [self.contentView addSubview:self.baseView];
    
    NSURL *URL = [BaseHelper qiniuImageCenter:_topicEntity.user.avatar withWidth:@"76" withHeight:@"76"];
#pragma mark SDWebImage
    [_avatarImageView sd_setImageWithURL:URL placeholderImage:[UIImage imageNamed:@"avatar_placeholder"]];
    _topicTitleLabel.text = _topicEntity.topicTitle;
    _topicInfoLabel.text = [NSString stringWithFormat:@"%@ • 最后由 %@ • %@", _topicEntity.node.nodeName, _topicEntity.lastReplyUser.username, [_topicEntity.updatedAt timeAgoSinceNow]];
    NSNumber *repliesCount = _topicEntity.topicRepliesCount;
    _topicRepliesCountLabel.text = repliesCount.integerValue > 99 ? @"99+" : repliesCount.stringValue;
    
    if (!_didSetupConstraints) {
        self.didSetupConstraints = YES;
        [self addAutoLayoutToCell];
    }
}
#pragma mark set方法创建子控件
- (BaseView *)baseView {
    if (!_baseView) {
        _baseView = [[BaseView alloc] init];
        
        [_baseView addSubview:self.avatarImageView];
        [_baseView addSubview:self.circleImageView];
        [_baseView addSubview:self.topicTitleLabel];
        [_baseView addSubview:self.topicInfoLabel];
        [_baseView addSubview:self.topicRepliesCountLabel];
    }
    return _baseView;
}

- (UIImageView *)avatarImageView {
    if (!_avatarImageView) {
        _avatarImageView = [[UIImageView alloc] initWithFrame:CGRectMake(10, 10, topicListCellAvatarHeight, topicListCellAvatarHeight)];
        _avatarImageView.contentMode = UIViewContentModeScaleAspectFill;
        _avatarImageView.userInteractionEnabled = YES;
#pragma mark 为cell上的图片添加手势
        UITapGestureRecognizer *tapAvatar = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didTapAvatarImageView)];
        [_avatarImageView addGestureRecognizer:tapAvatar];
    }
    return _avatarImageView;
}

- (UIImageView *)circleImageView {
    if (!_circleImageView) {
        _circleImageView = [[UIImageView alloc] initWithFrame:CGRectMake(10, 10, topicListCellAvatarHeight, topicListCellAvatarHeight)];
        _circleImageView.image = [UIImage imageNamed:@"corner_circle"];
    }
    return _circleImageView;
}

- (UILabel *)topicTitleLabel {
    if (!_topicTitleLabel) {
        _topicTitleLabel = [[UILabel alloc] init];
        _topicTitleLabel.font = [UIFont fontWithName:FontName size:14];
        _topicTitleLabel.numberOfLines = 2;
    }
    return _topicTitleLabel;
}

- (UILabel *)topicInfoLabel {
    if (!_topicInfoLabel) {
        _topicInfoLabel = [[UILabel alloc] init];
        _topicInfoLabel.height = 15;
        _topicInfoLabel.font = [UIFont fontWithName:FontName size:11];
        _topicInfoLabel.numberOfLines = 1;
        _topicInfoLabel.textColor = [UIColor colorWithWhite:0.773 alpha:1.000];
    }
    return _topicInfoLabel;
}

- (UILabel *)topicRepliesCountLabel {
    if (!_topicRepliesCountLabel) {
        _topicRepliesCountLabel = [[UILabel alloc] init];
        _topicRepliesCountLabel.font = [UIFont fontWithName:FontName size:11];
        _topicRepliesCountLabel.numberOfLines = 1;
        _topicRepliesCountLabel.textColor = [UIColor whiteColor];
        _topicRepliesCountLabel.textAlignment = NSTextAlignmentCenter;
        _topicRepliesCountLabel.backgroundColor = [UIColor clearColor];
        _topicRepliesCountLabel.layer.backgroundColor = [UIColor colorWithRed:0.392 green:0.702 blue:0.945 alpha:1.000].CGColor;
    }
    return _topicRepliesCountLabel;
}
#pragma mark 自动布局
- (void)addAutoLayoutToCell {
    CGFloat baseViewMargin = 8;
    CGFloat topicTitleMargin = 10;
    CGFloat topicTitleOffset = self.avatarImageView.width + topicTitleMargin * 2;
    
    [self.baseView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(self.contentView).offset(0);
        make.left.equalTo(self.contentView.mas_left).offset(baseViewMargin);
        make.right.equalTo(self.contentView.mas_right).offset(-baseViewMargin);
        make.bottom.equalTo(self.contentView).offset(-baseViewMargin);
    }];
    
    [self.topicTitleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(self.baseView.mas_top).offset(topicTitleMargin);
        make.left.equalTo(self.baseView.mas_left).offset(topicTitleOffset);
        make.right.equalTo(self.topicRepliesCountLabel.mas_left).offset(-topicTitleMargin);
    }];
    
    [self.topicInfoLabel mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.equalTo(self.topicTitleLabel.mas_bottom).offset(baseViewMargin);
        make.left.equalTo(self.baseView.mas_left).offset(topicTitleOffset);
        make.right.equalTo(self.topicRepliesCountLabel.mas_left).offset(-topicTitleMargin);
        make.bottom.equalTo(self.baseView).offset(-topicTitleMargin);
    }];
    
    [self.topicRepliesCountLabel mas_makeConstraints:^(MASConstraintMaker *make) {
        CGFloat topicRepliesCountHeight = 20;
        _topicRepliesCountLabel.layer.cornerRadius = topicRepliesCountHeight/2;
        _topicRepliesCountLabel.layer.shouldRasterize = YES;
        make.size.mas_equalTo(CGSizeMake(topicRepliesCountHeight, topicRepliesCountHeight));
        make.centerY.mas_equalTo(self.baseView.mas_centerY);
        make.right.equalTo(self.baseView).offset(-10);
    }];
}


#pragma mark Tap User Avatar 点击cell上的图片就调用  并创建控制器跳转到用户详情控制器

- (void)didTapAvatarImageView {
    UserProfileViewController *userProfileVC = [[UIStoryboard storyboardWithName:@"UserProfile"
                                                                          bundle:[NSBundle mainBundle]]
                                                instantiateViewControllerWithIdentifier:@"userprofile"];
    userProfileVC.userEntity = _topicEntity.user;//传递模型
    [JumpToOtherVCHandler pushToOtherView:userProfileVC animated:YES];
}

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
    if ([[gestureRecognizer view] isKindOfClass:[UITableViewCell class]]) {
        return NO;
    }
    return YES;
}

@end


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值