Commit 38586c15 authored by 曹云霄's avatar 曹云霄

修改项说明:论坛开发

parent 05e058fe
//
// CommentListTableViewCell.h
// Lighting
//
// Created by 曹云霄 on 2016/12/12.
// Copyright © 2016年 上海勾芒科技有限公司. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface CommentListTableViewCell : UITableViewCell
/**
评论人头像
*/
@property (weak, nonatomic) IBOutlet UIImageView *issuerImageView;
/**
评论人姓名
*/
@property (weak, nonatomic) IBOutlet UILabel *issuerNameLabel;
/**
评论时间
*/
@property (weak, nonatomic) IBOutlet UILabel *issuerDateLabel;
/**
评论内容
*/
@property (weak, nonatomic) IBOutlet UILabel *commentContentLabel;
/**
选项按钮
*/
@property (weak, nonatomic) IBOutlet UIButton *optionButton;
@end
//
// CommentListTableViewCell.m
// Lighting
//
// Created by 曹云霄 on 2016/12/12.
// Copyright © 2016年 上海勾芒科技有限公司. All rights reserved.
//
#import "CommentListTableViewCell.h"
@implementation CommentListTableViewCell
- (void)awakeFromNib {
[super awakeFromNib];
// Initialization code
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
@end
//
// CommentListViewController.h
// Lighting
//
// Created by 曹云霄 on 2016/12/12.
// Copyright © 2016年 上海勾芒科技有限公司. All rights reserved.
//
#import "BaseViewController.h"
@interface CommentListViewController : BaseViewController
/**
评论列表
*/
@property (weak, nonatomic) IBOutlet UITableView *commentListTableView;
@end
//
// CommentListViewController.m
// Lighting
//
// Created by 曹云霄 on 2016/12/12.
// Copyright © 2016年 上海勾芒科技有限公司. All rights reserved.
//
#import "CommentListViewController.h"
@interface CommentListViewController ()
@end
@implementation CommentListViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
@end
//
// ContentTableViewCell.h
// Lighting
//
// Created by 曹云霄 on 2016/12/9.
// Copyright © 2016年 上海勾芒科技有限公司. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "KeyBoardAccessoryView.h"
@protocol ExtensionViewTapDelegate <NSObject>
@required
/**
拍照
*/
- (void)showCameraAction;
/**
相册选择
*/
- (void)showPhotoAlbumAction;
/**
刷新高度
*/
- (void)refreshHeight:(CGFloat)height;
@end
/**
扩展项
- Camera: 相机
- PhotoAlbum: 相册
- Emoji: 表情
*/
typedef NS_ENUM(NSInteger,ItemIndex){
Camera = 0,
PhotoAlbum,
Emoji,
};
@interface ContentTableViewCell : UITableViewCell<ExtensionDelegate,UITextViewDelegate>
@property (nonatomic,weak) id<ExtensionViewTapDelegate>delgate;
/**
内容
*/
@property (weak, nonatomic) IBOutlet UITextView *contentTextView;
@end
//
// ContentTableViewCell.m
// Lighting
//
// Created by 曹云霄 on 2016/12/9.
// Copyright © 2016年 上海勾芒科技有限公司. All rights reserved.
//
#import "ContentTableViewCell.h"
#import "STEmojiKeyboard.h"
@implementation ContentTableViewCell
- (void)awakeFromNib {
[super awakeFromNib];
[self setUpToolView];
}
#pragma mark - ToolView
- (void)setUpToolView
{
KeyBoardAccessoryView *toolView = [[KeyBoardAccessoryView alloc] initWithFrame:CGRectMake(0, 0, ScreenWidth, 44)];
toolView.delegate = self;
self.contentTextView.inputAccessoryView = toolView;
}
#pragma mark - Click
- (void)extensionButtonClick:(UIButton *)sender
{
switch (sender.tag) {
case Camera:
{
if ([self.delgate respondsToSelector:@selector(showCameraAction)]) {
[self.delgate showCameraAction];
}
}
break;
case PhotoAlbum:
{
if ([self.delgate respondsToSelector:@selector(showPhotoAlbumAction)]) {
[self.delgate showPhotoAlbumAction];
}
}
break;
case Emoji:
{
sender.selected = !sender.selected;
if (sender.selected) {
[[STEmojiKeyboard keyboard] setTextView:self.contentTextView];
}else {
[self.contentTextView setInputView:nil];
}
[self.contentTextView reloadInputViews];
[self.contentTextView becomeFirstResponder];
}
break;
default:
break;
}
}
#pragma mark - <UITextViewDelegate>
- (void)textViewDidEndEditing:(UITextView *)textView
{
self.contentTextView.height = [self calculateStudyIntroductionHeight:textView.text];
if ([self.delgate respondsToSelector:@selector(refreshHeight:)]) {
[self.delgate refreshHeight:self.contentTextView.height];
}
}
#pragma mark - 计算高度
- (CGFloat)calculateStudyIntroductionHeight:(NSString *)content
{
CGSize s = [content boundingRectWithSize:CGSizeMake(ScreenWidth-40, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:14]} context:nil].size;
return s.height+20;
}
@end
......@@ -10,4 +10,10 @@
@interface CustomImageBackView : UIView
/**
图片
*/
@property (nonatomic,strong) NSArray<TOAttachmentEntity *> *imageArray;
@end
......@@ -18,7 +18,7 @@
CGFloat width = 150;
CGFloat interval = 15;
for (int i=0; i<3; i++) {
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(i*width+i*interval, 0, width, self.height)];
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(i*width+i*interval, 0, width, width)];
imageView.backgroundColor = kMainBlueColor;
[self addSubview:imageView];
if (i == 2) {
......@@ -36,6 +36,29 @@
return self;
}
#pragma mark - 更新View
- (void)setImageArray:(NSArray<TOAttachmentEntity *> *)imageArray
{
_imageArray = imageArray;
for (int i=0;i<self.subviews.count;i++) {
id object = self.subviews[i];
if ([object isKindOfClass:[UIImageView class]]) {
UIImageView *imageView = (UIImageView *)object;
TOAttachmentEntity *entity = _imageArray[i];
[imageView sd_setImageWithURL:[NSURL URLWithString:entity.fileUrl] placeholderImage:ReplaceImage];
}
if ([object isKindOfClass:[UILabel class]]) {
UILabel *label = (UILabel *)object;
label.text = [NSString stringWithFormat:@"共%ld张",_imageArray.count];
}
}
}
@end
//
// CustomTOForumTopicEntity.h
// Lighting
//
// Created by 曹云霄 on 2016/12/12.
// Copyright © 2016年 上海勾芒科技有限公司. All rights reserved.
//
#import "opple_objc_json_client.h"
@interface CustomTOForumTopicEntity : TOForumTopicEntity
/**
内容高度
*/
@property (nonatomic,assign) CGFloat contentHeight;
@end
//
// CustomTOForumTopicEntity.m
// Lighting
//
// Created by 曹云霄 on 2016/12/12.
// Copyright © 2016年 上海勾芒科技有限公司. All rights reserved.
//
#import "CustomTOForumTopicEntity.h"
@implementation CustomTOForumTopicEntity
- (CGFloat)contentHeight
{
if (!_contentHeight) {
_contentHeight = [self calculateStudyIntroductionHeight:self.content];
}
return _contentHeight;
}
#pragma mark - 计算高度
- (CGFloat)calculateStudyIntroductionHeight:(NSString *)content
{
CGSize s = [content boundingRectWithSize:CGSizeMake(ScreenWidth-28*2, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:13]} context:nil].size;
return s.height;
}
@end
//
// ForumItemDetailTableViewCell.h
// Lighting
//
// Created by 曹云霄 on 2016/12/12.
// Copyright © 2016年 上海勾芒科技有限公司. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface ForumItemDetailTableViewCell : UITableViewCell
/**
发贴人头像
*/
@property (weak, nonatomic) IBOutlet UIImageView *issuerImageView;
/**
贴心标题
*/
@property (weak, nonatomic) IBOutlet UILabel *postTitleLabel;
/**
发帖人姓名、时间
*/
@property (weak, nonatomic) IBOutlet UILabel *issuerNameAndDateLabel;
/**
删除帖子
*/
@property (weak, nonatomic) IBOutlet UIButton *delectButton;
/**
帖子内容
*/
@property (weak, nonatomic) IBOutlet UILabel *contentLabel;
@end
//
// ForumItemDetailTableViewCell.m
// Lighting
//
// Created by 曹云霄 on 2016/12/12.
// Copyright © 2016年 上海勾芒科技有限公司. All rights reserved.
//
#import "ForumItemDetailTableViewCell.h"
@implementation ForumItemDetailTableViewCell
- (void)awakeFromNib {
[super awakeFromNib];
// Initialization code
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
@end
//
// ForumItemDetailViewController.h
// Lighting
//
// Created by 曹云霄 on 2016/12/12.
// Copyright © 2016年 上海勾芒科技有限公司. All rights reserved.
//
#import "BaseViewController.h"
@interface ForumItemDetailViewController : BaseViewController
/**
发布评论View
*/
@property (weak, nonatomic) IBOutlet UIView *commentView;
/**
评论输入框
*/
@property (weak, nonatomic) IBOutlet UITextField *commentInputTextFieldView;
/**
已经评论个数
*/
@property (weak, nonatomic) IBOutlet UILabel *commentNumberLabel;
/**
点赞按钮
*/
@property (weak, nonatomic) IBOutlet UIButton *praiseButton;
/**
帖子详情
*/
@property (weak, nonatomic) IBOutlet UITableView *forumDetailTableView;
@end
//
// ForumItemDetailViewController.m
// Lighting
//
// Created by 曹云霄 on 2016/12/12.
// Copyright © 2016年 上海勾芒科技有限公司. All rights reserved.
//
#import "ForumItemDetailViewController.h"
@interface ForumItemDetailViewController ()
@end
@implementation ForumItemDetailViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
@end
......@@ -11,7 +11,29 @@
@interface ForumItemListViewController : BaseViewController
/**
帖子列表
*/
@property (weak, nonatomic) IBOutlet UITableView *classificationListTableView;
@property (weak, nonatomic) IBOutlet UILabel *titleLabel;
/**
分类头像
*/
@property (weak, nonatomic) IBOutlet UIImageView *classifyImageView;
/**
分类标题
*/
@property (weak, nonatomic) IBOutlet UILabel *classifyTitleLabel;
/**
帖子数量
*/
@property (weak, nonatomic) IBOutlet UILabel *classifyListCountLabel;
/**
分类
*/
@property (nonatomic,copy) NSString *category;
@end
......@@ -8,33 +8,149 @@
#import "ForumItemListViewController.h"
#import "ForumItemTableViewCell.h"
#import "ReleasePostViewController.h"
#import "ForumItemDetailViewController.h"
@interface ForumItemListViewController ()<UITableViewDelegate,UITableViewDataSource>
@interface ForumItemListViewController ()<UITableViewDelegate,UITableViewDataSource,DZNEmptyDataSetSource,DZNEmptyDataSetDelegate>
@property (nonatomic,strong) ForumTopicCondition *condition;
@property (nonatomic,strong) NSMutableArray *datasArray;
@end
@implementation ForumItemListViewController
#pragma mark - lazy
- (ForumTopicCondition *)condition
{
if (!_condition) {
_condition = [[ForumTopicCondition alloc] init];
DataPage *page = [[DataPage alloc] init];
page.page = ZERO;
page.rows = KROWS;
_condition.categoryEquals = self.category;
_condition.page = page;
}
return _condition;
}
- (NSMutableArray *)datasArray
{
if (!_datasArray) {
_datasArray = [NSMutableArray array];
}
return _datasArray;
}
- (void)viewDidLoad {
[super viewDidLoad];
[self setUpRefreshAction];
}
#pragma mark - 设置刷新
- (void)setUpRefreshAction
{
WS(weakSelf);
MjRefreshHeaderCustom *headerRefresh = [MjRefreshHeaderCustom headerWithRefreshingBlock:^{
weakSelf.condition.page.page = ONE;
[weakSelf.classificationListTableView.mj_footer resetNoMoreData];
[weakSelf getClassificationList:weakSelf.condition isRemoveArray:YES];
}];
headerRefresh.stateLabel.hidden = YES;
headerRefresh.lastUpdatedTimeLabel.hidden = YES;
self.classificationListTableView.mj_header =headerRefresh;
//进入刷新状态
[self.classificationListTableView.mj_header beginRefreshing];
//上拉加载
self.classificationListTableView.mj_footer = [MJRefreshAutoNormalFooter footerWithRefreshingBlock:^{
if (++ weakSelf.condition.page.page > weakSelf.condition.page.total) {
[weakSelf.classificationListTableView.mj_footer endRefreshingWithNoMoreData];
}else
{
[weakSelf getClassificationList:weakSelf.condition isRemoveArray:NO];
}
}];
self.classificationListTableView.mj_footer.automaticallyHidden = YES;
}
#pragma mark - 获取分类帖子列表
- (void)getClassificationList:(ForumTopicCondition *)condtion isRemoveArray:(BOOL)remove
{
[XBLoadingView showHUDViewWithDefault];
WS(weakSelf);
[[NetworkRequestClassManager Manager] NetworkRequestWithURL:SERVERREQUESTURL(QUERTFORUMLIST) WithRequestType:ZERO WithParameter:condtion WithReturnValueBlock:^(id returnValue) {
[XBLoadingView hideHUDViewWithDefault];
[weakSelf endRefreshingForTableView:weakSelf.classificationListTableView];
weakSelf.classificationListTableView.emptyDataSetSource = weakSelf;
weakSelf.classificationListTableView.emptyDataSetDelegate = weakSelf;
if ([returnValue[@"code"] isEqualToNumber:@0]) {
if (remove) {
[weakSelf.datasArray removeAllObjects];
}
ForumTopicResponse *result = [[ForumTopicResponse alloc] initWithDictionary:returnValue[@"data"] error:nil];
[weakSelf.datasArray addObjectsFromArray:result.forumTopicEntity];
}else {
[XBLoadingView showHUDViewWithText:returnValue[@"message"]];
}
[weakSelf.classificationListTableView reloadData];
} WithFailureBlock:^(NSError *error) {
[XBLoadingView showHUDViewWithText:error.localizedDescription];
}];
}
#pragma mark - 发帖
- (IBAction)releaseButtonClickAction:(UIButton *)sender {
ReleasePostViewController *releaseVc = [[[self class] getLearningCenterStoryboardClass] instantiateViewControllerWithIdentifier:@"ReleasePostViewController"];
releaseVc.category = self.category;
[self.navigationController pushViewController:releaseVc animated:YES];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
ForumItemTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"ForumItemTableViewCell" forIndexPath:indexPath];
cell.topicEntity = self.datasArray[indexPath.row];
return cell;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 5;
return self.datasArray.count;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 250;
CustomTOForumTopicEntity *entity = self.datasArray[indexPath.row];
//20 表示控件间隙、60 表示content Y 150 表示图片背景框高度
CGFloat height = entity.contentHeight + 60 + 20;
if (entity.attachments.count) {
height += 150;
}
return height;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
ForumItemDetailViewController *postDetail = [[[self class] getLearningCenterStoryboardClass] instantiateViewControllerWithIdentifier:@"ForumItemDetailViewController"];
[self.navigationController pushViewController:postDetail animated:YES];
}
#pragma mark -友好界面
- (UIImage *)imageForEmptyDataSet:(UIScrollView *)scrollView
{
return kNoDataImage;
}
- (BOOL)emptyDataSetShouldAllowScroll:(UIScrollView *)scrollView
{
return YES;
}
- (NSAttributedString *)titleForEmptyDataSet:(UIScrollView *)scrollView
{
return [[NSAttributedString alloc]initWithString:@"暂无数据" attributes:nil];
}
@end
......@@ -11,12 +11,44 @@
@interface ForumItemTableViewCell : UITableViewCell
/**
帖子标题
*/
@property (weak, nonatomic) IBOutlet UILabel *titleLabel;
/**
发布人头像
*/
@property (weak, nonatomic) IBOutlet UIImageView *headerImageView;
/**
发布人、时间
*/
@property (weak, nonatomic) IBOutlet UILabel *nameAndDateLabel;
/**
内容
*/
@property (weak, nonatomic) IBOutlet UILabel *contentLabel;
/**
评论数量
*/
@property (weak, nonatomic) IBOutlet UILabel *commentsNumberLabel;
/**
赞数量
*/
@property (weak, nonatomic) IBOutlet UILabel *praiseNumberLabel;
/**
图片背景
*/
@property (weak, nonatomic) IBOutlet CustomImageBackView *imageBackView;
/**
数据源
*/
@property (nonatomic,strong) CustomTOForumTopicEntity *topicEntity;
@end
......@@ -15,10 +15,21 @@
// Initialization code
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
- (void)setTopicEntity:(CustomTOForumTopicEntity *)topicEntity
{
_topicEntity = topicEntity;
if (_titleLabel) {
self.titleLabel.text = _topicEntity.title;
self.contentLabel.text = _topicEntity.content;
self.nameAndDateLabel.text = [NSString stringWithFormat:@"%@: %@ %@",_topicEntity.posterPosition,_topicEntity.posterRealName,_topicEntity.postTime];
self.commentsNumberLabel.text = [NSString stringWithFormat:@"%ld",_topicEntity.replyCount];
self.praiseNumberLabel.text = [NSString stringWithFormat:@"%ld",_topicEntity.likeCount];
self.imageBackView.hidden = _topicEntity.attachments.count?NO:YES;
if (_topicEntity.attachments.count) {
self.imageBackView.imageArray = _topicEntity.attachments;
}
self.contentLabel.height = _topicEntity.contentHeight;
}
}
@end
......@@ -68,6 +68,7 @@
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
ForumItemListViewController *itemListVc = [[[self class] getLearningCenterStoryboardClass] instantiateViewControllerWithIdentifier:@"ForumItemListViewController"];
itemListVc.category = [self.category.categories[indexPath.row] fid];
[self.navigationController pushViewController:itemListVc animated:YES];
}
......
//
// HeadlineTableViewCell.h
// Lighting
//
// Created by 曹云霄 on 2016/12/9.
// Copyright © 2016年 上海勾芒科技有限公司. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface HeadlineTableViewCell : UITableViewCell
/**
标题
*/
@property (weak, nonatomic) IBOutlet UITextField *titleTextField;
@end
//
// HeadlineTableViewCell.m
// Lighting
//
// Created by 曹云霄 on 2016/12/9.
// Copyright © 2016年 上海勾芒科技有限公司. All rights reserved.
//
#import "HeadlineTableViewCell.h"
@implementation HeadlineTableViewCell
- (void)awakeFromNib {
[super awakeFromNib];
}
@end
//
// KeyBoardAccessoryView.h
// Lighting
//
// Created by 曹云霄 on 2016/12/9.
// Copyright © 2016年 上海勾芒科技有限公司. All rights reserved.
//
#import <UIKit/UIKit.h>
/**
扩展工具栏
*/
@protocol ExtensionDelegate <NSObject>
@required
- (void)extensionButtonClick:(UIButton *)sender;
@end
@interface KeyBoardAccessoryView : UIView
@property (nonatomic,weak) id<ExtensionDelegate>delegate;
@end
//
// KeyBoardAccessoryView.m
// Lighting
//
// Created by 曹云霄 on 2016/12/9.
// Copyright © 2016年 上海勾芒科技有限公司. All rights reserved.
//
#import "KeyBoardAccessoryView.h"
@implementation KeyBoardAccessoryView
- (instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame]) {
self.backgroundColor = [UIColor whiteColor];
[self uiConfigAction];
}
return self;
}
#pragma mark - UI
- (void)uiConfigAction
{
NSArray *itemArray = @[@"camera",@"album",@"smilingface"];
CGFloat size = 25;
CGFloat interval = 30;
for (int i=0; i<itemArray.count; i++) {
UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
button.tag = i;
button.tintColor = [UIColor whiteColor];
[button setBackgroundImage:TCImage(itemArray[i]) forState:UIControlStateNormal];
button.frame = CGRectMake(i*size+i*interval+50, (self.height-size)/2, size, size);
[button addTarget:self action:@selector(extensionButtonClick:) forControlEvents:UIControlEventTouchUpInside];
if (i == itemArray.count-1) {
[button setBackgroundImage:TCImage(@"keyboard") forState:UIControlStateSelected];
}
[self addSubview:button];
}
}
#pragma mark - Click
- (void)extensionButtonClick:(UIButton *)sender
{
if ([self.delegate respondsToSelector:@selector(extensionButtonClick:)]) {
[self.delegate extensionButtonClick:sender];
}
}
@end
//
// PhotoManagerCollectionViewCell.h
// Lighting
//
// Created by 曹云霄 on 2016/12/9.
// Copyright © 2016年 上海勾芒科技有限公司. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface PhotoManagerCollectionViewCell : UICollectionViewCell
/**
图片
*/
@property (weak, nonatomic) IBOutlet UIImageView *photoImageView;
@end
//
// PhotoManagerCollectionViewCell.m
// Lighting
//
// Created by 曹云霄 on 2016/12/9.
// Copyright © 2016年 上海勾芒科技有限公司. All rights reserved.
//
#import "PhotoManagerCollectionViewCell.h"
@implementation PhotoManagerCollectionViewCell
@end
//
// PhotoManagerViewController.h
// Lighting
//
// Created by 曹云霄 on 2016/12/9.
// Copyright © 2016年 上海勾芒科技有限公司. All rights reserved.
//
#import "BaseViewController.h"
@interface PhotoManagerViewController : BaseViewController
@property (weak, nonatomic) IBOutlet UICollectionView *photoManagerCollectionView;
@property (weak, nonatomic) IBOutlet UICollectionViewFlowLayout *photoManagerFlowLayout;
/**
图片
*/
@property (nonatomic,strong) NSMutableArray *imageArray;
@end
//
// PhotoManagerViewController.m
// Lighting
//
// Created by 曹云霄 on 2016/12/9.
// Copyright © 2016年 上海勾芒科技有限公司. All rights reserved.
//
#import "PhotoManagerViewController.h"
#import "PhotoManagerCollectionViewCell.h"
#import "MWPhotoBrowser.h"
@interface PhotoManagerViewController ()<UICollectionViewDelegate,UICollectionViewDataSource,MWPhotoBrowserDelegate>
@property (nonatomic,strong) NSMutableArray *browserArray;
@end
@implementation PhotoManagerViewController
#pragma mark - lazy
- (NSMutableArray *)browserArray
{
if (!_browserArray) {
_browserArray = [NSMutableArray array];
}
return _browserArray;
}
- (void)viewDidLoad {
[super viewDidLoad];
[self setUpCollectionView];
}
- (void)setImageArray:(NSArray *)imageArray
{
_imageArray = imageArray;
[self.photoManagerCollectionView reloadData];
}
#pragma mark - UICollectionView
- (void)setUpCollectionView
{
//7表示7个间隔20的距离,40 表示左右边距
self.photoManagerFlowLayout.itemSize = CGSizeMake((ScreenWidth-40-7*20)/8, (ScreenWidth-40-7*20)/8);
self.photoManagerFlowLayout.minimumLineSpacing = 20;
self.photoManagerFlowLayout.minimumInteritemSpacing = 20;
}
#pragma mark - <UICollectionViewDelegate,UICollectionViewDataSource>
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return self.imageArray.count;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
PhotoManagerCollectionViewCell *photoCell = [collectionView dequeueReusableCellWithReuseIdentifier:@"PhotoManagerCollectionViewCell" forIndexPath:indexPath];
photoCell.photoImageView.image = self.imageArray[indexPath.item];
photoCell.photoImageView.tag = indexPath.item;
[photoCell.photoImageView addGestureRecognizer:[[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressClickAction:)]];
return photoCell;
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
[self.browserArray removeAllObjects];
for (UIImage *image in self.imageArray) {
MWPhoto *photo = [MWPhoto photoWithImage:image];
[self.browserArray addObject:photo];
}
MWPhotoBrowser *browser = [[MWPhotoBrowser alloc] initWithDelegate:self];
[browser setCurrentPhotoIndex:indexPath.item];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:browser];
[self.navigationController presentViewController:nav animated:YES completion:nil];
}
#pragma mark - <MWPhotoBrowserDelegate>
- (NSUInteger)numberOfPhotosInPhotoBrowser:(MWPhotoBrowser *)photoBrowser
{
return self.browserArray.count;
}
- (id<MWPhoto>)photoBrowser:(MWPhotoBrowser *)photoBrowser photoAtIndex:(NSUInteger)index
{
if (index < self.browserArray.count) {
return [self.browserArray objectAtIndex:index];
}
return nil;
}
- (NSString *)photoBrowser:(MWPhotoBrowser *)photoBrowser titleForPhotoAtIndex:(NSUInteger)index
{
return [NSString stringWithFormat:@"%ld/%ld", index + 1, self.browserArray.count];
}
#pragma mark -长按删除
- (void)longPressClickAction:(UILongPressGestureRecognizer *)sender
{
WS(weakSelf);
[self promptBoxWithMessage:@"是否删除此项?" cancelBlock:nil sureBlock:^{
NSInteger index = sender.view.tag;
[weakSelf.imageArray removeObjectAtIndex:index];
[weakSelf.photoManagerCollectionView reloadData];
}];
}
@end
//
// ReleasePostViewController.h
// Lighting
//
// Created by 曹云霄 on 2016/12/9.
// Copyright © 2016年 上海勾芒科技有限公司. All rights reserved.
//
#import "BaseViewController.h"
/**
cell类型
- HeadlineCell: 标题
- ContentCell: 文本
*/
typedef NS_ENUM(NSInteger,CellType){
HeadlineCell = 0,
ContentCell
};
@interface ReleasePostViewController : BaseViewController
/**
分类图片
*/
@property (weak, nonatomic) IBOutlet UIImageView *categoryImageView;
/**
分类标题
*/
@property (weak, nonatomic) IBOutlet UILabel *categoryTitleLabel;
/**
发布tableview
*/
@property (weak, nonatomic) IBOutlet UITableView *publishTableView;
/**
所属分类
*/
@property (nonatomic,copy) NSString *category;
@end
This diff is collapsed.
{
"images" : [
{
"idiom" : "universal",
"filename" : "album.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "album@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "album@3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
\ No newline at end of file
{
"images" : [
{
"idiom" : "universal",
"filename" : "keyboard.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "keyboard@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "keyboard@3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
},
"properties" : {
"template-rendering-intent" : "original"
}
}
\ No newline at end of file
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "keyboard_btn_delete@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "keyboard_btn_delete@3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
\ No newline at end of file
{
"images" : [
{
"idiom" : "universal",
"filename" : "smilingface.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "smilingface@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "smilingface@3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
},
"properties" : {
"template-rendering-intent" : "original"
}
}
\ No newline at end of file
{
"images" : [
{
"idiom" : "universal",
"filename" : "success.png",
"scale" : "1x"
},
{
"idiom" : "universal",
"filename" : "success@2x.png",
"scale" : "2x"
},
{
"idiom" : "universal",
"filename" : "success@3x.png",
"scale" : "3x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
\ No newline at end of file
This diff is collapsed.
......@@ -14,7 +14,9 @@ PODS:
- AFNetworking/Serialization (3.1.0)
- AFNetworking/UIKit (3.1.0):
- AFNetworking/NSURLSession
- AliyunOSSiOS (2.5.3)
- Bugly (2.4.2)
- DACircularProgress (2.3.1)
- DZNEmptyDataSet (1.8.1)
- FDFullscreenPopGesture (1.1)
- IQKeyboardManager (4.0.7)
......@@ -34,6 +36,10 @@ PODS:
- MMDrawerController/Core
- MMDrawerController/Subclass (0.6.0):
- MMDrawerController/Core
- MWPhotoBrowser (2.1.2):
- DACircularProgress (~> 2.3)
- MBProgressHUD (~> 0.9)
- SDWebImage (!= 3.7.2, ~> 3.7)
- PNChart (0.8.9):
- UICountingLabel (~> 1.2.0)
- SDWebImage (3.8.2):
......@@ -46,6 +52,7 @@ PODS:
DEPENDENCIES:
- AFNetworking (~> 3.1.0)
- AliyunOSSiOS (~> 2.5.1)
- Bugly
- DZNEmptyDataSet
- FDFullscreenPopGesture
......@@ -55,6 +62,7 @@ DEPENDENCIES:
- MBProgressHUD (~> 0.9.1)
- MJRefresh
- MMDrawerController
- MWPhotoBrowser (~> 2.1.2)
- PNChart (~> 0.8.9)
- SDWebImage
- UMengAnalytics (~> 4.1.2)
......@@ -63,7 +71,9 @@ DEPENDENCIES:
SPEC CHECKSUMS:
AFNetworking: 5e0e199f73d8626b11e79750991f5d173d1f8b67
AliyunOSSiOS: 80e7617a5f4b5af50888a8946f6a744726032972
Bugly: b09cd3c7e54048a0e079be88a7a99610f14eab8f
DACircularProgress: 4dd437c0fc3da5161cb289e07ac449493d41db71
DZNEmptyDataSet: 9525833b9e68ac21c30253e1d3d7076cc828eaa7
FDFullscreenPopGesture: a8a620179e3d9c40e8e00256dcee1c1a27c6d0f0
IQKeyboardManager: 69002bb4fea60596b710e57d426abc00e5063630
......@@ -72,6 +82,7 @@ SPEC CHECKSUMS:
MBProgressHUD: 1569cf7ace17a8bac47aabfbb8580a49690386d1
MJRefresh: b96cdb21c4aa75a7b07654311ab2f315c497e806
MMDrawerController: e3a54a5570388463ad3b36975251575b50c4e1a0
MWPhotoBrowser: 5836d7aa041dc05a13de380c246826578adc5ea5
PNChart: 84774d225c2126ded6c93d4dbe6ae98c3a73c2d2
SDWebImage: 098e97e6176540799c27e804c96653ee0833d13c
UICountingLabel: 1db4e7d023e1762171eb226d6dff47a7a84f27aa
......
//
// OSSClient.h
// oss_ios_sdk
//
// Created by zhouzhuo on 8/16/15.
// Copyright (c) 2015 aliyun.com. All rights reserved.
//
#import <Foundation/Foundation.h>
@class OSSGetServiceRequest;
@class OSSCreateBucketRequest;
@class OSSDeleteBucketRequest;
@class OSSHeadObjectRequest;
@class OSSGetBucketRequest;
@class OSSGetBucketACLRequest;
@class OSSGetObjectRequest;
@class OSSPutObjectRequest;
@class OSSPutObjectACLRequest;
@class OSSDeleteObjectRequest;
@class OSSCopyObjectRequest;
@class OSSInitMultipartUploadRequest;
@class OSSUploadPartRequest;
@class OSSCompleteMultipartUploadRequest;
@class OSSListPartsRequest;
@class OSSAbortMultipartUploadRequest;
@class OSSAppendObjectRequest;
@class OSSResumableUploadRequest;
@class OSSTask;
@class OSSExecutor;
@class OSSNetworking;
@class OSSClientConfiguration;
@protocol OSSCredentialProvider;
/**
OSSClient是OSS服务的iOS客户端,它为调用者提供了一系列的方法,用于和OSS服务进行交互。
一般来说,全局内只需要保持一个OSSClient,用来调用各种操作。
*/
@interface OSSClient : NSObject
/**
OSS访问域名
*/
@property (nonatomic, strong) NSString * endpoint;
/**
用以收发网络请求
*/
@property (nonatomic, strong) OSSNetworking * networking;
/**
提供访问所需凭证
*/
@property (nonatomic, strong) id<OSSCredentialProvider> credentialProvider;
/**
客户端设置
*/
@property (nonatomic, strong) OSSClientConfiguration * clientConfiguration;
/**
任务队列
*/
@property (nonatomic, strong, readonly) OSSExecutor * ossOperationExecutor;
/**
初始化OSSClient,使用默认的本地设置
@endpoint 指明Bucket所在的Region域名
@credentialProvider 需要实现的签名器
*/
- (instancetype)initWithEndpoint:(NSString *)endpoint
credentialProvider:(id<OSSCredentialProvider>) credentialProvider;
/**
初始化OSSClient,使用自定义设置
@endpoint 指明Bucket所在的Region域名
@credentialProvider 需要实现的签名器
@conf 可以设置一些本地参数如重试次数、超时时间等
*/
- (instancetype)initWithEndpoint:(NSString *)endpoint
credentialProvider:(id<OSSCredentialProvider>)credentialProvider
clientConfiguration:(OSSClientConfiguration *)conf;
#pragma mark restful-api
/**
对应RESTFul API:GetService
获取请求者当前拥有的全部Bucket。
注意:
1. 尚不支持STS;
2. 当所有的bucket都返回时,返回的xml中不包含Prefix、Marker、MaxKeys、IsTruncated、NextMarker节点,如果还有部分结果未返回,则增加上述节点,其中NextMarker用于继续查询时给marker赋值。
*/
- (OSSTask *)getService:(OSSGetServiceRequest *)request;
/**
对应RESTFul API:PutBucket
用于创建Bucket(不支持匿名访问)。默认情况下,创建的Bucket位于默认的数据中心:oss-cn-hangzhou。
用户可以显式指定Bucket位于的数据中心,从而最优化延迟,最小化费用或者满足监管要求等。
注意:
1. 尚不支持STS。
*/
- (OSSTask *)createBucket:(OSSCreateBucketRequest *)request;
/**
对应RESTFul API:DeleteBucket
用于删除某个Bucket。
*/
- (OSSTask *)deleteBucket:(OSSDeleteBucketRequest *)request;
/**
对应RESTFul API:GetBucket
用来list Bucket中所有Object的信息,可以通过prefix,marker,delimiter和max-keys对list做限定,返回部分结果。
*/
- (OSSTask *)getBucket:(OSSGetBucketRequest *)request;
/**
对应RESTFul API:GetBucketACL
用来获取某个Bucket的访问权限。
*/
- (OSSTask *)getBucketACL:(OSSGetBucketACLRequest *)request;
/**
对应RESTFul API:HeadObject
只返回某个Object的meta信息,不返回文件内容。
*/
- (OSSTask *)headObject:(OSSHeadObjectRequest *)request;
/**
对应RESTFul API:GetObject
用于获取某个Object,此操作要求用户对该Object有读权限。
*/
- (OSSTask *)getObject:(OSSGetObjectRequest *)request;
/**
对应RESTFul API:PutObject
用于上传文件。
*/
- (OSSTask *)putObject:(OSSPutObjectRequest *)request;
/**
Put Object ACL接口用于修改Object的访问权限。目前Object有三种访问权限:private, public-read, public-read-write。
Put Object ACL操作通过Put请求中的“x-oss-object-acl”头来设置,这个操作只有Bucket Owner有权限执行。如果操作成功,则返回200;否则返回相应的错误码和提示信息。
*/
- (OSSTask *)putObjectACL:(OSSPutObjectACLRequest *)request;
/**
对应RESTFul API:AppendObject
以追加写的方式上传文件。通过Append Object操作创建的Object类型为Appendable Object,而通过Put Object上传的Object是Normal Object。
*/
- (OSSTask *)appendObject:(OSSAppendObjectRequest *)request;
/**
对应RESTFul API:copyObject
拷贝一个在OSS上已经存在的object成另外一个object,可以发送一个PUT请求给OSS,并在PUT请求头中添加元素“x-oss-copy-source”来指定拷贝源。
OSS会自动判断出这是一个Copy操作,并直接在服务器端执行该操作。如果拷贝成功,则返回新的object信息给用户。
该操作适用于拷贝小于1GB的文件。
*/
- (OSSTask *)copyObject:(OSSCopyObjectRequest *)request;
/**
对应RESTFul API:DeleteObject
用于删除某个Object。
*/
- (OSSTask *)deleteObject:(OSSDeleteObjectRequest *)request;
/**
对应RESTFul API:InitiateMultipartUpload
使用Multipart Upload模式传输数据前,必须先调用该接口来通知OSS初始化一个Multipart Upload事件。该接口会返回一个OSS服务器创建的全局唯一的Upload ID,用于标识本次Multipart Upload事件。
用户可以根据这个ID来发起相关的操作,如中止Multipart Upload、查询Multipart Upload等。
*/
- (OSSTask *)multipartUploadInit:(OSSInitMultipartUploadRequest *)request;
/**
对应RESTFul API:UploadPart
初始化一个Multipart Upload之后,可以根据指定的Object名和Upload ID来分块(Part)上传数据。
每一个上传的Part都有一个标识它的号码(part number,范围是1~10,000)。
对于同一个Upload ID,该号码不但唯一标识这一块数据,也标识了这块数据在整个文件内的相对位置。
如果你用同一个part号码,上传了新的数据,那么OSS上已有的这个号码的Part数据将被覆盖。除了最后一块Part以外,其他的part最小为100KB;
最后一块Part没有大小限制。
*/
- (OSSTask *)uploadPart:(OSSUploadPartRequest *)request;
/**
对应RESTFul API:CompleteMultipartUpload
在将所有数据Part都上传完成后,必须调用Complete Multipart Upload API来完成整个文件的Multipart Upload。
在执行该操作时,用户必须提供所有有效的数据Part的列表(包括part号码和ETAG);OSS收到用户提交的Part列表后,会逐一验证每个数据Part的有效性。
当所有的数据Part验证通过后,OSS将把这些数据part组合成一个完整的Object。
*/
- (OSSTask *)completeMultipartUpload:(OSSCompleteMultipartUploadRequest *)request;
/**
对应RESTFul API:ListParts
可以罗列出指定Upload ID所属的所有已经上传成功Part。
*/
- (OSSTask *)listParts:(OSSListPartsRequest *)request;
/**
对应RESTFul API:AbortMultipartUpload
该接口可以根据用户提供的Upload ID中止其对应的Multipart Upload事件。
当一个Multipart Upload事件被中止后,就不能再使用这个Upload ID做任何操作,已经上传的Part数据也会被删除。
*/
- (OSSTask *)abortMultipartUpload:(OSSAbortMultipartUploadRequest *)request;
#pragma mark extention method
/**
对一个Object签名出一个URL,可以把该URL转给第三方实现授权访问。
@bucketName Object所在的Bucket名称
@objectKey Object名称
@interval 签名URL时,可以指定这个URL的有效时长是多久,单位是秒,比如说需要有效时长为1小时的URL,这里传入3600
*/
- (OSSTask *)presignConstrainURLWithBucketName:(NSString *)bucketName
withObjectKey:(NSString *)objectKey
withExpirationInterval:(NSTimeInterval)interval;
/**
如果Object的权限是公共读或者公共读写,调用这个接口对该Object签名出一个URL,可以把该URL转给第三方实现授权访问。
@bucketName Object所在的Bucket名称
@objectKey Object名称
*/
- (OSSTask *)presignPublicURLWithBucketName:(NSString *)bucketName
withObjectKey:(NSString *)objectKey;
/**
断点上传接口
这个接口封装了分块上传的若干接口以实现断点上传,但是需要用户自行保存UploadId。
对一个新文件,用户需要首先调用multipartUploadInit接口获得一个UploadId,然后调用此接口上传这个文件。
如果上传失败,首先需要检查一下失败原因:
如果非不可恢复的失败,那么可以用同一个UploadId和同一文件继续调用这个接口续传
否则,需要重新获取UploadId,重新上传这个文件。
详细参考demo。
*/
- (OSSTask *)resumableUpload:(OSSResumableUploadRequest *)request;
/**
查看某个Object是否存在
@bucketName Object所在的Bucket名称
@objectKey Object名称
return YES Object存在
return NO && *error = nil Object不存在
return NO && *error != nil 发生错误
*/
- (BOOL)doesObjectExistInBucket:(NSString *)bucketName
objectKey:(NSString *)objectKey
error:(const NSError **)error;
@end
This diff is collapsed.
//
// OSSCompat.h
// oss_ios_sdk_new
//
// Created by zhouzhuo on 9/10/15.
// Copyright (c) 2015 aliyun.com. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "OSSService.h"
@class OSSCancellationTokenSource;
typedef OSSCancellationTokenSource OSSTaskHandler;
@interface OSSClient (Compat)
/**
兼容老版本用法的上传数据接口
建议更换使用:putObject
*/
- (OSSTaskHandler *)uploadData:(NSData *)data
withContentType:(NSString *)contentType
withObjectMeta:(NSDictionary *)meta
toBucketName:(NSString *)bucketName
toObjectKey:(NSString *)objectKey
onCompleted:(void(^)(BOOL, NSError *))onCompleted
onProgress:(void(^)(float progress))onProgress;
/**
兼容老版本用法的下载数据接口
建议更换使用:getObject
*/
- (OSSTaskHandler *)downloadToDataFromBucket:(NSString *)bucketName
objectKey:(NSString *)objectKey
onCompleted:(void(^)(NSData *, NSError *))onCompleted
onProgress:(void(^)(float progress))onProgress;
/**
兼容老版本用法的上传文件接口
建议更换使用:putObject
*/
- (OSSTaskHandler *)uploadFile:(NSString *)filePath
withContentType:(NSString *)contentType
withObjectMeta:(NSDictionary *)meta
toBucketName:(NSString *)bucketName
toObjectKey:(NSString *)objectKey
onCompleted:(void(^)(BOOL, NSError *))onCompleted
onProgress:(void(^)(float progress))onProgress;
/**
兼容老版本用法的下载文件接口
建议更换使用:getObject
*/
- (OSSTaskHandler *)downloadToFileFromBucket:(NSString *)bucketName
objectKey:(NSString *)objectKey
toFile:(NSString *)filePath
onCompleted:(void(^)(BOOL, NSError *))onCompleted
onProgress:(void(^)(float progress))onProgress;
/**
兼容老版本用法的断点上传文件接口
建议更换使用:resumableUpload
*/
- (OSSTaskHandler *)resumableUploadFile:(NSString *)filePath
withContentType:(NSString *)contentType
withObjectMeta:(NSDictionary *)meta
toBucketName:(NSString *)bucketName
toObjectKey:(NSString *)objectKey
onCompleted:(void(^)(BOOL, NSError *))onCompleted
onProgress:(void(^)(float progress))onProgress;
/**
兼容老版本用法的删除Object接口
建议更换使用:deleteObject
*/
- (void)deleteObjectInBucket:(NSString *)bucketName
objectKey:(NSString *)objectKey
onCompleted:(void(^)(BOOL, NSError *))onCompleted;
@end
\ No newline at end of file
This diff is collapsed.
//
// OSSDefine.h
// AliyunOSSiOS
//
// Created by zhouzhuo on 5/1/16.
// Copyright © 2016 zhouzhuo. All rights reserved.
//
#import <Foundation/Foundation.h>
#ifndef OSSDefine_h
#define OSSDefine_h
#define OSSUAPrefix @"aliyun-sdk-ios"
#define OSSSDKVersion @"2.5.3"
#define OSSListBucketResultXMLTOKEN @"ListBucketResult"
#define OSSNameXMLTOKEN @"Name"
#define OSSDelimiterXMLTOKEN @"Delimiter"
#define OSSMarkerXMLTOKEN @"Marker"
#define OSSNextMarkerXMLTOKEN @"NextMarker"
#define OSSMaxKeysXMLTOKEN @"MaxKeys"
#define OSSIsTruncatedXMLTOKEN @"IsTruncated"
#define OSSContentsXMLTOKEN @"Contents"
#define OSSKeyXMLTOKEN @"Key"
#define OSSLastModifiedXMLTOKEN @"LastModified"
#define OSSETagXMLTOKEN @"ETag"
#define OSSTypeXMLTOKEN @"Type"
#define OSSSizeXMLTOKEN @"Size"
#define OSSStorageClassXMLTOKEN @"StorageClass"
#define OSSCommonPrefixesXMLTOKEN @"CommonPrefixes"
#define OSSOwnerXMLTOKEN @"Owner"
#define OSSAccessControlListXMLTOKEN @"AccessControlList"
#define OSSGrantXMLTOKEN @"Grant"
#define OSSIDXMLTOKEN @"ID"
#define OSSDisplayNameXMLTOKEN @"DisplayName"
#define OSSBucketsXMLTOKEN @"Buckets"
#define OSSBucketXMLTOKEN @"Bucket"
#define OSSCreationDate @"CreationDate"
#define OSSPrefixXMLTOKEN @"Prefix"
#define OSSUploadIdXMLTOKEN @"UploadId"
#define OSSLocationXMLTOKEN @"Location"
#define OSSNextPartNumberMarkerXMLTOKEN @"NextPartNumberMarker"
#define OSSMaxPartsXMLTOKEN @"MaxParts"
#define OSSPartXMLTOKEN @"Part"
#define OSSPartNumberXMLTOKEN @"PartNumber"
#define OSSClientErrorDomain @"com.aliyun.oss.clientError"
#define OSSServerErrorDomain @"com.aliyun.oss.serverError"
#define OSSErrorMessageTOKEN @"ErrorMessage"
#define OSSHttpHeaderContentDisposition @"Content-Disposition"
#define OSSHttpHeaderXOSSCallback @"x-oss-callback"
#define OSSHttpHeaderXOSSCallbackVar @"x-oss-callback-var"
#define OSSHttpHeaderContentEncoding @"Content-Encoding"
#define OSSHttpHeaderContentType @"Content-Type"
#define OSSHttpHeaderContentMD5 @"Content-MD5"
#define OSSHttpHeaderCacheControl @"Cache-Control"
#define OSSHttpHeaderExpires @"Expires"
#define OSSDefaultRetryCount 3
#define OSSDefaultMaxConcurrentNum 5
#define OSSDefaultTimeoutForRequestInSecond 15
#define OSSDefaultTimeoutForResourceInSecond 7 * 24 * 60 * 60
#endif /* OSSDefine_h */
//
// OSSHttpdns.h
// AliyunOSSiOS
//
// Created by zhouzhuo on 5/1/16.
// Copyright © 2016 zhouzhuo. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface OSSHttpdns : NSObject
+ (instancetype)sharedInstance;
- (NSString *)asynGetIpByHost:(NSString *)host;
@end
//
// OSSHttpdns.m
// AliyunOSSiOS
//
// Created by zhouzhuo on 5/1/16.
// Copyright © 2016 zhouzhuo. All rights reserved.
//
#import "OSSLog.h"
#import "OSSHttpdns.h"
#import "OSSIPv6Adapter.h"
NSString * const HTTPDNS_SERVER_IP = @"203.107.1.1";
NSString * const HTTPDNS_SERVER_PORT = @"80";
NSString * const ACCOUNT_ID = @"181345";
NSTimeInterval const MAX_ENDURABLE_EXPIRED_TIME_IN_SECOND = 60; // 如果离TTL到期已经过去某个秒数,不再使用该解析结果
NSTimeInterval const PRERESOLVE_IN_ADVANCE_IN_SECOND = 10; // 如果发现距离TTL到期小于某个秒数,提前发起更新
@interface IpObject : NSObject
@property (nonatomic, copy) NSString * ip;
@property (nonatomic, assign) NSTimeInterval expiredTime;
@end
@implementation IpObject
@end
@implementation OSSHttpdns {
NSMutableDictionary * gHostIpMap;
NSMutableSet * penddingSet;
}
+ (instancetype)sharedInstance {
static OSSHttpdns * sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [OSSHttpdns new];
});
return sharedInstance;
}
- (instancetype)init {
if (self = [super init]) {
gHostIpMap = [NSMutableDictionary new];
penddingSet = [NSMutableSet new];
}
return self;
}
/**
* OSS SDK专用
*
* @param host 需要严格遵守domain标准格式,如 oss-cn-hangzhou.aliyuncs.com
*
* @return 解析host得到的ip列表中的某个ip
*/
- (NSString *)asynGetIpByHost:(NSString *)host {
IpObject * ipObject = [gHostIpMap objectForKey:host];
if (!ipObject) {
// 如果还没解析过该host,发起解析,返回nil
[self resolveHost:host];
return nil;
} else if ([[NSDate date] timeIntervalSince1970] - ipObject.expiredTime > MAX_ENDURABLE_EXPIRED_TIME_IN_SECOND) {
// 如果该host的解析结果已经过期太久,发起解析,返回nil
[self resolveHost:host];
return nil;
} else if (ipObject.expiredTime -[[NSDate date] timeIntervalSince1970] < PRERESOLVE_IN_ADVANCE_IN_SECOND) {
// 如果该host的解析结果即将过期,或已经过期一段可以接受的时间,发起解析,并返回之前的结果
[self resolveHost:host];
return ipObject.ip;
} else {
// 还未过期,直接返回结果
return ipObject.ip;
}
}
/**
* 发起对一个host的解析,异步执行
* 如果该host已经在解析中,那么后续的请求都会被放弃,直到它解析完成
*
* @param host 需要解析的ip
*/
- (void)resolveHost:(NSString *)host {
@synchronized (self) {
if ([penddingSet containsObject:host]) {
return;
} else {
[penddingSet addObject:host];
}
}
NSURL * url = [NSURL URLWithString:[NSString stringWithFormat:@"http://%@/%@/d?host=%@", [[OSSIPv6Adapter getInstance] handleIpv4Address:HTTPDNS_SERVER_IP], ACCOUNT_ID, host]];
NSURLSession * session = [NSURLSession sharedSession];
NSURLSessionDataTask * dataTask = [session dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
IpObject * ipObject = nil;
NSUInteger statusCode = ((NSHTTPURLResponse *)response).statusCode;
if (statusCode != 200) {
OSSLogError(@"Httpdns resolve host: %@ failed, responseCode: %lu", host, (unsigned long)statusCode);
} else {
NSError *error = nil;
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
NSTimeInterval expiredTime = [[NSDate new] timeIntervalSince1970] + [[json objectForKey:@"ttl"] longLongValue];
NSArray *ips = [json objectForKey:@"ips"];
if (ips == nil || [ips count] == 0) {
OSSLogError(@"Httpdns resolve host: %@ failed, ip list empty.", host);
} else {
NSString * ip = ips[0];
ipObject = [IpObject new];
ipObject.expiredTime = expiredTime;
ipObject.ip = ip;
OSSLogDebug(@"Httpdns resolve host: %@ success, ip: %@, expiredTime: %lf", host, ipObject.ip, ipObject.expiredTime);
}
}
@synchronized (self) {
if (ipObject) {
gHostIpMap[host] = ipObject;
}
[penddingSet removeObject:host];
}
}];
[dataTask resume];
}
@end
/*
* Copyright (c) 2000-2015 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. The rights granted to you under the License
* may not be used to create, or enable the creation or redistribution of,
* unlawful or unlicensed copies of an Apple operating system, or to
* circumvent, violate, or enable the circumvention or violation of, any
* terms of an Apple operating system software license agreement.
*
* Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
/*
* Copyright (c) 1980, 1986, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)route.h 8.3 (Berkeley) 4/19/94
* $FreeBSD: src/sys/net/route.h,v 1.36.2.1 2000/08/16 06:14:23 jayanth Exp $
*/
#ifndef AlicloudIPv6Adapter_h
#define AlicloudIPv6Adapter_h
#import <Foundation/Foundation.h>
@interface OSSIPv6Adapter : NSObject
+ (instancetype)getInstance;
/**
* @brief 判断当前是否为IPv6-Only网络
*
* @return
*/
- (BOOL)isIPv6OnlyNetwork;
/**
* @brief 手动刷新IPv6-Only网络的判定
*
* @return
*/
- (BOOL)reResolveIPv6OnlyStatus;
/**
* @brief 自动完成对IPv4地址的适配
* IPv6-Only网络环境:IPv4 address -> IPv4 Embedded IPv6 address
例:42.156.220.114 -> 64:ff9b::2a9c:dc72
* @param addr
*
* @return
*/
- (NSString *)handleIpv4Address:(NSString *)addr;
/**
* @brief 判断是否为IPv4地址
*
* @return
*/
- (BOOL)isIPv4Address:(NSString *)addr;
/**
* @brief 判断是否为IPv6地址
*
* @return
*/
- (BOOL)isIPv6Address:(NSString *)addr;
@end
#endif /* OSSIPv6Adapter_h */
This diff is collapsed.
//
// OSSIPv6PrefixResolver.h
//
// Created by lingkun on 16/5/16.
// Edit by zhouzhuo on 16/5/22
// Copyright © 2016年 Ali. All rights reserved.
//
#ifndef AlicloudIPv6PrefixResolver_h
#define AlicloudIPv6PrefixResolver_h
#import <Foundation/Foundation.h>
@interface OSSIPv6PrefixResolver : NSObject
+ (instancetype)getInstance;
- (void)updateIPv6Prefix;
- (NSString *)convertIPv4toIPv6:(NSString *)ipv4;
@end
#endif /* OSSIPv6PrefixResolver_h */
This diff is collapsed.
//
// OSSReachabilityManager.h
//
// Created by 亿刀 on 14-1-9.
// Edited by junmo on 15-5-16
// Copyright (c) 2014年 Twitter. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface OSSReachabilityManager : NSObject
+ (OSSReachabilityManager *)shareInstance;
@end
\ No newline at end of file
//
// OSSReachabilityManager.m
//
// Created by 亿刀 on 14-1-9.
// Edited by junmo on 15-5-16
// Edited by zhouzhuo on 2016/5/22
// Copyright (c) 2014年 Twitter. All rights reserved.
//
#import "OSSReachabilityManager.h"
#import "OSSIPv6Adapter.h"
#import "OSSLog.h"
#import <arpa/inet.h>
#import <CommonCrypto/CommonDigest.h>
#import <CoreTelephony/CTCarrier.h>
#import <CoreTelephony/CTTelephonyNetworkInfo.h>
#import <ifaddrs.h>
#import <netdb.h>
#import <netinet/in.h>
#import <netinet6/in6.h>
#import <sys/socket.h>
#import <SystemConfiguration/CaptiveNetwork.h>
#import <SystemConfiguration/SystemConfiguration.h>
#import <UIKit/UIDevice.h>
static char *const OSSReachabilityQueueIdentifier = "com.alibaba.oss.network.ReachabilityQueue";
static dispatch_queue_t reachabilityQueue;
static NSString *const CHECK_HOSTNAME = @"www.taobao.com";
@implementation OSSReachabilityManager {
SCNetworkReachabilityRef _reachabilityRef;
}
+ (OSSReachabilityManager *)shareInstance
{
static OSSReachabilityManager *s_SPDYNetworkStatusManager = nil;
@synchronized([self class])
{
if (!s_SPDYNetworkStatusManager)
{
s_SPDYNetworkStatusManager = [[OSSReachabilityManager alloc] init];
}
}
return s_SPDYNetworkStatusManager;
}
- (id)init
{
self = [super init];
if (self)
{
_reachabilityRef = SCNetworkReachabilityCreateWithName(NULL, [CHECK_HOSTNAME UTF8String]);
//开始监控网络变化
[self _startNotifier];
}
return self;
}
- (BOOL)_startNotifier
{
if (!_reachabilityRef)
{
_reachabilityRef = SCNetworkReachabilityCreateWithName(NULL, [CHECK_HOSTNAME UTF8String]);
}
if (_reachabilityRef)
{
SCNetworkReachabilityContext context = {0, (__bridge void *)(self), NULL, NULL, NULL};
if(SCNetworkReachabilitySetCallback(_reachabilityRef, ReachabilityCallback, &context))
{
reachabilityQueue = dispatch_queue_create(OSSReachabilityQueueIdentifier, DISPATCH_QUEUE_SERIAL);
SCNetworkReachabilitySetDispatchQueue(_reachabilityRef, reachabilityQueue);
return YES;
}
}
return NO;
}
//网络变化回调函数
static void ReachabilityCallback(SCNetworkReachabilityRef target, SCNetworkReachabilityFlags flags, void* info)
{
if ([[OSSIPv6Adapter getInstance] isIPv6OnlyNetwork]) {
OSSLogDebug(@"[AlicloudReachabilityManager]: Network changed, Pre network status is IPv6-Only.");
} else {
OSSLogDebug(@"[AlicloudReachabilityManager]: Network changed, Pre network status is not IPv6-Only.");
}
[[OSSIPv6Adapter getInstance] reResolveIPv6OnlyStatus];
}
@end
\ No newline at end of file
This diff is collapsed.
//
// OSSLog.m
// oss_ios_sdk
//
// Created by zhouzhuo on 8/16/15.
// Copyright (c) 2015 aliyun.com. All rights reserved.
//
#import "OSSLog.h"
@implementation OSSLog
+ (void)enableLog {
isEnable = YES;
}
+ (void)disableLog {
isEnable = NO;
}
+ (BOOL)isLogEnable {
return isEnable;
}
@end
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
../../../AliyunOSSiOS/AliyunOSSiOS/OSSTask/OSSBolts.h
\ No newline at end of file
../../../AliyunOSSiOS/AliyunOSSiOS/OSSTask/OSSCancellationToken.h
\ No newline at end of file
../../../AliyunOSSiOS/AliyunOSSiOS/OSSTask/OSSCancellationTokenRegistration.h
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment