Sian 发表于 2014-4-24 00:31:12

ios实战开发之仿新浪微博(第十讲:微博功能完善二)

1、效果演示

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

2、更新说明

2.1、增加点击微博显示详细信息
2.2、优化微博展示功能
2.3、增加各按钮点击事件(演示事件)

3、设计说明

3.1 点击某条微博,进入该微博的详细信息,通过新窗口展示
3.1.1 该新窗口通过监听微博的点击事件触发,新窗口为导航控制器的子控制器,将首页控制器弹出
3.1.1.1 首页控制器下面有主管理器的Dock栏,而新窗口不需要该导航条,因此在新窗口进入主屏幕时需要完成去掉Dock栏并调节新窗口高度;
3.1.1.2 导航控制器有两个代理方法,分别在新控制器即将进入主屏幕及完全进入主屏幕时调用;
3.1.1.3 实现这两个方法,即将进入主屏幕时将Dock栏从主管理器上撤出,调整Dock的位置并加到Home控制器(导航控制器的根控制器)上,视觉上Dock栏与根控制器一起并推出;
3.1.1.4 在切回根控制器时,实现第二个方法,让根控制器即回到主屏幕时(即完全进入主屏幕)后将Dock归还给主管理器并调整Dock位置,视觉上Dock栏与根控制器一起并退回;

3.2 微博详细信息界面设计
3.2.1 详细页面的内容除了首页展示的微博信息外,附加该微博的转发详细信息与评论详细信息以及点赞数
3.2.2 两者对比图:


3.2.3 由于两者相似性很高,因此抽取出一个用来描述该对象的父类,将其共性在父类中实现,特性各自实现
3.2.4 该对象为微博数据对象,微博对象包括数据模型(M)与展示视图(V),遵循MVC设计模式,逻辑继承图如下所示:


3.2.5 两者的区别在于微博的工具栏,首页微博信息工具栏在微博视图的最下方,并显示为当前微博的转发、评论、点赞信息,详情中微博工具栏显示的是被转发的微博转发、评论、点赞信息,如果该微博没有转发信息则详细信息中无工具栏,区别在于计算微博视图高度,被转发信息视图高度、被转发信息中工具栏数据,这三者都在子类中实现,实现细节代码中有注释说明
3.2.6 两个工具栏又极其类似,因此也抽取共性创建父类,两者通过继承将特性在子类中实现,逻辑图如下:


3.2.7 详细信息展示无疑通过UITableView展示,总体体分为两部分,一部分展示原微博信息,另一部分展示评论、转发、点赞信息,因为Table分组展示,UITableView内部实现原理错综复杂,尤其是各方法调用顺序,实现原理,相信很多码友一直都很困惑,看下图:


3.2.8 以2组表格为例,参照上图说明下表格的绘制过程
1、计算表格组数(得出2组,即第0组与第1组)

2.1、计算第1组 表格高度(倒序额,从后面算起)
2.2、计算第1组 头部高度(可选,如果有的话)
2.3、计算第1组 尾部高度(可选,如果有的话)
2.4、计算第1组 行数
2.5、计算第1组 第0行高度
2.6、计算第1组 第1行高度
2.7、计算第1组 第n行高度

3.1、计算第0组 表格高度
3.2、计算第0组 头部高度(可选,如果有的话)
3.3、计算第0组 尾部高度(可选,如果有的话)
3.4、计算第0组 行数
3.5、计算第0组 第0行高度
3.6、计算第0组 第1行高度
3.7、计算第0组 第n行高度

4.1、计算第0组 第0行内容 (计算内容为正序)
4.2、计算第0组 第1行内容
4.3、计算第0组 第n行内容
4.4、计算第1组 第0行内容
4.5、计算第1组 第1行内容
4.6、计算第1组 第n行内容

5.1、计算头部及尾部内容(这个不重要了,关键在于前面的)

3.2.9 本微博的评论、转发、点赞详细信息后续实现,待续.....

3.3 点击微博内容转到其它视图在主控制器中实现,并且其他控制器都为UITableView类型,其他控制器中点击事件也发生在Table中,因此复制到所有的点击事件(这便是模型的好处MVC设计思想)

