首页显示微博列表,是微博的核心部分,这一章节,我们主要是显示出微博的列表。

导入第三方类库

pod 'SDWebImage', '~> 3.7.3'
pod 'MJRefresh', '~> 2.4.12'
pod 'MJExtension', '~> 2.5.14'

需求分析

由于Cell的高度是不一样的,因而采用自定义cell的方式来实现。具体实现思路,请参数之前的文章:

iOS UI基础-9.2 UITableView 简单微博列表

代码实现

1、根据新浪微博的API文档,需要定义两个模型(User/Status),由于我们还需要计算控制的位置,另外定义一个StatusFrame模型。

User.h

//
// User.h
// Weibo
//
// Created by jiangys on 15/10/24.
// Copyright © 2015年 Jiangys. All rights reserved.
// #import <Foundation/Foundation.h> typedef enum {
UserVerifiedTypeNone = -, // 没有任何认证
UserVerifiedPersonal = , // 个人认证
UserVerifiedOrgEnterprice = , // 企业官方:CSDN、EOE、搜狐新闻客户端
UserVerifiedOrgMedia = , // 媒体官方:程序员杂志、苹果汇
UserVerifiedOrgWebsite = , // 网站官方:猫扑
UserVerifiedDaren = // 微博达人
} UserVerifiedType; @interface User : NSObject /** string 字符串型的用户UID*/
@property (nonatomic, copy) NSString *idstr; /** string 友好显示名称*/
@property (nonatomic, copy) NSString *name; /** string 用户头像地址,50×50像素*/
@property (nonatomic, copy) NSString *profile_image_url; /** 会员类型 > 2代表是会员 */
@property (nonatomic, assign) int mbtype; /** 会员等级 */
@property (nonatomic, assign) int mbrank; @property (nonatomic, assign, getter = isVip) BOOL vip; /** 认证类型 */
@property (nonatomic, assign) UserVerifiedType verified_type; @end

User.m

//
// User.m
// Weibo
//
// Created by jiangys on 15/10/24.
// Copyright © 2015年 Jiangys. All rights reserved.
// #import "User.h" @implementation User - (void)setMbtype:(int)mbtype
{
_mbtype = mbtype; self.vip = mbtype > ;
} @end

Status.h

//
// Status.h
// Weibo
//
// Created by jiangys on 15/10/24.
// Copyright © 2015年 Jiangys. All rights reserved.
// #import <Foundation/Foundation.h>
@class User; @interface Status : NSObject /** string 字符串型的微博ID*/
@property (nonatomic, copy) NSString *idstr; /** string 微博信息内容*/
@property (nonatomic, copy) NSString *text; /** object 微博作者的用户信息字段 详细*/
@property (nonatomic, strong) User *user; /** string 微博创建时间*/
@property (nonatomic, copy) NSString *created_at; /** string 微博来源*/
@property (nonatomic, copy) NSString *source; /** 微博配图地址。多图时返回多图链接。无配图返回“[]” */
@property (nonatomic, strong) NSArray *pic_urls; @end

Status.m

#import "Status.h"

@implementation Status

// source == <a href="http://app.weibo.com/t/feed/2llosp" rel="nofollow">OPPO_N1mini</a>
- (void)setSource:(NSString *)source
{
if (source.length != ) {
NSRange range;
range.location = [source rangeOfString:@">"].location + ;
range.length = [source rangeOfString:@"</"].location - range.location;
_source = [NSString stringWithFormat:@"来自%@", [source substringWithRange:range]];
} else{
_source = @"来自微博";
}
} @end

StatusFrame.h

