Sian 发表于 2014-4-19 00:38:06

ios实战开发之仿新浪微博(第六讲:微博数据展示一)

1、效果演示

http://player.youku.com/player.php/sid/XNzAwNzI5Mzg4/v.swf

2、设计说明

2.0 无相关基础请先参照前面几讲的内容
2.1 设计框架模型SAStatusFrame类,用来保存微博内容及各控件尺寸与位置,参考链接:ios实战开发之代码创建Cell(演示新浪微博)
2.2 修改SAStatusTool类,修改数据模型数组(之前数据模型数组保存的对象为SAStatus模型,现保存SAStatusFrame模型)
2.3 设计SAStatueCell类,自定义TableViewCell,参考链接:ios实战开发之代码创建Cell(演示新浪微博)
2.4 数据模型初始化之后已将各Cell的尺寸位置及内容均已计算好,因此,直接将取数据模型中的值即可轻松准确展示各Cell的值及视图
2.5 参考模型图:


3、关键代码
SAStatus.h
//
//SAStatus.h
//SianWeibo
//
//Created by yusian on 14-4-16.
//Copyright (c) 2014年 小龙虾论坛. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "SAStatusUser.h"

@interface SAStatus : NSObject

@property (nonatomic, copy)   NSString      *text;            // 正文
@property (nonatomic, strong)   SAStatusUser    *user;            // 用户
@property (nonatomic, copy)   NSString      *createdAt;         // 创建时间
@property (nonatomic, copy)   NSString      *source;            // 来源
@property (nonatomic, strong)   SAStatus      *retweetedStatus;   // 转发体
@property (nonatomic, assign)   NSInteger       repostsCount;       // 转发数
@property (nonatomic, assign)   NSInteger       commentsCount;      // 评论数
@property (nonatomic, assign)   NSInteger       attitudesCount;   // 点赞数
@property (nonatomic, strong)   NSArray         *picUrls;         // 配图

- (id)initWithDict:(NSDictionary *)dict;

+ (id)statusWithDict:(NSDictionary *)dict;

@end

SAStatus.m
//
//SAStatus.m
//SianWeibo
//
//Created by yusian on 14-4-16.
//Copyright (c) 2014年 小龙虾论坛. All rights reserved.
//

#import "SAStatus.h"

@implementation SAStatus

- (id)initWithDict:(NSDictionary *)dict
{
    if (self = ) {
      self.text = dict[@"text"];                                    // 正文
      self.user = ];    // 用户
      self.createdAt = dict[@"created_at"];                           // 创建时间
      self.source = dict[@"source"];                                  // 来源
      self.repostsCount = intValue];          // 转发数
      self.commentsCount = intValue];      // 评论数
      self.attitudesCount = intValue];      // 点赞数
      self.picUrls = dict[@"pic_urls"];                               // 配图
      
      NSDictionary *retweetedStatus = dict[@"retweeted_status"];
      if (retweetedStatus) {                                          // 转发体(被转载的微博内容)
            
            self.retweetedStatus = [ initWithDict:retweetedStatus];
            
      }
    }
    return self;
}

+ (id)statusWithDict:(NSDictionary *)dict
{
    return [ initWithDict:dict];
}

@end

SAStatusUser.h
//
//SAStatusUser.h
//SianWeibo
//
//Created by yusian on 14-4-16.
//Copyright (c) 2014年 小龙虾论坛. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface SAStatusUser : NSObject

@property (nonatomic, copy)   NSString    *screenName;      // 昵称
@property (nonatomic, copy)   NSString    *profileImageUrl;   // 头像
@property (nonatomic, assign)   BOOL      verified;         // 是否验证
@property (nonatomic, assign)   NSInteger   verifiedType;       // 验证类型
@property (nonatomic, assign)   NSInteger   mbrank;             // 会员等级
@property (nonatomic, assign)   NSInteger   mbtype;             // 会员类型

- (id)initWithDict:(NSDictionary *)dict;

+ (id)statusUserWithDict:(NSDictionary *)dict;

@end

SAStatusUser.m
//
//SAStatusUser.m
//SianWeibo
//
//Created by yusian on 14-4-16.
//Copyright (c) 2014年 小龙虾论坛. All rights reserved.
//

#import "SAStatusUser.h"

@implementation SAStatusUser

- (id)initWithDict:(NSDictionary *)dict
{
    if (self = ) {
      self.screenName = dict[@"screen_name"];                     // 昵称
      self.profileImageUrl = dict[@"profile_image_url"];          // 头像
      self.verified = boolValue];            // 是否验证
      self.verifiedType = integerValue];// 验证类型
      self.mbrank = integerValue];               // 会员等级
      self.mbtype = integerValue];               // 会员类型
    }
    return self;
}