4、关键代码
文件目录:
SABaseCell.h
SABaseCell.m
SABaseFrame.h
SABaseFrame.m
SAStatusCell.h
SAStatusFrame.m
SAStatusDetailCell.h
SAStatusDetailCell.m
SAStatusDetailFrame.h
SAStatusDetailFrame.m
SAMainController.h
SAMainController.m
SAStatusDetailController.h
SAStatusDetailController.m
==================================
SABaseCell.h
//
//SABaseCell.h
//SianWeibo
//
//Created by yusian on 14-4-23.
//Copyright (c) 2014年 小龙虾论坛. All rights reserved.
//

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

@interface SABaseCell : UITableViewCell
{
    SABaseFrame   *_cellFrame;    // 数据模型
    UIImageView   *_retweet;      // 转发体视图
}

@property (nonatomic, strong) SABaseFrame *cellFrame;

@end

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

#import "SABaseCell.h"
#import "SAAvata.h"
#import "SAStatus.h"
#import "SAStatusFrame.h"
#import "SAImageListView.h"

@interface SABaseCell ()
{
    SAAvata         *_profile;      // 头像
    UILabel         *_screenName;   // 昵称
    UIImageView   *_mbIcon;       // 会员图标
    UILabel         *_time;         // 时间
    UILabel         *_source;       // 来源
    UILabel         *_text;         // 正文
    SAImageListView *_image;      // 配图
    UILabel         *_reScreenName; // 转发体昵称
    UILabel         *_reText;       // 转发体正文
    SAImageListView *_reImage;      // 转发体配图
}
@end

@implementation SABaseCell

#pragma mark 初始化单元格元素
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = ;
    if (self) {
      
      self.backgroundColor = ;
      self.backgroundView = [ initWithImage:[ stretchableImageWithLeftCapWidth:5 topCapHeight:5]];
      self.selectedBackgroundView = [ initWithImage:[ stretchableImageWithLeftCapWidth:5 topCapHeight:5]];
      
      // 1、头像
      _profile = [ init];
      _profile.backgroundColor = ;
      ;
      
      // 2、昵称
      _screenName = [ init];
      _screenName.backgroundColor = ;
      _screenName.font = kScreenNameFount;
      ;
      
      // 2.1 会员图标
      _mbIcon = [ init];
      _mbIcon.image = ;
      ;
      
      // 3、时间
      _time = [ init];
      _time.backgroundColor = ;
      _time.font = kTimeFont;
      _time.textColor = kTimeColor;
      ;
      
      // 4、来源
      _source = [ init];
      _source.backgroundColor = ;
      _source.font = kSourceFont;
      _source.textColor = ;
      ;
      
      // 5、正文
      _text = [ init];
      _text.backgroundColor = ;
      _text.font = kTextFount;
      _text.numberOfLines = 0;
      ;
      
      // 6、配图
      _image = [ init];
      _image.contentMode = UIViewContentModeScaleAspectFit;
      ;
      
      // 7、转发体视图
      _retweet = [ init];
      _retweet.image = [ stretchableImageWithLeftCapWidth:25 topCapHeight:10];
      ;
      
      // 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)setCellFrame:(SABaseFrame *)cellFrame
{
    _cellFrame = cellFrame;
   
    // 1、设置子控件内容
    ;
   
    // 2、计算子控件Frame
    ;
}

#pragma mark 设置单元格内容
- (void)cellFrameSettingView
{
    SAStatus *status = self.cellFrame.status;
   
    // 1、设置头像
    ;
   
    // 2、设置昵称
    _screenName.text = status.user.screenName;
    if (status.user.mbtype == kMbTypeNone) {
      _screenName.textColor = kScreenNameColor;
    } else {
      _screenName.textColor = kMBScreenNameColor;
    }
   
    // 2.1 设置会员图标
    if (status.user.mbtype == kMbTypeNone) {
      _mbIcon.hidden = YES;
    } else {
      _mbIcon.hidden = NO;
    }
   
    // 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;
      
      _image.imageList = status.picUrls;
      
    } 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;
            _reImage.imageList = status.retweetedStatus.picUrls;
            
      } else {                                    // 第二种情况:2、转发的微博不带配图
            
            // 无配图则清空属性并隐藏
            _reImage.hidden = YES;
      }
      
    } else {                                        // 第三种情况:不带配图的微博
      
      _image.hidden = YES;
      _retweet.hidden = YES;
    }
   
}