//
// StatusFrame.h
// Weibo
//
// Created by jiangys on 15/10/24.
// Copyright © 2015年 Jiangys. All rights reserved.
// #import <Foundation/Foundation.h>
@class Status; // cell的边框宽度
#define StatusCellBorderW 10
// 昵称字体
#define StatusCellNameFont [UIFont systemFontOfSize:15]
// 时间字体
#define StatusCellTimeFont [UIFont systemFontOfSize:12]
// 来源字体
#define StatusCellSourceFont StatusCellTimeFont
// 正文字体
#define StatusCellContentFont [UIFont systemFontOfSize:14] // 被转发微博的正文字体
#define StatusCellRetweetContentFont [UIFont systemFontOfSize:13] // cell之间的间距
#define StatusCellMargin 15 @interface StatusFrame : NSObject /** 存在微博模型 */
@property (nonatomic, strong) Status *status; /** 原创微博整体 */
@property (nonatomic, assign, readonly) CGRect originalViewF;
/** 头像 */
@property (nonatomic, assign, readonly) CGRect iconViewF;
/** 会员图标 */
@property (nonatomic, assign, readonly) CGRect vipViewF;
/** 配图 */
@property (nonatomic, assign, readonly) CGRect photosViewF;
/** 昵称 */
@property (nonatomic, assign, readonly) CGRect nameLabelF;
/** 时间 */
@property (nonatomic, assign, readonly) CGRect timeLabelF;
/** 来源 */
@property (nonatomic, assign, readonly) CGRect sourceLabelF;
/** 正文 */
@property (nonatomic, assign, readonly) CGRect contentLabelF; /** cell的高度 */
@property (nonatomic, assign, readonly) CGFloat cellHeight; @end

StatusFrame.m

//
// StatusFrame.m
// Weibo
//
// Created by jiangys on 15/10/24.
// Copyright © 2015年 Jiangys. All rights reserved.
// #import "StatusFrame.h"
#import "Status.h"
#import "User.h"
#import "NSString+Size.h" @implementation StatusFrame /**
* 设置每一条微博的Frame 及cell的高度
*
* @param status 微博模型
*/
-(void)setStatus:(Status *)status
{
_status = status; User *user=status.user; // cell的宽度
CGFloat cellW = [UIScreen mainScreen].bounds.size.width; /* 原创微博 */ /** 头像 */
CGFloat iconWH = ;
CGFloat iconX = StatusCellBorderW;
CGFloat iconY = StatusCellBorderW;
_iconViewF = CGRectMake(iconX, iconY, iconWH, iconWH); /** 昵称 */
CGFloat nameX = CGRectGetMaxX(self.iconViewF) + StatusCellBorderW;
CGFloat nameY = iconY;
CGSize nameSize = [user.name sizeWithFont:StatusCellNameFont];
_nameLabelF = (CGRect){{nameX, nameY}, nameSize}; /** 会员图标 */
if (user.isVip) {
CGFloat vipX = CGRectGetMaxX(self.nameLabelF) + StatusCellBorderW;
CGFloat vipY = nameY;
CGFloat vipH = nameSize.height;
CGFloat vipW = ;
_vipViewF = CGRectMake(vipX, vipY, vipW, vipH);
} /** 时间 */
CGFloat timeX = nameX;
CGFloat timeY = CGRectGetMaxY(self.nameLabelF) + StatusCellBorderW;
CGSize timeSize = [status.created_at sizeWithFont:StatusCellTimeFont];
_timeLabelF = (CGRect){{timeX, timeY}, timeSize}; /** 来源 */
CGFloat sourceX = CGRectGetMaxX(self.timeLabelF) + StatusCellBorderW;
CGFloat sourceY = timeY;
CGSize sourceSize = [status.source sizeWithFont:StatusCellSourceFont];
_sourceLabelF = (CGRect){{sourceX, sourceY}, sourceSize}; /** 正文 */
CGFloat contentX = iconX;
CGFloat contentY = MAX(CGRectGetMaxY(self.iconViewF), CGRectGetMaxY(self.timeLabelF)) + StatusCellBorderW;
CGFloat maxW = cellW - * contentX;
CGSize contentSize = [status.text sizeWithFont:StatusCellContentFont maxW:maxW];
_contentLabelF = (CGRect){{contentX, contentY}, contentSize}; /* cell的高度 */
_cellHeight = CGRectGetMaxY(self.contentLabelF)+StatusCellBorderW;
} @end

2、接下来,我们需要自定义cell,在cell里添加所有的控件及设置控件的尺寸。

StatusCell.h

//
// StatusCell.h
// Weibo
//
// Created by jiangys on 15/10/24.
// Copyright © 2015年 Jiangys. All rights reserved.
// #import <UIKit/UIKit.h>
@class StatusFrame; @interface StatusCell : UITableViewCell
@property (nonatomic, strong) StatusFrame *statusFrame; + (instancetype)cellWithTableView:(UITableView *)tableView;
@end

StatusCell.m

//
// StatusCell.m
// Weibo
//
// Created by jiangys on 15/10/24.
// Copyright © 2015年 Jiangys. All rights reserved.
// #import "StatusCell.h"
#import "Status.h"
#import "StatusFrame.h"
#import "User.h"
#import "UIImageView+WebCache.h" @interface StatusCell() /* 原创微博 */
/** 原创微博整体 */
@property (nonatomic, weak) UIView *originalView;
/** 头像 */
@property (nonatomic, weak) UIImageView *iconView;
/** 会员图标 */
@property (nonatomic, weak) UIImageView *vipView;
/** 配图 */
@property (nonatomic, weak) UIImageView *photosView;
/** 昵称 */
@property (nonatomic, weak) UILabel *nameLabel;
/** 时间 */
@property (nonatomic, weak) UILabel *timeLabel;
/** 来源 */
@property (nonatomic, weak) UILabel *sourceLabel;
/** 正文 */
@property (nonatomic, weak) UILabel *contentLabel; @end @implementation StatusCell /**
* 重写initWithStyle:reuseIdentifier:方法
* 添加所有需要显示的子控件(不需要设置子控件的数据和frame,子控件要添加到contentView中)
* 进行子控件一次性的属性设置(有些属性只需要设置一次, 比如字体\固定的图片)
*/
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
if (self==[super initWithStyle:style reuseIdentifier:reuseIdentifier]) { /** 原创微博整体 */
UIView *originalView = [[UIView alloc] init];
originalView.backgroundColor = [UIColor whiteColor];
[self.contentView addSubview:originalView];
self.originalView = originalView; /** 头像 */
UIImageView *iconView = [[UIImageView alloc] init];
[originalView addSubview:iconView];
self.iconView = iconView; /** 会员图标 */
UIImageView *vipView = [[UIImageView alloc] init];
vipView.contentMode = UIViewContentModeCenter;
[originalView addSubview:vipView];
self.vipView = vipView; /** 配图 */
UIImageView *photosView = [[UIImageView alloc] init];
[originalView addSubview:photosView];
self.photosView = photosView; /** 昵称 */
UILabel *nameLabel = [[UILabel alloc] init];
nameLabel.font = StatusCellNameFont;
[originalView addSubview:nameLabel];
self.nameLabel = nameLabel; /** 时间 */
UILabel *timeLabel = [[UILabel alloc] init];
timeLabel.font = StatusCellTimeFont;
timeLabel.textColor = [UIColor orangeColor];
[originalView addSubview:timeLabel];
self.timeLabel = timeLabel; /** 来源 */
UILabel *sourceLabel = [[UILabel alloc] init];
sourceLabel.font = StatusCellSourceFont;
[originalView addSubview:sourceLabel];
self.sourceLabel = sourceLabel; /** 正文 */
UILabel *contentLabel = [[UILabel alloc] init];
contentLabel.font = StatusCellContentFont;
contentLabel.numberOfLines = ;
[originalView addSubview:contentLabel];
self.contentLabel = contentLabel;
}
return self;
} - (void)setStatusFrame:(StatusFrame *)statusFrame
{
_statusFrame = statusFrame;
Status *status = self.statusFrame.status;
User *user = status.user; /** 原创微博整体 */
self.originalView.frame = statusFrame.originalViewF; /** 头像 */
self.iconView.frame = statusFrame.iconViewF;
[self.iconView sd_setImageWithURL:[NSURL URLWithString:user.profile_image_url] placeholderImage:[UIImage imageNamed:@"avatar_default_small"]]; /** 会员图标 */
if (user.isVip) {
self.vipView.hidden = NO; self.vipView.frame = statusFrame.vipViewF;
NSString *vipName = [NSString stringWithFormat:@"common_icon_membership_level%d", user.mbrank];
self.vipView.image = [UIImage imageNamed:vipName]; self.nameLabel.textColor = [UIColor orangeColor];
} else {
self.nameLabel.textColor = [UIColor blackColor];
self.vipView.hidden = YES;
} /** 配图 */
self.photosView.frame = statusFrame.photosViewF;
self.photosView.backgroundColor = [UIColor redColor]; /** 昵称 */
self.nameLabel.text = user.name;
self.nameLabel.frame = statusFrame.nameLabelF; /** 时间 */
self.timeLabel.text = status.created_at;
self.timeLabel.frame = statusFrame.timeLabelF; /** 来源 */
self.sourceLabel.text = status.source;
self.sourceLabel.frame = statusFrame.sourceLabelF; /** 正文 */
self.contentLabel.text = status.text;
self.contentLabel.frame = statusFrame.contentLabelF; } + (instancetype)cellWithTableView:(UITableView *)tableView
{
static NSString *ID = @"status";
StatusCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
if (cell == nil) {
cell = [[StatusCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
}
return cell;
} @end

3、最后,就是有首页里显示出cell。首页里,显示用到的MJRefresh刷新控件

//
// HomeViewController.m
// Weibo
//
// Created by jiangys on 15/10/5.
// Copyright (c) 2015年 Jiangys. All rights reserved.
// #import "HomeViewController.h"
#import "Test1ViewController.h"
#import "DropdownMenu.h"
#import "TitleMenuViewController.h"
#import "TitleButton.h"
#import "Status.h"
#import "StatusFrame.h"
#import "MJRefresh.h"
#import "MJExtension.h"
#import "AccountTool.h"
#import "Account.h"
#import "HttpTool.h"
#import "StatusCell.h"
#import "User.h" @interface HomeViewController ()<DropdownMenuDelegate> /** 微博列表 (里面放的都是HWStatusFrame模型,一个StatusFrame对象就代表一条微博)*/
@property (nonatomic, strong) NSMutableArray *statusFrames; @end @implementation HomeViewController - (NSMutableArray *)statusFrames
{
if (!_statusFrames) {
self.statusFrames = [NSMutableArray array];
}
return _statusFrames;
} - (void)viewDidLoad {
[super viewDidLoad]; // 设置导航栏内容
[self setupNav]; // 获得用户信息(昵称)
[self setupUserInfo]; // 集成下拉刷新控件
[self setupDownRefresh]; // 集成上拉刷新控制
[self setupUpRefresh];
} /**
* 集成下拉刷新控件
*/
- (void)setupDownRefresh
{
// 设置回调(一旦进入刷新状态,就调用target的action,也就是调用self的loadNewData方法)
self.tableView.header = [MJRefreshNormalHeader headerWithRefreshingTarget:self refreshingAction:@selector(loadNewStatus)]; // 马上进入刷新状态
[self.tableView.header beginRefreshing];
} - (void)setupUpRefresh
{
// 设置回调(一旦进入刷新状态,就调用target的action,也就是调用self的loadNewData方法)
self.tableView.footer = [MJRefreshAutoNormalFooter footerWithRefreshingTarget:self refreshingAction:@selector(loadMoreStatus)];
} - (void)loadNewStatus
{
// 1.拼接请求参数
Account *account = [AccountTool getAccount];
NSMutableDictionary *params = [NSMutableDictionary dictionary];
params[@"access_token"] = account.access_token; // 取出最前面的微博(最新的微博,ID最大的微博)
StatusFrame *firstStatusF = [self.statusFrames firstObject];
if (firstStatusF) {
// 若指定此参数,则返回ID比since_id大的微博(即比since_id时间晚的微博),默认为0
params[@"since_id"] = firstStatusF.status.idstr;
} // 2.发送请求
[HttpTool get:@"https://api.weibo.com/2/statuses/friends_timeline.json" params:params success:^(id json) {
// YSLog(@"--json--%@",json); // 将 "微博字典"数组 转为 "微博模型"数组
NSArray *newStatuses = [Status objectArrayWithKeyValuesArray:json[@"statuses"]]; // 将 HWStatus数组 转为 HWStatusFrame数组
NSArray *newFrames = [self stausFramesWithStatuses:newStatuses]; // 将最新的微博数据,添加到总数组的最前面
NSRange range = NSMakeRange(, newFrames.count);
NSIndexSet *set = [NSIndexSet indexSetWithIndexesInRange:range];
[self.statusFrames insertObjects:newFrames atIndexes:set]; // 刷新表格
[self.tableView reloadData]; // 结束刷新
[self.tableView.header endRefreshing]; // 显示最新微博的数量
[self showNewStatusCount:newStatuses.count]; } failure:^(NSError *error) {
YSLog(@"请求失败-%@", error); // 结束刷新刷新
[self.tableView.header endRefreshing];
}];
} /**
* 加载更多微博数据
*/
- (void)loadMoreStatus
{
// 1.拼接请求参数
Account *account = [AccountTool getAccount];
NSMutableDictionary *params = [NSMutableDictionary dictionary];
params[@"access_token"] = account.access_token; // 取出最后面的微博(最新的微博,ID最大的微博)
StatusFrame *lastStatusF = [self.statusFrames lastObject];
if (lastStatusF) {
// 若指定此参数,则返回ID小于或等于max_id的微博,默认为0。
// id这种数据一般都是比较大的,一般转成整数的话,最好是long long类型
long long maxId = lastStatusF.status.idstr.longLongValue - ;
params[@"max_id"] = @(maxId);
} // 2.发送请求
[HttpTool get:@"https://api.weibo.com/2/statuses/friends_timeline.json" params:params success:^(id json) {
// 将 "微博字典"数组 转为 "微博模型"数组
NSArray *newStatuses = [Status objectArrayWithKeyValuesArray:json[@"statuses"]]; // 如果没有更多数据,隐藏
if (newStatuses.count==) {
self.tableView.footer.hidden = YES;
} // 将 Status数组 转为 StatusFrame数组
NSArray *newFrames = [self stausFramesWithStatuses:newStatuses]; // 将更多的微博数据,添加到总数组的最后面
[self.statusFrames addObjectsFromArray:newFrames]; // 刷新表格
[self.tableView reloadData]; // 结束footer刷新
[self.tableView.footer endRefreshing]; } failure:^(NSError *error) {
YSLog(@"请求失败-%@", error); // 结束刷新
[self.tableView.footer endRefreshing];
}];
} /**
* 显示最新微博的数量
*
* @param count 最新微博的数量
*/
- (void)showNewStatusCount:(NSUInteger)count
{
// 1.创建label
UILabel *label = [[UILabel alloc] init];
label.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"timeline_new_status_background"]];
label.width = [UIScreen mainScreen].bounds.size.width;
label.height = ; // 2.设置其他属性
if (count == ) {
label.text = @"没有新的微博数据,稍后再试";
} else {
label.text = [NSString stringWithFormat:@"共有%zd条新的微博数据", count];
}
label.textColor = [UIColor whiteColor];
label.textAlignment = NSTextAlignmentCenter;
label.font = [UIFont systemFontOfSize:]; // 3.添加
label.y = - label.height;
// 将label添加到导航控制器的view中,并且是盖在导航栏下边
[self.navigationController.view insertSubview:label belowSubview:self.navigationController.navigationBar]; // 4.动画
// 先利用1s的时间,让label往下移动一段距离
CGFloat duration = 1.0; // 动画的时间
[UIView animateWithDuration:duration animations:^{
label.transform = CGAffineTransformMakeTranslation(, label.height);
} completion:^(BOOL finished) {
// 延迟1s后,再利用1s的时间,让label往上移动一段距离(回到一开始的状态)
CGFloat delay = 1.0; // 延迟1s
// UIViewAnimationOptionCurveLinear:匀速
[UIView animateWithDuration:duration delay:delay options:UIViewAnimationOptionCurveLinear animations:^{
label.transform = CGAffineTransformIdentity;
} completion:^(BOOL finished) {
[label removeFromSuperview];
}];
}]; // 如果某个动画执行完毕后,又要回到动画执行前的状态,建议使用transform来做动画
} /**
* 将Status模型转为StatusFrame模型
*/
- (NSArray *)stausFramesWithStatuses:(NSArray *)statuses
{
NSMutableArray *frames = [NSMutableArray array];
for (Status *status in statuses) {
StatusFrame *f = [[StatusFrame alloc] init];
f.status = status;
[frames addObject:f];
}
return frames;
} /**
* 设置导航栏内容
*/
- (void)setupNav
{
self.navigationItem.leftBarButtonItem=[UIBarButtonItem itemWithImage:@"navigationbar_friendsearch" highImage:@"navigationbar_friendsearch_highlighted" target:self action:@selector(friendSearch)]; self.navigationItem.rightBarButtonItem=[UIBarButtonItem itemWithImage:@"navigationbar_pop" highImage:@"navigationbar_pop_highlighted" target:self action:@selector(pop)]; /* 中间的标题按钮 */
TitleButton *titleButton = [[TitleButton alloc] init]; NSString *name = [AccountTool getAccount].name;
[titleButton setTitle:name?name:@"首页" forState:UIControlStateNormal]; // 监听标题点击
[titleButton addTarget:self action:@selector(titleClick:) forControlEvents:UIControlEventTouchUpInside]; self.navigationItem.titleView = titleButton;
} /**
* 标题点击
*/
- (void)titleClick:(UIButton *)titleButton
{
// 1.创建下拉菜单
DropdownMenu *menu = [DropdownMenu menu];
menu.delegate = self; // 2.设置内容
TitleMenuViewController *vc = [[TitleMenuViewController alloc] init];
vc.view.height = ;
vc.view.width = ; menu.contentController = vc; // 3.显示
[menu showFrom:titleButton];
} /**
* 获得用户信息(昵称)
*/
- (void)setupUserInfo
{
// 1.拼接请求参数
Account *account = [AccountTool getAccount];
NSMutableDictionary *params = [NSMutableDictionary dictionary];
params[@"access_token"] = account.access_token;
params[@"uid"] = account.uid; // 2.发送请求
[HttpTool get:@"https://api.weibo.com/2/users/show.json" params:params success:^(id json) {
// 标题按钮
UIButton *titleButton = (UIButton *)self.navigationItem.titleView;
// 设置名字
User *user = [User objectWithKeyValues:json];
[titleButton setTitle:user.name forState:UIControlStateNormal]; // 存储昵称到沙盒中
account.name = user.name;
[AccountTool saveAccount:account];
} failure:^(NSError *error) {
YSLog(@"请求失败-%@", error);
}];
} -(void)friendSearch
{ } -(void)pop
{
Test1ViewController *test1=[[Test1ViewController alloc]init];
test1.title = @"测试2控制器";
[self.navigationController pushViewController:test1 animated:YES];
} #pragma mark - HWDropdownMenuDelegate
/**
* 下拉菜单被销毁了
*/
- (void)dropdownMenuDidDismiss:(DropdownMenu *)menu
{
UIButton *titleButton = (UIButton *)self.navigationItem.titleView;
titleButton.selected = NO;// 让箭头向下
} /**
* 下拉菜单显示了
*/
- (void)dropdownMenuDidShow:(DropdownMenu *)menu
{
UIButton *titleButton = (UIButton *)self.navigationItem.titleView;
titleButton.selected = YES;// 让箭头向上
} #pragma mark - Table view data source
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.statusFrames.count;
} -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// 获得cell
StatusCell *cell = [StatusCell cellWithTableView:tableView]; // 给cell传递模型数据
cell.statusFrame = self.statusFrames[indexPath.row]; return cell;
} -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
StatusFrame *statusFrame=self.statusFrames[indexPath.row];
return statusFrame.cellHeight;
} @end