+ (id)statusUserWithDict:(NSDictionary *)dict
{
    return [ initWithDict:dict];
}

@end

SAStatusFrame.h
//
//SAStatusFrame.h
//SianWeibo
//
//Created by yusian on 14-4-18.
//Copyright (c) 2014年 小龙虾论坛. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "SAStatus.h"
#define kInterval 10
#define kProfileWH 40
#define kScreenNameFount
#define kTimeFont
#define kSourceFont kTimeFont
#define kTextFount
#define kReScreenNameFont
#define kReTextFont kReScreenNameFont

@interface SAStatusFrame : NSObject

@property (nonatomic, readonly) CGRect      profile;      // 头像
@property (nonatomic, readonly) CGRect      screenName;   // 昵称
@property (nonatomic, readonly) CGRect      time;         // 时间
@property (nonatomic, readonly) CGRect      source;         // 来源
@property (nonatomic, readonly) CGRect      text;         // 正文
@property (nonatomic, readonly) CGRect      image;          // 配图
@property (nonatomic, readonly) CGRect      retweet;      // 转发体视图
@property (nonatomic, readonly) CGRect      reScreenName;   // 转发体昵称
@property (nonatomic, readonly) CGRect      reText;         // 转发体正文
@property (nonatomic, readonly) CGRect      reImage;      // 转发体配图

@property (nonatomic, readonly) CGFloat   cellHeight;   // 行高
@property (nonatomic, strong)   SAStatus    *status;      // 数据模型



@end

SAStatusFrame.m
//
//SAStatusFrame.m
//SianWeibo
//
//Created by yusian on 14-4-18.
//Copyright (c) 2014年 小龙虾论坛. All rights reserved.
//

#import "SAStatusFrame.h"

@implementation SAStatusFrame

-(void)setStatus:(SAStatus *)status
{
    _status = status;
    CGSize screenSize = .applicationFrame.size;
   
    // 1、设置头像尺寸位置;
    CGFloat profileX = kInterval;
    CGFloat profileY = kInterval;
    _profile = CGRectMake(profileX, profileY, kProfileWH, kProfileWH);
   
    // 2、设置昵称尺寸位置;
    CGFloat screenNameX = CGRectGetMaxX(_profile) + kInterval;
    CGFloat screenNameY = profileY;
    CGSize screenNameSize = ;
    _screenName = (CGRect){{screenNameX, screenNameY}, screenNameSize};
   
    // 3、设置时间尺寸位置
    CGFloat timeX = screenNameX;
    CGFloat timeY = CGRectGetMaxY(_screenName);
    CGSize timeSize = ;
    _time = (CGRect){{timeX, timeY}, timeSize};
   
    // 4、设置来源尺寸位置
    CGFloat sourceX = CGRectGetMaxX(_time) + kInterval;
    CGFloat sourceY = timeY;
    CGSize sourceSize = ;
    _source = (CGRect){{sourceX, sourceY}, sourceSize};
   
    // 5、设置正文尺寸位置;
    CGFloat textX = profileX;
    CGFloat textY = MAX (CGRectGetMaxY(_profile), CGRectGetMaxY(_time)) + kInterval;
    CGFloat textW = screenSize.width - 2 * kInterval;
    CGSize textSize = ;
    _text = (CGRect){{textX, textY}, textSize};
   
    if (_status.picUrls.count) {                            // 第一种情况:带配图的微博
      
      // 6、设置配图尺寸位置
      CGFloat imageX = profileX;
      CGFloat imageY = CGRectGetMaxY(_text) + kInterval;
      CGSize imageSize = {100, 100};
      _image = (CGRect){{imageX, imageY}, imageSize};
      
      // 有配图无转发体单元格高度
      _cellHeight = CGRectGetMaxY(_image) + kInterval;
      
    } else if (_status.retweetedStatus) {                   // 第二种情况:转发的微博
      
      // 7、设置转发体尺寸位置
      CGFloat retweetX = profileX;
      CGFloat retweetY = CGRectGetMaxY(_text) + kInterval;
      CGFloat retweetW = screenSize.width - 2 * kInterval;
      CGFloat retweetH = kInterval;
      _retweet = CGRectMake(retweetX, retweetY, retweetW, retweetH);
      
      // 8、设置转发体昵称尺寸位置
      CGFloat reScreenNameX = kInterval;
      CGFloat reScreenNameY = kInterval;
      CGSize reScreenNameSize = [ sizeWithFont:kReScreenNameFont];
      _reScreenName = (CGRect){{reScreenNameX, reScreenNameY}, reScreenNameSize};
      
      // 9、设置转发体正文尺寸位置
      CGFloat reTextX = reScreenNameX;
      CGFloat reTextY = CGRectGetMaxY(_reScreenName) + kInterval;
      CGSize reTextSize = ;
      _reText = (CGRect){{reTextX, reTextY}, reTextSize};
      
      // 10、设置转发体配图尺寸位置
      if (_status.retweetedStatus.picUrls) {            // 第二种情况:1、转发的微博带图
            CGFloat reImageX = reScreenNameX;
            CGFloat reImageY = CGRectGetMaxY(_reText) + kInterval;
            CGSize reImageSize = {100, 100};
            _reImage = (CGRect){{reImageX, reImageY}, reImageSize};
            
            // 转发体有配图转发体尺寸
            retweetH = CGRectGetMaxY(_reImage) + kInterval;
            _retweet = CGRectMake(retweetX, retweetY, retweetW, retweetH);
            
      } else {                                          // 第二种情况:2、转发的微博不带图
            
            // 转发体无配图转发体尺寸
            retweetH = CGRectGetMaxY(_reText) + kInterval;
            _retweet = CGRectMake(retweetX, retweetY, retweetW, retweetH);
      }
      
      // 有转发体的单元格高度
      _cellHeight = CGRectGetMaxY(_retweet) + kInterval;
      
    } else {                                                // 第三种情况:不带配图的普通微博
      
      // 11、设置单元格高度尺寸位置
      // 无配图,无转发体单元格高度
      _cellHeight = CGRectGetMaxY(_text) + kInterval;
    }
}