#pragma mark 单元格子控件布局
- (void)cellFrameSettingFrame
{
    // 1、设置头像尺寸位置
    _profile.frame = _cellFrame.profile;
   
    // 2、设置昵称尺寸位置
    _screenName.frame = _cellFrame.screenName;
   
    // 2.1 设置会员图标尺寸位置
    _mbIcon.frame = _cellFrame.mbIcon;
   
    // 3、设置时间尺寸位置
    CGRect timeDynamicFrame =_cellFrame.time;
    timeDynamicFrame.size = ; // 时间动态显示,时间尺寸动态计算
    _time.frame = timeDynamicFrame;
   
    // 4、设置来源尺寸位置
    CGRect sourceDynamicFrame = _cellFrame.source;
    sourceDynamicFrame.origin.x = CGRectGetMaxX(timeDynamicFrame) + kInterval;      // 时间尺寸动态计算,来源位置动态计算
    _source.frame = sourceDynamicFrame;
   
    // 5、设置正文尺寸位置
    _text.frame = _cellFrame.text;
   
    // 6、设置配图尺寸位置
    _image.frame = _cellFrame.image;
   
    // 7、设置转发体尺寸位置
    _retweet.frame = _cellFrame.retweet;
   
    // 8、设置转发体昵称尺寸位置
    _reScreenName.frame = _cellFrame.reScreenName;
   
    // 9、转发体正文尺寸位置
    _reText.frame = _cellFrame.reText;
   
    // 10、转发体配图尺寸位置
    _reImage.frame = _cellFrame.reImage;
   
}

#pragma mark 重写frame方法设置Cell宽度
// 该方法会被调用2次
-(void)setFrame:(CGRect)frame
{
    frame.origin.x += kCellMargins;
    frame.size.width -= (2 *kCellMargins);
    frame.origin.y += kCellMargins;
    frame.size.height -= kCellMargins;
   
    ;
}

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

#import <Foundation/Foundation.h>
#import "SAStatus.h"
@interface SABaseFrame : NSObject
{
    // 提供给子类访问的成员变量
    CGFloat   _cellHeight;      // 行高
    CGRect      _retweet;         // 转发体Frame
    SAStatus    *_status;         // 数据模型
}

@property (nonatomic, readonly) CGRect      profile;      // 头像
@property (nonatomic, readonly) CGRect      screenName;   // 昵称
@property (nonatomic, readonly) CGRect      mbIcon;         // 会员图标
@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

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

#import "SABaseFrame.h"
#import "SAAvata.h"
#import "SAStatus.h"
#import "SAImageListView.h"

@implementation SABaseFrame

-(void)setStatus:(SAStatus *)status
{
    _status = status;
   
    CGSize screenSize = .applicationFrame.size;
    CGFloat cellWidth = screenSize.width - 2 * kCellMargins;
   
    // 1、设置头像尺寸位置;
    CGFloat profileX = kInterval;
    CGFloat profileY = kInterval;
    _profile = (CGRect){{kInterval, kInterval}, };
   
    // 2、设置昵称尺寸位置;
    CGFloat screenNameX = CGRectGetMaxX(_profile) + kInterval;
    CGFloat screenNameY = profileY;
    CGSize screenNameSize = ;
    _screenName = (CGRect){{screenNameX, screenNameY}, screenNameSize};
   
    // 2.1 设置会员图标尺寸位置
    CGFloat mbIconX = CGRectGetMaxX(_screenName) + kInterval;
    CGFloat mbIconY = (screenNameSize.height - kMBIconWH) * 0.5 + screenNameY;
    _mbIcon = CGRectMake(mbIconX, mbIconY, kMBIconWH, kMBIconWH);
   
    // 3、设置时间尺寸位置
    CGFloat timeX = screenNameX;
    CGFloat timeY = CGRectGetMaxY(_screenName) + kInterval * 0.5;
    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));
    CGFloat textW = cellWidth - 2 * kInterval;
    CGSize textSize = ;
    _text = (CGRect){{textX, textY}, textSize};
   
    if (_status.picUrls.count) {                            // 第一种情况:带配图的微博
      
      // 6、设置配图尺寸位置
      CGFloat imageX = profileX;
      CGFloat imageY = CGRectGetMaxY(_text) + kInterval;
      CGSize imageSize = ;
      _image = (CGRect){{imageX, imageY}, imageSize};
      
      // 有配图无转发体单元格高度
      _cellHeight = CGRectGetMaxY(_image) + kInterval+ kCellMargins;
      
    } else if (_status.retweetedStatus) {                   // 第二种情况:转发的微博
      
      // 7、设置转发体尺寸位置
      CGFloat retweetX = profileX;
      CGFloat retweetY = CGRectGetMaxY(_text) + kInterval;
      CGFloat retweetW = cellWidth - 2 * kInterval;
      
      // 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.count) {      // 第二种情况:1、转发的微博带图
            CGFloat reImageX = reScreenNameX;
            CGFloat reImageY = CGRectGetMaxY(_reText) + kInterval;
            CGSize reImageSize = ;
            _reImage = (CGRect){{reImageX, reImageY}, reImageSize};
            
            // 转发体有配图转发体尺寸
            CGFloat retweetH = CGRectGetMaxY(_reImage) + kInterval;
            _retweet = CGRectMake(retweetX, retweetY, retweetW, retweetH);
            
      } else {                                          // 第二种情况:2、转发的微博不带图
            
            // 转发体无配图转发体尺寸
            CGFloat retweetH = CGRectGetMaxY(_reText) + kInterval;
            _retweet = CGRectMake(retweetX, retweetY, retweetW, retweetH);
      }
      
      // 有转发体的单元格高度
      _cellHeight = CGRectGetMaxY(_retweet) + kInterval + kCellMargins;
      
    } else {                                                // 第三种情况:不带配图的普通微博
      
      // 11、设置单元格高度尺寸位置
      // 无配图,无转发体单元格高度
      _cellHeight = CGRectGetMaxY(_text) + kInterval + kCellMargins;
    }
   
}
@end

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