最终效果如下:

章节源代码下载:http://pan.baidu.com/s/1c00SK1q

新浪微博Github:https://github.com/jiangys/Weibo

iOS 新浪微博-5.0 首页微博列表的更多相关文章

  1. iOS 新浪微博-5.1 首页微博列表_时间/配图

    在上一篇中,我们已经把首页微博显示出来了,但还有很多细节,需要我们去调整的.这一章中,我们将处理好时间,配图,工具框及转发微博等小细节的功能. 时间处理 第一步:定义一个时间的类别,用于判断是昨天.今 ...

  2. iOS 新浪微博-5.2 首页微博列表_转发微博/工具栏

    继续于上一篇,还是做首页的功能,这一篇把剩下的首页继续完善. 看看上面的图片,分析: 1.转发微博里面的内容,和原创微博是一样的,由文字+配图组成.这应该放在一个UIView里处理. 2.工具栏也当成 ...

  3. iOS 新浪微博-5.3 首页微博列表_集成图片浏览器

    实际上,我们可以使用李明杰在教程里集成的MJPhotoBrowser,地址: http://code4app.com/ios/快速集成图片浏览器/525e06116803fa7b0a000001 使用 ...

  4. IOS SWIFT UITableView 实现简单微博列表

    // // Weibo.swift // UITableViewCellExample // // Created by XUYAN on 15/8/15. // Copyright (c) 2015 ...

  5. iOS 新浪微博-4.0 OAuth授权

    申请开发者 想要拉到到新浪微博的数据,首先让自己成为开发者.申请成为开发者账号很简单,只要有新浪微博的账号即可. 申请地址:http://open.weibo.com/ 在开发的过程中,我们需要拿到几 ...

  6. iOS 新浪微博-3.0 新特性

    每个程序在第一次启动的时候,都会显示新特性.效果如下: 思路: 添加一个ViewController,里面放两个View,一个是UISrollView,另一个pageControl 往UISrollV ...

  7. iOS 新浪微博-2.0 搜索框/标题带箭头/下拉菜单

    不管是搜索框还是下拉菜单,我们都需要对背景的图片进行拉伸.定义一个Category分类对图片进行操作. UIImage+Effect.h #import <UIKit/UIKit.h> @ ...

  8. iOS新浪微博OAuth2.0认证代码

    #import "ViewController.h" #import "AFNetworking.h" @interface ViewController () ...

  9. 【Android 我的博客APP】1.抓取博客首页文章列表内容——网页数据抓取

    打算做个自己在博客园的博客APP,首先要能访问首页获取数据获取首页的文章列表,第一步抓取博客首页文章列表内容的功能已实现,在小米2S上的效果图如下: 思路是:通过编写的工具类访问网页,获取页面源代码, ...