@end

SAStatusTool.m
//
//SAStatusTool.m
//SianWeibo
//
//Created by yusian on 14-4-16.
//Copyright (c) 2014年 小龙虾论坛. All rights reserved.
//

#import "SAStatusTool.h"
#import "SAStatusFrame.h"
#import "SAHttpTool.h"

@implementation SAStatusTool

+ (void)statusToolGetStatusSuccess:(StatusSuccess)success failurs:(StatusFailurs)failure
{
    [ initWithHttpToolStatusSuccess:success failurs:failure];
}

- (void)initWithHttpToolStatusSuccess:(StatusSuccess)success failurs:(StatusFailurs)failure
{
    // 调用SAHttpTool这个工具类,发送相关请求返回数组内容
    [SAHttpTool httpToolPostWithBaseURL:kBaseURL path:@"2/statuses/home_timeline.json" params:
   @{
       @"count" : @"40"
      
       } success:^(id JSON) {
         
         // 如果方法调用没有实现success部分,则方法直接返回
         if (success == nil) return;
         
         // 1、将返回的JSON转换成微博模型并保存到数组
         NSMutableArray *statuses = ;
         for (NSDictionary *dict in JSON[@"statuses"]) {
            
             // 将JSON中解析的数据保存到框架模型中
             SAStatusFrame *statusFrame = [ init];
             statusFrame.status = ;
             ;
         }
         
         // 2、将数组返回给Block形参供方法调用者使用
         success(statuses);
         
   } failure:^(NSError *error) {
         
         if (failure == nil) return;
         
         failure(error);
         
   } method:@"GET"];
   
}
@end

SAStatusCell.h
//
//SAStatusCell.h
//SianWeibo
//
//Created by yusian on 14-4-18.
//Copyright (c) 2014年 小龙虾论坛. All rights reserved.
//

#import <UIKit/UIKit.h>
#import "SAStatusFrame.h"

@interface SAStatusCell : UITableViewCell

@property (nonatomic, strong) SAStatusFrame *statusFrame;

+ (NSString *)ID;

@end

SAStatusCell.m
//
//SAStatusCell.m
//SianWeibo
//
//Created by yusian on 14-4-18.
//Copyright (c) 2014年 小龙虾论坛. All rights reserved.
//

#import "SAStatusCell.h"
#import "UIImageView+WebCache.h"

@interface SAStatusCell ()
{
    UIImageView *_profile;      // 头像
    UILabel   *_screenName;   // 昵称
    UILabel   *_time;         // 时间
    UILabel   *_source;       // 来源
    UILabel   *_text;         // 正文
    UIImageView *_image;      // 配图
    UIImageView *_retweet;      // 转发体视图
    UILabel   *_reScreenName; // 转发体昵称
    UILabel   *_reText;       // 转发体正文
    UIImageView *_reImage;      // 转发体配图
}
@end

@implementation SAStatusCell