#import "SABaseCell.h"
#import "SAStatusFrame.h"

@interface SAStatusCell : SABaseCell

+ (NSString *)ID;

@end

SAStatusFrame.m
//
//SAStatusCell.m
//SianWeibo
//
//Created by yusian on 14-4-18.
//Copyright (c) 2014年 小龙虾论坛. All rights reserved.
//微博单元格类

#import "SAStatusCell.h"
#import "SAStatusDock.h"

@interface SAStatusCell ()
{
    SAStatusDock    *_statusDock;   // 功能菜单
}
@end

@implementation SAStatusCell

#pragma mark 初始化单元格元素
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = ;
    if (self) {
      
      // 1、添加功能菜单
      _statusDock = [ init];
      ;
    }
    return self;
}


#pragma mark - 设置单元格
-(void)setCellFrame:(SAStatusFrame *)cellFrame
{
    ;
   
    // 1、设置功能菜单栏内容
    _statusDock.status = cellFrame.status;
   
}


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

@end

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

#import "SABaseCell.h"

@interface SAStatusDetailCell : SABaseCell

+ (NSString *)ID;

@end

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

#import "SAStatusDetailCell.h"
#import "SADetailRetweetDock.h"
#import "SAStatusDetailFrame.h"

@interface SAStatusDetailCell ()
{
    SADetailRetweetDock *_retweetDock;
}
@end

@implementation SAStatusDetailCell

#pragma mark 调用父类方法初始化
-(id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    if (self = ) {
      
      // 在父类的基础上增加一个转发体Dock工具栏
      _retweetDock = [ init];
      
      ;
    }
    return self;
}

#pragma mark 给转发体赋值
-(void)setCellFrame:(SAStatusDetailFrame *)cellFrame
{
    ;
   
    // 调用父类的方法将共有的控件赋值,再将特有的控件赋值
    _retweetDock.status = cellFrame.status.retweetedStatus;
}

#pragma mark Cell标记写成类方法
+(NSString *)ID
{
    return @"StatusDetailCell";
}
@end

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

#import "SABaseFrame.h"

@interface SAStatusDetailFrame : SABaseFrame

@end

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

#import "SAStatusDetailFrame.h"

@implementation SAStatusDetailFrame

#pragma mark 调整转发体与Cell的高度
-(void)setStatus:(SAStatus *)status
{
    ;
   
    // 在父类视图的基础上,如果有转发,则将转发体高度增加一个Dock高度,并将Cell总高度也增加一个Dock高度
    if (status.retweetedStatus){
      
      _retweet.size.height += kDetailReDockH + kInterval;
      
      _cellHeight += kDetailReDockH + kInterval;
    }
}

@end