随机推荐

  1. BZOJ 1002 - 轮状病毒 - [基尔霍夫矩阵(待补)+高精度]

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1002 Description 轮状病毒有很多变种,所有轮状病毒的变种都是从一个轮状基产生 ...

  2. CH 1401 - 兔子与兔子 - [字符串hash]

    题目链接:传送门 描述 很久很久以前,森林里住着一群兔子.有一天,兔子们想要研究自己的 DNA 序列.我们首先选取一个好长好长的 DNA 序列(小兔子是外星生物,DNA 序列可能包含 26 个小写英文 ...

  3. LCA&最小生成树

    LCA 经常被用来使用.比如询问树两点之间的距离. 比如树上差分 都是经常被使用的类型.有的时候倍增求LCA的同时还可以优化算法. 这道题呢 求一个严格的最小生成树,当然如果不严格的话如果有重边那么就 ...

  4. LeetCode 953 Verifying an Alien Dictionary 解题报告

    题目要求 In an alien language, surprisingly they also use english lowercase letters, but possibly in a d ...

  5. 新建虚拟机_WIN8 64位系统_启动报错Directory "EZBOOT" not found

    准备工作:下载win8 64 镜像文件 1.虚拟机安装win8 64位操作系统,新建虚拟机步骤同XP系统 2.BIOS设置CD/ROM启动,但启动报错,如下,由于镜像文件超过4G,无法从虚拟机安装,需 ...

  6. springmvc shiro整合cas单点登入

    shiro cas分为登入跟登出 maven依赖: <dependency> <groupId>org.apache.shiro</groupId> <art ...

  7. 【PyQt5-Qt Designer】QComboBox-下拉列表框

    知识点: 1.QComboBox下拉列表框的一些常用方法 2.下拉列表框常用信号使用方法 案例:选中下拉框选项时触发信号 #[str] 表示comboBox中的选择框内容如A B C D 等 self ...

  8. Vue通过build打包后 打开index.html页面是空白的

    最近在build打包vue项目遇到了几个问题,如下: 1.npm run build打包项目之后,我们通常是把dist文件里面被压缩后的static文件跟index.html提交到服务器,但最近发现直 ...

  9. Sql批量修改帝国cms文章发布时间(需unix时间,否则会变为1970-01-01)

    在迁移网站时,有时我们需要将帝国cms文章发表时间批量修改为当前时间,在帝国cms后台→系统设置→备份与恢复数据→执行sql语句: update phome_ecms_news set newstim ...

  10. OC动画CABasicAnimation

    //1.创建动画 CABasicAnimation *anima=[CABasicAnimation animationWithKeyPath:@"bounds"]; //1.1设 ...