#pragma mrak 初始化单元格元素
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = ;
    if (self) {
      
      // 1、头像
      _profile = [ init];
      ;
      
      // 2、昵称
      _screenName = [ init];
      _screenName.font = kScreenNameFount;
      ;
      
      // 3、时间
      _time = [ init];
      _time.font = kTimeFont;
      ;
      
      // 4、来源
      _source = [ init];
      _source.font = kSourceFont;
      ;
      
      // 5、正文
      _text = [ init];
      _text.font = kTextFount;
      _text.numberOfLines = 0;
      ;
      
      // 6、配图
      _image = [ init];
      _image.contentMode = UIViewContentModeScaleAspectFit;
      ;
      
      // 7、转发体视图
      _retweet = [ init];
      _retweet.backgroundColor = ;
      ;
      
      // 8、转发体昵称
      _reScreenName = [ init];
      _reScreenName.font = kReScreenNameFont;
      _reScreenName.backgroundColor = ;
      _reScreenName.textColor = ;
      ;
      
      // 9、转发体正文
      _reText = [ init];
      _reText.numberOfLines = 0;
      _reText.font = kReTextFont;
      _reText.backgroundColor = ;
      ;
      
      // 10、转发体配图
      _reImage = [ init];
      _reImage.contentMode = UIViewContentModeScaleAspectFit;
      ;
      
    }
    return self;
}

#pragma mark - 设置单元格
-(void)setStatusFrame:(SAStatusFrame *)statusFrame
{
    _statusFrame = statusFrame;
   
    ;
   
    ;
}

#pragma mark 设置单元格内容
- (void)statusFrameSettingView
{
    SAStatus *status = self.statusFrame.status;
   
    // 1、设置头像
   
             placeholderImage:
                      options:SDWebImageRetryFailed | SDWebImageLowPriority];
   
    // 2、设置昵称
    _screenName.text = status.user.screenName;
   
    // 3、设置时间
    _time.text = status.createdAt;
   
    // 4、设置来源
    _source.text = status.source;
   
    // 5、设置正文
    _text.text = status.text;
   
    // 6、设置配图
    if (status.picUrls.count) {                     // 第一种情况:带有配图的微博
      
      _image.hidden = NO;
      _retweet.hidden = YES;
      
      [@"thumbnail_pic"]] placeholderImage: options:SDWebImageLowPriority | SDWebImageRetryFailed];
      
    } else if (status.retweetedStatus) {            // 第二种情况:转发的微博
      
      _image.hidden = YES;
      _retweet.hidden = NO;
      
      // 7、设置转发体昵称
      _reScreenName.text = ;
      
      // 8、转发体正文
      _reText.text = status.retweetedStatus.text;
      
      // 9、转发体配图
      if (status.retweetedStatus.picUrls.count) { // 第二种情况:1、转发的微博带配图
            
            // 设置转发体图片内容(暂时取一张为例)
            _reImage.hidden = NO;
            [@"thumbnail_pic"]] placeholderImage: options:SDWebImageLowPriority | SDWebImageRetryFailed];
            
      } else {                                    // 第二种情况:2、转发的微博不带配图
            
            // 无配图则清空属性并隐藏
            _reImage.hidden = YES;
      }
      
    } else {                                        // 第三种情况:不带配图的微博
      
      _image.hidden = YES;
      _retweet.hidden = YES;
    }

}

#pragma mark 单元格元素布局
- (void)statusFrameSettingFrame
{
    // 1、设置头像尺寸位置
    _profile.frame = _statusFrame.profile;
   
    // 2、设置昵称尺寸位置
    _screenName.frame = _statusFrame.screenName;
   
    // 3、设置时间尺寸位置
    _time.frame = _statusFrame.time;
   
    // 4、设置来源尺寸位置
    _source.frame = _statusFrame.source;
   
    // 5、设置正文尺寸位置
    _text.frame = _statusFrame.text;
   
    // 6、设置配图尺寸位置
    _image.frame = _statusFrame.image;
   
    // 7、设置转发体尺寸位置
    _retweet.frame = _statusFrame.retweet;
   
    // 8、设置转发体昵称尺寸位置
    _reScreenName.frame = _statusFrame.reScreenName;
   
    // 9、转发体正文尺寸位置
    _reText.frame = _statusFrame.reText;
   
    // 10、转发体配图尺寸位置
    _reImage.frame = _statusFrame.reImage;

}

#pragma mark 设置单元格标识
+ (NSString *)ID
{
    return @"StatusCell";
}

@end

SAHomeController.m
//
//SAHomeController.m
//SianWeibo
//
//Created by yusian on 14-4-12.
//Copyright (c) 2014年 小龙虾论坛. All rights reserved.
//首页控制器