SAMainController.h
//
//SAMainController.h
//SianWeibo
//
//Created by yusian on 14-4-11.
//Copyright (c) 2014年 小龙虾论坛. All rights reserved.
//主程序界面

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

@interface SAMainController : SADockController

@end

SAMainController.m
//
//SAMainController.m
//SianWeibo
//
//Created by yusian on 14-4-11.
//Copyright (c) 2014年 小龙虾论坛. All rights reserved.
//主程序界面

#import "SAMainController.h"
#import "SAHomeController.h"
#import "SAMessageController.h"
#import "SAProfileController.h"
#import "SADiscoverController.h"
#import "SAMoreController.h"
#import "SANavigationController.h"
#import "UIBarButtonItem+SA.h"

@interface SAMainController () <SADockDelegate, UINavigationControllerDelegate>

@end

@implementation SAMainController

- (void)viewDidLoad
{
    ;
   
    // 添加其他View
    ;
   
    // 添加Dock控件元素
    ;

}

#pragma mark 添加子控件到首页控制器
- (void)addSubView
{
    // 添加"首页"视图
    SAHomeController *homeControl = [ init];
    SANavigationController *homeNav = [ initWithRootViewController:homeControl];
    homeNav.delegate = self;
    ;
   
    // 添加"消息"视图
    SAMessageController *messageControl = [ initWithStyle:UITableViewStyleGrouped];
    SANavigationController *messageNav = [ initWithRootViewController:messageControl];
    messageNav.delegate = self;
    ;
   
    // 添加"我"视图
    SAProfileController *profileControl = [ init];
    SANavigationController *profileNav = [ initWithRootViewController:profileControl];
    profileNav.delegate = self;
    ;
   
    // 添加"广场"视图
    SADiscoverController *discoverControl = [ init];
    SANavigationController *discoverNav = [ initWithRootViewController:discoverControl];
    discoverNav.delegate = self;
    ;
   
    // 添加"更多"视图
    SAMoreController *moreControl = [ initWithStyle:UITableViewStyleGrouped];
    SANavigationController *moreNav = [ initWithRootViewController:moreControl];
    moreNav.delegate = self;
    ;
}

#pragma mark 添加Dock控件到首页控制器
- (void)addDockItems
{
    ;
    ;
    ;
    ;
    ;
   
}

#pragma mark - 导航控制器代理方法
#pragma mark 即将展示下一控制器时调用
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    // 从首页控制器内部切换需要调整控制器的高度及Dock栏的归属
    UIViewController *rootViewController = ;
   
    // 如果从根控制器切换到其他控制器需要把Dock栏移走,并调整切换后的控制器高度
    if (viewController != rootViewController) {
      
      // 1、调整控制器高度
      CGRect naConViewFrame = navigationController.view.frame;
      CGFloat naConY = navigationController.navigationBar.frame.origin.y;
      CGFloat appHeight = .applicationFrame.size.height;
      naConViewFrame.size.height = appHeight + naConY;
      navigationController.view.frame = naConViewFrame;
      
      // 2、新控制器添加按钮
      viewController.navigationItem.leftBarButtonItem = ;
      
      // 3、计算Dock的y值变化
      CGRect dockFrame = self.dock.frame;
      CGFloat AppHeight = .applicationFrame.size.height;
      CGFloat navBarHeight = navigationController.navigationBar.frame.size.height;
      
      // 3.1 Dock的y值为应用程序的高度(460)-导航条高度-Dock自身的高度,考虑到ios7兼容性问题,这里不利用View自身的高度
      dockFrame.origin.y = AppHeight - navBarHeight - kDockHeight;
      
      // 3.2 TableView滚动后,View的y值发生变量,因此Dock的Y值也需要一起调整
      if (]) {
      
            // 3.2.1 计算滚动的长度,y值自加该长度
            UIScrollView *scrollView = (UIScrollView *)rootViewController.view;
            CGFloat contentY = scrollView.contentOffset.y;
            
            // 3.2.2 ios下透明导航条特性,使得contentOffset自动往下移了64个像素(导航条高度+系统状态栏高度)
            if ([[ systemVersion] floatValue] >= 7.0) contentY +=64;
            dockFrame.origin.y += contentY;
      }
      
      // 4、调整Dock的位置
      ;
      self.dock.frame = dockFrame;
      ;
    }
   
}