#import "SAHomeController.h"
#import "NSString+SA.h"
#import "UIBarButtonItem+SA.h"
#import "SAStatusTool.h"
#import "UIImageView+WebCache.h"
#import "SAStatusCell.h"


@interface SAHomeController ()
{
    NSArray         *_statusFrame;// 框架模型数组
}

@end

@implementation SAHomeController

#pragma mark - 初始化方法
- (id)initWithStyle:(UITableViewStyle)style
{
    self = ;
    if (self) {
      // Custom initialization
    }
    return self;
}

#pragma mark - 界面内容展示
- (void)viewDidLoad
{
    ;
   
    // self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
   
    _statusFrame = ;
   
    // 1、设置基本界面
    ;
   
    // 2、加载数据
    ;
   
}

#pragma mark 加载基本界面
- (void)loadBasicUI
{
   
    self.title = @"首页";
   
    // 用自定的分类方法给导航条添加左边按钮
    self.navigationItem.leftBarButtonItem = ;
   
    // 用自定的分类方法给导航条添加右边按钮
    self.navigationItem.rightBarButtonItem = ;
   
}

#pragma mark 加载微博数据
- (void)loadStatusData
{
    // 调用SAStatusTool方法直接加载数据到模型数组
    [SAStatusTool statusToolGetStatusSuccess:^(NSArray *array) {
      
      _statusFrame = ;
      ;
      
    } failurs:^(NSError *error) {
      
      MyLog(@"%@", );
      
    }];
   
}

#pragma mark - 单元格属性
#pragma mark 总单元格行数
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    // 框架模型个数即为单元格数
    return _statusFrame.count;
}

#pragma mark 单元格内容
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    SAStatusCell *cell = ];
   
    if (cell == nil){
      cell = [ initWithStyle:UITableViewCellStyleDefault reuseIdentifier:];
    }
   
    // 单元格内容由框架模型提供
    cell.statusFrame = _statusFrame;
   
    return cell;
}

#pragma mark 单元格高度
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    // 取对应框架模型中的单元格高度属性
    return cellHeight];
}

#pragma mark - 按钮事件处理
#pragma mark 首页导航左按钮事件
- (void)leftButtonClick
{
    MyLog(@"首页左按钮");
}

#pragma mark 首页导航右按钮事件
- (void)rightButtonClick
{
    MyLog(@"首页右按钮");
}

@end

4、源码下载
**** Hidden Message *****
相关主题链接
1、ios实战开发之仿新浪微博(第一讲:新特性展示)
2、ios实战开发之仿新浪微博(第二讲:主框架搭建)
3、ios实战开发之仿新浪微博(第三讲:更多界面搭建)
4、ios实战开发之仿新浪微博(第四讲:OAuth认证)
5、ios实战开发之仿新浪微博(第五讲:微博数据加载)
6、ios实战开发之仿新浪微博(第六讲:微博数据展示一)
7、ios实战开发之仿新浪微博(第七讲:微博数据展示二)
8、ios实战开发之仿新浪微博(第八讲:微博数据展示三)
9、ios实战开发之仿新浪微博(第九讲:微博功能完善一)
10、ios实战开发之仿新浪微博(第十讲:微博功能完善二)
11、ios实战开发之仿新浪微博(第十一讲:微博功能完善三)
12、ios实战开发之仿新浪微博(小龙虾发布版)

Sian 发表于 2014-4-19 10:48:26

本帖最后由 Sian 于 2014-4-19 10:56 编辑

SAStatusFrame数据模型:

齐坦 发表于 2014-6-6 16:01:31

好东西,必须果断收藏啊。

panzilong 发表于 2014-11-4 19:09:46

感谢楼主无私分享!!

yipangzi 发表于 2014-11-21 16:06:20

楼主给力啊、、、、、、、、、、、、、

warmlight 发表于 2014-12-1 10:41:02

学习学习怎么进行cell的设计

1051390159 发表于 2014-12-5 10:37:43

获取指定用户的微博,怎么获取

Sian 发表于 2014-12-6 14:51:58

1051390159 发表于 2014-12-5 10:37
获取指定用户的微博,怎么获取

有相对应的接口,直接调用...

dfgdfsgdfgdfgfd 发表于 2014-12-10 14:45:21

1111111111111111111111

1051390159 发表于 2014-12-17 15:53:39

Sian 发表于 2014-12-6 14:51
有相对应的接口,直接调用...

貌似只有一个高级接口可用,调用指定用户的微博api,现在好像只对微博第三方客户端开放,大神能给点具体的提示吗
页: [1] 2 3 4 5
查看完整版本: ios实战开发之仿新浪微博(第六讲:微博数据展示一)