#pragma mark 新控制器展示完毕时调用
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
   
    UIViewController *rootViewController = ;
    // 如果切回到根控制器
    if (viewController == rootViewController) {
      
      // 1、把Dock栏返回给主控制器,并调整Dock的位置
      ;
      ;
      CGRect dockFrame = self.dock.frame;
      dockFrame.origin.y = self.view.frame.size.height - kDockHeight;
      self.dock.frame = dockFrame;
      
      // 2、调整控制器View高度
      CGRect naConViewFrame = navigationController.view.frame;
      CGFloat naConY = navigationController.navigationBar.frame.origin.y;
      CGFloat appHeight = .applicationFrame.size.height;
      naConViewFrame.size.height = appHeight + naConY - kDockHeight;
      navigationController.view.frame = naConViewFrame;
      
    }
}

#pragma mark - 按钮事件处理
- (void)back
{
    // 利用Dock传过来的Dock序号(0 - 5),来确定当前需要操作的导航控制器,从而在当前控制器的子控制器数据组找到对应的导航控制器,弹出栈顶控制器
    popToRootViewControllerAnimated:YES];
}

@end

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

#import <UIKit/UIKit.h>
@class SAStatus;

@interface SAStatusDetailController : UITableViewController

@property (nonatomic, strong) SAStatus *status;   // 数据模型,接收传进来的模型数据

@end

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

#import "SAStatusDetailController.h"
#import "SAStatusDetailCell.h"
#import "SAStatusDetailFrame.h"

@interface SAStatusDetailController ()
{
    SAStatusDetailFrame *_detailFrame;
}
@end

@implementation SAStatusDetailController

#pragma mark - Table view default setting
- (id)initWithStyle:(UITableViewStyle)style
{
    self = ;
    if (self) {
      
      self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
      self.view.backgroundColor = kBGColor;
      self.title = @"微博详情";
      
    }
    return self;
}

- (void)viewDidLoad
{
    ;
   
}

#pragma mark 微博内容赋值
-(void)setStatus:(SAStatus *)status
{
    // 通过外界传进来的模型数据,调用自己的框架模型计算出各子视图的数据尺寸位置
    _status = status;
    _detailFrame = [ init];
    _detailFrame.status = status;
}

#pragma mark - Table view data source
#pragma mark 1、返回表格组数
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 2;
}

#pragma mark 2、返回每组头部高度
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
    return 0;
}

#pragma mrak 3、返回每组表格行数
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    if (section == 0) return 1;
    return 2;
}

#pragma mark 4、返回每行高度
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (indexPath.section == 0) return _detailFrame.cellHeight;
    return 40;
}


#pragma mark 5、返回每行内容
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
   
    SAStatusDetailCell *detailCell = ];
    UITableViewCell *cell = [ initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];
   
    if (detailCell == nil) {
      detailCell = [ initWithStyle:UITableViewCellStyleDefault reuseIdentifier:];
    }

    detailCell.cellFrame = _detailFrame;
    cell.textLabel.text = ;
    cell.textLabel.backgroundColor = ;
    cell.backgroundColor = ;
   
    if (indexPath.section == 0) return detailCell;
   
    return cell;
}

#pragma mark 6、返回每组头部视图
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    return nil;
}

#pragma mark 单元格点击事件
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    ;
}

@end

5、源码下载
**** 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实战开发之仿新浪微博(小龙虾发布版)

大象装冰箱O 发表于 2014-10-19 18:10:13

谢谢楼主,加紧学习了

zhwyaoyao 发表于 2014-11-7 10:51:44

学习中,很不错。。。

panzilong 发表于 2014-11-10 20:27:32

很好的学习材料,感谢楼主!

天狼020 发表于 2014-11-10 21:07:57

项目代码 怎么获取啊

规划局规划局 发表于 2014-11-11 12:43:59

期待已久,希望能够学习

yipangzi 发表于 2014-12-9 09:44:12

先码完再说、、、、、、、、、、、、

hnxyzhw 发表于 2014-12-22 10:21:59

一次性下载下来完

basketboy1984 发表于 2014-12-23 18:46:55

牛人的实现

warmlight 发表于 2014-12-29 14:22:40

已经第十课了!!!!!这个项目够我消化好久的说~
页: [1] 2 3 4 5
查看完整版本: ios实战开发之仿新浪微博(第十讲:微博功能完善二)