添加PCH文件Starry.pch
在程序Build Settings 的Prefix Header 写上$(SRCROOT)/工程名称/Starry.pch
Starry.pch
#ifndef Starry_pch
#define Starry_pch
/*
常用头文件的导入
*/
#import "BaseViewController.h"
#import "AppDelegate.h"
#import "MBProgressHUD.h"
#import "UIView+NewMethods.h"
#import "NSString+NewMethods.h"
#import "UserDataBase.h"
#import "NewsDataBase.h"
#import "UIImage+Tailor.h"
#import "QRCodeGenerator.h"
#import "URLService.h"
#define App_Delegate (AppDelegate *)[UIApplication sharedApplication].delegate
/*
系统版本号
*/
#define VERSION_10_0 [UIDevice currentDevice].systemVersion.doubleValue >= 10.0
#define VERSION_9_0 [UIDevice currentDevice].systemVersion.doubleValue >= 9.0
/*
用于适配的宏
*/
#define SCR_W [UIScreen mainScreen].bounds.size.width
#define SCR_H [UIScreen mainScreen].bounds.size.height
//适配x轴的宏
#define FIT_X(w) (SCR_W / 375. *(w))
//适配Y轴的宏
#define FIT_Y(h) (SCR_H / 667. *(h))
/*
当前app版本号的宏
*/
#define VERSION_CURRENT [[NSBundle mainBundle].infoDictionary objectForKey:@"CFBundleShortVersionString"]
//持久化当前版本号的key的宏
#define NOT_FIRST_LANUCH @"NotFirstLanuch"
/*
Doucuments目录的宏
*/
#define DOCUMENT_PATH [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject]
/*
注册通知
*/
//退出登录
#define LOGOUT_NOTIFICATION_NAME @"logoutNotification"
#endif /* Starry_pch */
BaseViewController.h
#import
typedef enum{
BaseViewControllerTag_Main = 444,//头条,天气,直播
BaseViewControllerTag_Left//个人信息,我的收藏,关于我们
} BaseViewControllerTag;
@interface BaseViewController : UIViewController
//实例化对象并设置是那种类型(分为主模块和侧滑模块)
-(instancetype)initWithTag:(BaseViewControllerTag)tag;
#pragma mark -子类调用方法
//在导航条右侧添加一个分享按钮
- (void)addShareButtonToNavigationRightBarItem;
//隐藏弹出的分享视图
- (void)hidePopView;
//收藏按钮
@property (nonatomic,strong)UIButton *saveBtn;
//分享按钮保存数组
@property (nonatomic,strong)NSMutableArray *shareBtnArr;
@end
BaseViewController.m
#import "BaseViewController.h"
#import "UserDataBase.h"
@interface BaseViewController ()
{
UIButton *headImgBtn;
BaseViewControllerTag _ctlTag;//用于区分控制器的标签
UIView *backView;//弹出分享窗口的背景图
}
@property (nonatomic,strong)UIWindow *shareView;
@end
@implementation BaseViewController
-(instancetype)initWithTag:(BaseViewControllerTag)tag
{
self = [super init];
if (self) {
_ctlTag = tag;
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.view.backgroundColor = [UIColor grayColor];
/*
导航条设置
*/
//背景图
[self.navigationController.navigationBar setBackgroundImage:[UIImage imageNamed:@"navigationItem_background"] forBarMetrics:UIBarMetricsDefault];
//设置导航条文字颜色和字体大小
[self.navigationController.navigationBar setTitleTextAttributes:@{NSForegroundColorAttributeName:[UIColor whiteColor],NSFontAttributeName:[UIFont systemFontOfSize:18.0]}];
/*
返回按钮设置
*/
if (self.navigationController.viewControllers.count == 1) {
if (_ctlTag == BaseViewControllerTag_Main) {
headImgBtn = [UIButton buttonWithType:UIButtonTypeCustom];
headImgBtn.frame = CGRectMake(0, 0, 44, 44);
headImgBtn.clipsToBounds = YES;
headImgBtn.layer.cornerRadius = 44/2;
headImgBtn.imageView.contentMode = UIViewContentModeScaleAspectFill;
[headImgBtn addTarget:self action:@selector(headBtnHandle:) forControlEvents:UIControlEventTouchUpInside];
UIView *view = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 44, 44)];
[view addSubview:headImgBtn];
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc]initWithCustomView:view];
}else{//还是导航的根(个人信息,我的收藏,关于我们)
UIButton *backBtn = [UIButton buttonWithType:UIButtonTypeCustom];
backBtn.frame = CGRectMake(0, 0, 20, 30);
[backBtn setImage:[UIImage imageNamed:@"navigationItem_back"] forState:UIControlStateNormal];
[backBtn addTarget:self action:@selector(backBtnHandle:) forControlEvents:UIControlEventTouchUpInside];
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc]initWithCustomView:backBtn];
}
}
//导航次级控制器
else{
self.navigationItem.hidesBackButton = YES;
UIButton *backBtn = [UIButton buttonWithType:UIButtonTypeCustom];
backBtn.frame = CGRectMake(0, 0, 20, 30);
[backBtn setImage:[UIImage imageNamed:@"navigationItem_back"] forState:UIControlStateNormal];
[backBtn addTarget:self action:@selector(backBtnHandle:) forControlEvents:UIControlEventTouchUpInside];
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc]initWithCustomView:backBtn];
}
//注册一个监听,监听退出登录
[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(updateAllViewContents) name:LOGOUT_NOTIFICATION_NAME object:nil];
}
//头像按钮触发事件
- (void)headBtnHandle:(id)sender{
AppDelegate *app = App_Delegate;
[app.sideMenu presentLeftMenuViewController];
}
//返回方法
- (void)backBtnHandle:(id)sender{
//点击了导航根视图控制器上的导航左侧按钮
if (self.navigationController.viewControllers.count == 1) {
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
}
//点击了导航控制器中的次级视图控制器上的左侧按钮
else{
[self.navigationController popViewControllerAnimated:YES];
}
}
#pragma mark -私有方法
//更新UI
-(void)updateAllViewContents{
//判断导航栈中有几个控制器
if (self.navigationController.viewControllers.count == 1) {
//表示该视图是导航的根视图控制器
self.tabBarController.tabBar.hidden = NO;
//判断有无用户登录.来设置头像按钮的图片
if(![[UserDataBase sharedDataBase]userHadLogin]){
//如果没有登录用户,显示默认头像图片
[headImgBtn setImage:[UIImage imageNamed:@"40"] forState:UIControlStateNormal];
}else{
//有持久化的登录人数据
User *u= [[UserDataBase sharedDataBase]getCurrentLoginUser];
//用户没有设置头像
if(u.headImg == nil){
//没有设置头像,显示默认图片头像
[headImgBtn setImage:[UIImage imageNamed:@"40"] forState:UIControlStateNormal];
}else{
//设置头像,显示头像
UIImage *img = [[UIImage alloc]initWithContentsOfFile:[DOCUMENT_PATH stringByAppendingPathComponent:u.headImg]];
[headImgBtn setImage:img forState:UIControlStateNormal];
}
}
}
else{
//表示该视图是导航的2级或3级视图控制器
self.tabBarController.tabBar.hidden = YES;
}
}
//在导航条右侧添加一个分享按钮
- (void)addShareButtonToNavigationRightBarItem{
UIBarButtonItem *shareItem = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(popShareView)];
self.navigationItem.rightBarButtonItem = shareItem;
}
//按钮触发弹出一个分享视图
- (void)popShareView{
//如果view在屏幕的下面,就让他弹出
if (self.shareView.frame.origin.y == SCR_H) {
[UIView animateWithDuration:0.15 animations:^{
self.shareView.frame = CGRectMake(0, SCR_H*3/5, SCR_W, SCR_H*2/5);
}];
backView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, SCR_W, SCR_H)];
backView.backgroundColor = [UIColor lightGrayColor];
backView.alpha = 0.2;
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(hidePopView)];
[backView addGestureRecognizer:tap];
[self.view addSubview:backView];
[self.shareView makeKeyAndVisible];
}else{//如果view在屏幕上显示,就让他消失
[self hidePopView];
}
}
//隐藏视图
- (void)hidePopView{
[backView removeFromSuperview];
backView = nil;
[UIView animateWithDuration:0.15 animations:^{
self.shareView.frame = CGRectMake(0, SCR_H, SCR_W, SCR_H*2/5);
}];
[self.shareView resignKeyWindow];
}
#pragma Mark- 导航右侧按钮
- (UIButton *)saveBtn{
if (!_saveBtn) {
self.saveBtn = [UIButton buttonWithType:UIButtonTypeCustom];
self.saveBtn.frame = CGRectMake(0, 0, FIT_X(60), FIT_Y(60));
self.saveBtn.center = CGPointMake(SCR_W/2,FIT_X(30+40));
[self.saveBtn setImage:[UIImage imageNamed:@"left_myorder"] forState:UIControlStateNormal];
}
return _saveBtn;
}
//分享视图
- (UIView *)shareView{
if (!_shareView) {
_shareView = [[UIWindow alloc]initWithFrame:CGRectMake(0, SCR_H, SCR_W, SCR_H*2/5)];
_shareView.backgroundColor = [UIColor whiteColor];
_shareView.windowLevel = UIWindowLevelAlert;
//添加一个收藏按钮
[_shareView addSubview:self.saveBtn];
//添加分享按钮
NSArray *shareImgNames = @[@"sns_icon_1",@"sns_icon_22",@"sns_icon_23",@"sns_icon_24"];
CGFloat btnWidth = FIT_X(60);
CGFloat btnDis = FIT_X(20);
CGFloat startX = (SCR_W - shareImgNames.count*btnWidth - (shareImgNames.count - 1)*btnDis)/2;
CGFloat btnY = self.saveBtn.frame.origin.y + self.saveBtn.frame.size.height + FIT_X(40);
self.shareBtnArr = [[NSMutableArray alloc]init];
for (int i = 0; i < shareImgNames.count; i++) {
UIButton *shareBtn = [UIButton buttonWithType:UIButtonTypeCustom];
shareBtn.frame = CGRectMake(startX + i * (btnDis + btnWidth), btnY, btnWidth, btnWidth);
[shareBtn setImage:[UIImage imageNamed:shareImgNames[i]] forState:UIControlStateNormal];
[_shareView addSubview:shareBtn];
[self.shareBtnArr addObject:shareBtn];
}
}
return _shareView;
}
#pragma mark - viewWillAppear
- (void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
[self updateAllViewContents];
}
- (void)viewWillDisappear:(BOOL)animated{
[super viewWillDisappear:animated];
[self hidePopView];
}
- (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
HttpRequest.h //封装网络请求
#import
typedef void (^PassType)(id ,BOOL);
@interface HttpRequest : NSObject
///实例化对象,同时设置回传的代码块
- (instancetype)initWithRequestCompletion:(PassType)pass;
///NSURLSession的GET方式请求网络数据
- (void)requestBySessionGETWithURL:(NSString *)urlStr parames:(NSDictionary *)paramaDic;
///NSURLSession的POST方式请求网络数据
- (void)requestBySessionPOSTWithURL:(NSString *)urlStr parames:(NSDictionary *)paramaDic;
@end
HttpRequest.m
#import "HttpRequest.h"
@interface HttpRequest ()
@property (nonatomic,strong)PassType pass;
@end
@implementation HttpRequest
#pragma mark - 实例化对象,同时设置回传的代码块
- (instancetype)initWithRequestCompletion:(PassType)pass{
self = [super init];
if (self) {
self.pass = pass;
}
return self;
}
#pragma mark - NSURLSession请求数据
///NSURLSession的GET方式请求网络数据
/*
1)urlStr - 服务器的主地址
http://api.jisuapi.com/news/get
2)paramaDic - 参数字典 比如:
@{@"channel":@"头条",@"start":@"0"}
3)如果执行get请求,需要得到如下格式的网址字符串
http://api.jisuapi.com/news/get?channel = 头条&start=0
*/
- (void)requestBySessionGETWithURL:(NSString *)urlStr parames:(NSDictionary *)paramaDic{
//1)将网址字符串拼接好
NSMutableString *urlString = [urlStr mutableCopy];
if (paramaDic != nil && paramaDic.count != 0) {
[urlString appendString:@"?"];
for (NSString *key in paramaDic) {
/*假设第一次执行时键值对为chanel和头条.得到以下字符串:
http://api.jisuapi.com/news/get?channel=头条&
假设第二次执行时键值对为start和0.得到以下字符串:
http://api.jisuapi.com/news/get?channel=头条&start=0&
*/
NSString *temp = [NSString stringWithFormat:@"%@=%@&",key,paramaDic[key]];
[urlString appendString:temp];
}
//去除最后一个&字符
[urlString deleteCharactersInRange:NSMakeRange(urlString.length-1, 1)];
//2)如果带汉字,对汉字编码处理
urlString = [[urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]mutableCopy];
//3)封装网址对象
NSURL *url = [[NSURL URLWithString:urlString]copy];
//4)实例化请求对象
NSURLRequest *req = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:6.0];
//5)做一个NSURLSession,请求网络数据
NSURLSession *session = [NSURLSession sharedSession];
//6)执行获取网络数据任务
NSURLSessionDataTask *task = [session dataTaskWithRequest:req completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
NSLog(@"---------- 易晓腾,请求数据 ----------");
//如果请求失败
if (error) {
self.pass(error, NO);
}
//请求成功
else{
if (data == nil) {
self.pass(nil, NO);
}
else{
NSError *myError;
//JSON解析
id object = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&myError];
//解析失败
if (myError) {
self.pass(myError, NO);
}
else{
self.pass(object, YES);
}
}
}
}];
//7)任务开始执行
[task resume];
}
}
///NSURLSession的POST方式请求网络数据
- (void)requestBySessionPOSTWithURL:(NSString *)urlStr parames:(NSDictionary *)paramaDic{
//1)将网址字符串封装为地址对象
NSURL *url = [NSURL URLWithString:urlStr];
//2)定义一个请求对象
NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:6.0];
//设置请求方式为POST
[req setHTTPMethod:@"POST"];
//将请求的参数做成一个NSData数据
NSMutableString *contentStr = [[NSMutableString alloc]init];
for (NSString *key in paramaDic) {
NSString *temp = [NSString stringWithFormat:@"%@=%@",key,paramaDic[key]];
[contentStr appendString:temp];
}
[contentStr deleteCharactersInRange:NSMakeRange(contentStr.length-1, 1)];
NSData *contentData = [contentStr dataUsingEncoding:NSUTF8StringEncoding];
//设置请求的内容
[req setHTTPBody:contentData];
//3)使用NSURLSession执行任务
[[[NSURLSession sharedSession]dataTaskWithRequest:req completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (error) {
self.pass(error, NO);
}
else{
NSError *myError;
id object = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&myError];
if (myError) {
self.pass(myError, NO);
}
else{
self.pass(object, YES);
}
}
}]resume];
}
@end
URLService.h
#import
#import "News.h"
#import "Weather.h"
#import "BookIN.h"
#import "BookShow.h"
typedef void(^PassDataBlock)(id,BOOL);
@interface URLService : NSObject
//用于回传数据的方法
- (instancetype)initWithCompletion:(PassDataBlock)pass;
///"新闻头条" - 获取新闻数据
- (void)getNewsByChannel:(NSString *)channel start:(int)start;
///"新闻头条" - 获取频道数据
- (void)getAllChannels;
///"新闻头条" - 搜索新闻
- (void)searchNewsBySerachContent:(NSString *)searchTxt;
@end
URLService.m
#import "URLService.h"
#import "HttpRequest.h"
#import "LiveShow.h"
//--"AppKey"
#define APP_KEY @"dbe4d556aed8a277"
//--"新闻模块"网址
//获取新闻数据
#define NEWS_URL @"http://api.jisuapi.com/news/get"
//获取频道数据
#define CHANNELS_URL @"http://api.jisuapi.com/news/channel"
//搜索新闻
#define NEWS_SEARCH_URL @"http://api.jisuapi.com/news/search"
@interface URLService()
@property (nonatomic,strong)PassDataBlock pass;
@end
@implementation URLService
//用于回传数据的方法
- (instancetype)initWithCompletion:(PassDataBlock)pass{
self = [super init];
if (self) {
self.pass = pass;
}
return self;
}
#pragma mark - "新闻模块"接口
///"新闻头条" - 获取新闻数据
- (void)getNewsByChannel:(NSString *)channel start:(int)start{
NSNumber *startNum = [NSNumber numberWithInt:start];
//定义参数字典
NSDictionary *paramDic = @{
@"appkey":APP_KEY,
@"channel":channel,
@"num":@15,
@"start":startNum
};
//实例化自定义的request对象,并设置回调的代码块
HttpRequest *req = [[HttpRequest alloc]initWithRequestCompletion:^(id passData, BOOL success) {
NSLog(@"新闻数据:%@",passData);
if (!success) {
self.pass(passData, NO);
}
else{
NSDictionary *dic = (NSDictionary *)passData;
if (![dic[@"status"] isEqualToString:@"0"]) {
self.pass(dic[@"msg"], NO);
}
else{
NSArray *newsArr = [NewsCreat createNewsArrayWithDictionary:dic];
self.pass(newsArr, YES);
}
}
}];
//使用GET方式请求数据
[req requestBySessionGETWithURL:NEWS_URL parames:paramDic];
}
///"新闻头条" - 获取频道数据
- (void)getAllChannels{
}
///"新闻头条" - 搜索新闻
- (void)searchNewsBySerachContent:(NSString *)searchTxt{
}
@end
News.h
#import
@interface News : NSObject
@property (nonatomic,assign)int ID;//此ID用于收藏,表示收藏新闻的ID;如果从网络请求数据解析时,是没有此ID值得
@property (nonatomic,strong)NSString *title;//标题
@property (nonatomic,strong)NSString *time;//时间
@property (nonatomic,strong)NSString *src;//来源
@property (nonatomic,strong)NSString *category;//分类
@property (nonatomic,strong)NSString *pic;//图片
@property (nonatomic,strong)NSString *content;//内容
@property (nonatomic,strong)NSString *url;//原文手机网址
@property (nonatomic,strong)NSString *weburl;//原文pc网址
@end
@interface NewsCreat:NSObject
///解析返回的json数据,将其变为一个封装了多个News对象的数组
+ (NSArray *)createNewsArrayWithDictionary:(NSDictionary *)dict;
@end
News.m
#import "News.h"
@implementation News
@end
@implementation NewsCreat
+(NSArray *)createNewsArrayWithDictionary:(NSDictionary *)dict{
NSDictionary *resaultDic = dict[@"result"];
NSArray *listArr = resaultDic[@"list"];
NSMutableArray *newsArr = [[NSMutableArray alloc]init];
for (NSDictionary *newsDic in listArr) {
News *oneNew = [[News alloc]init];
[oneNew setValuesForKeysWithDictionary:newsDic];
[newsArr addObject:oneNew];
}
//将数组返回
return newsArr;
}
@end
NewsDataBase.h
#import
#import "News.h"
@interface NewsDataBase : NSObject
//类方法,用于外部类获取该单例类对象
+(instancetype)sharedDataBase;
-(BOOL)addNews:(News *)oneNew;
- (NSMutableArray *)getUserSvedNews;
- (BOOL)deleteOneNewsByID:(int)delID;
@end
NewsDataBase.m
#import "NewsDataBase.h"
#import "FMDB.h"
//-------SQL语句
#define SQL_INIT_TABLE @"CREATE TABLE news (id INTEGER PRIMARY KEY AUTOINCREMENT,userid INTEGER,title TEXT,time TEXT,pic TEXT,content TEXT,url TEXT,weburl TEXT)"
#define SQL_INSERT @"INSERT INTO news VALUES (NULL,%d,%@,%@,%@,%@,%@,%@)"
#define SQL_SELECT @"SELECT *FROM news WHERE userid = %d"
#define SQL_DELETE @"DELETE FROM news WHERE id = %d"
@interface NewsDataBase()
@property (nonatomic,strong)FMDatabase *fmDB;
@end
static NewsDataBase *_defaultNewsDB = nil;
@implementation NewsDataBase
#pragma mark -单例实现方法
//实例对外的类方法
+(instancetype)sharedDataBase{
if (_defaultNewsDB == nil) {
_defaultNewsDB = [[NewsDataBase alloc]init];
}
return _defaultNewsDB;
}
//重写allocWithZone方法.防止使用alloc生成新对象
+(instancetype)allocWithZone:(struct _NSZone *)zone{
if (_defaultNewsDB == nil) {
_defaultNewsDB = [super allocWithZone:zone];
}
return _defaultNewsDB;
}
- (id)copy{
return self;
}
- (id)mutableCopy{
return self;
}
#pragma mark - 数据库,初始化表
- (FMDatabase *)fmDB{
if (!_fmDB) {
//文件路径
NSString *filePath = [DOCUMENT_PATH stringByAppendingPathComponent:@"starrysky.db"];
NSLog(@"数据库路径%@",filePath);
_fmDB = [FMDatabase databaseWithPath:filePath];
}
return _fmDB;
}
- (instancetype)init{
self = [super init];
if (self) {
[self.fmDB open];
[self.fmDB executeUpdate:SQL_INIT_TABLE];
[self.fmDB close];
}
return self;
}
#pragma Mark- 增,删,查方法
-(BOOL)addNews:(News *)oneNew{
//如果打开数据库失败,直接返回NO,表示添加失败
if (![self.fmDB open]) {
[self.fmDB close];
return NO;
}
//获取当前登录用户的id
int userid = [[UserDataBase sharedDataBase]getCurrentLoginUser].ID;
//打开数据库成功,执行添加语句
BOOL success = [self.fmDB executeUpdateWithFormat:SQL_INSERT,userid,oneNew.title,oneNew.time,oneNew.pic,oneNew.content,oneNew.url,oneNew.weburl];
//假设不成功
if (!success) {
[self.fmDB close];
return NO;
}
[self.fmDB close];
return YES;
}
- (NSMutableArray *)getUserSvedNews{
if (![self.fmDB open]) {
[self.fmDB close];
return nil;
}
FMResultSet *resSet = [self.fmDB executeQueryWithFormat:SQL_SELECT,[UserDataBase sharedDataBase].getCurrentLoginUser.ID];
NSMutableArray *arr = [[NSMutableArray alloc]init];
while ([resSet next]) {
News *oneNew = [[News alloc]init];
oneNew.ID = [resSet intForColumn:@"id"];
oneNew.title = [resSet stringForColumn:@"title"];
oneNew.time = [resSet stringForColumn:@"time"];
oneNew.pic = [resSet stringForColumn:@"pic"];
oneNew.content = [resSet stringForColumn:@"content"];
oneNew.url = [resSet stringForColumn:@"url"];
oneNew.weburl = [resSet stringForColumn:@"weburl"];
[arr insertObject:oneNew atIndex:0];
}
//如果数组中没有数据,表示用户没有收藏过任何新闻,返回nil
if (arr.count == 0) {
[self.fmDB close];
return nil;
}
//数组中有数据,将数组返回给controller
[self.fmDB close];
return arr;
}
- (BOOL)deleteOneNewsByID:(int)delID{
if (![self.fmDB open]) {
[self.fmDB close];
return NO;
}
BOOL success = [self.fmDB executeUpdateWithFormat:SQL_DELETE,delID];
if (!success) {
[self.fmDB close];
return NO;
}
[self.fmDB close];
return YES;
return NO;
}
@end
NewsViewController.h
#import
@interface NewsViewController : BaseViewController
@end
NewsViewController.m
#import "NewsViewController.h"
#import "NewsDetailViewController.h"
#import "NewsCollectionViewCell.h"
#import "UIImageView+WebCache.h"
#define TITLE_HEIGHT 44 //标题视图的高度
#define TITLE_BTN_WIDTH (( SCR_W - 44)/6) // 每个标题按钮的宽度
#define COLLECTION_CELL_REUSE @"collectionCell"//网格单元格的复用标识
@interface NewsViewController ()
{
NSMutableArray *_titleArr;//标题数组
NSMutableArray *_contentArr;//新闻内容数组
NSInteger _currentIndex;//当前选中的标题按钮的tag值
int _newsStart; //获取新闻的起始位置
}
//标题滚动视图
@property (nonatomic,strong)UIScrollView *titleScrView;
//标题指示标签
@property (nonatomic,strong)UIView *titleDownLine;
//标题添加按钮
@property (nonatomic,strong)UIButton *titleAddBtn;
//新闻内容的网格视图
@property (nonatomic,strong)UICollectionView *newsCollectView;
//详情控制器
@property (nonatomic,strong)NewsDetailViewController *newsDetailVC;
@end
@implementation NewsViewController
#pragma mark ===== 改变按钮和指示线 ====
-(void)changeSelectButtonAndDownLineWithButtonTag:(NSInteger)tag{
// 如果选中的其他按钮,先将所有的按钮置为normal状态
for (UIView *sub in self.titleScrView.subviews) {
if ([sub isKindOfClass:[UIButton class]]) {
UIButton *btn = (UIButton *)sub;
btn.selected = NO;
if (btn.tag == tag) {
btn.selected = YES;
_currentIndex = btn.tag;
}
}
}
[UIView animateWithDuration:0.138 animations:^{
// 移动指示条
self.titleDownLine.frame = CGRectMake((tag - 200) * TITLE_BTN_WIDTH, TITLE_HEIGHT - 2, TITLE_BTN_WIDTH, 2);
}];
}
#pragma mark - 触发事件
//标题按钮触发
- (void)titleButtonPress:(UIButton *)sender{
// 如果选择了当前选中的按钮,不做任何处理,结束方法
if (_currentIndex == sender.tag) {
return;
}
//让网格视图跟着滚动
//[self.newsCollectView scrollRectToVisible:CGRectMake(SCR_W*(sender.tag - 200), 0, SCR_W, SCR_H-TITLE_HEIGHT) animated:YES];
[self .newsCollectView setContentOffset:CGPointMake(SCR_W*(sender.tag- 200), 0) animated:NO];
}
//标题添加按钮
- (void)titleAddButtonPress:(UIButton *)sender{
}
#pragma Mark-- 实例化重写
//标题滚动视图
- (UIScrollView *)titleScrView{
if (!_titleScrView) {
_titleScrView = [[UIScrollView alloc]initWithFrame:CGRectMake(0, 0,SCR_W-TITLE_HEIGHT, TITLE_HEIGHT)];
//设置内容视图大小
_titleScrView.contentSize = CGSizeMake(TITLE_BTN_WIDTH * _titleArr.count, TITLE_HEIGHT);
//隐藏自带的水平滚动指示条
_titleScrView.showsHorizontalScrollIndicator = NO;
//添加标题按钮子视图
for (int i = 0; i<_titleArr.count; i++) {
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
btn.frame = CGRectMake(i*TITLE_BTN_WIDTH, 0, TITLE_BTN_WIDTH, TITLE_HEIGHT - 1);
[btn setTitle:_titleArr[i] forState:UIControlStateNormal];
[btn setTitle:_titleArr[i] forState:UIControlStateSelected];
[btn setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
[btn setTitleColor:[UIColor redColor] forState:UIControlStateSelected];
btn.tag = i + 200;
if (i == 0) {
btn.selected = YES;
_currentIndex = 200;
}
[btn addTarget:self action:@selector(titleButtonPress:) forControlEvents:UIControlEventTouchUpInside];
[_titleScrView addSubview:btn];
}
[_titleScrView addSubview:self.titleDownLine];
}
return _titleScrView;
}
//标题指示视图
- (UIView *)titleDownLine{
if (!_titleDownLine) {
_titleDownLine = [[UIView alloc]initWithFrame:CGRectMake(0, TITLE_HEIGHT - 2, TITLE_BTN_WIDTH, 2)];
_titleDownLine.backgroundColor = [UIColor orangeColor];
}
return _titleDownLine;
}
//新闻内容的网格视图
- (UICollectionView *)newsCollectView{
if (!_newsCollectView) {
//实例化流式布局对象
UICollectionViewFlowLayout *flow = [[UICollectionViewFlowLayout alloc]init];
//设置单元格大小
flow.itemSize = CGSizeMake(SCR_W, SCR_H-TITLE_HEIGHT);
//设置滚动方向
flow.scrollDirection = UICollectionViewScrollDirectionHorizontal;
//设置间隔为0
flow.minimumLineSpacing = 0.;
_newsCollectView = [[UICollectionView alloc]initWithFrame:CGRectMake(0, TITLE_HEIGHT, SCR_W, SCR_H-TITLE_HEIGHT) collectionViewLayout:flow];
_newsCollectView.dataSource = self;
_newsCollectView.delegate = self;
//设置分页
_newsCollectView.pagingEnabled = YES;
_newsCollectView.backgroundColor = [UIColor whiteColor];
_newsCollectView.bounces = NO;
//tag值
_newsCollectView.tag = 999;
//注册网格单元格
[_newsCollectView registerClass:[NewsCollectionViewCell class] forCellWithReuseIdentifier:COLLECTION_CELL_REUSE];
}
return _newsCollectView;
}
//标题添加按钮
- (UIButton *)titleAddBtn{
if (!_titleAddBtn) {
_titleAddBtn = [UIButton buttonWithType:UIButtonTypeContactAdd];
_titleAddBtn.frame = CGRectMake(SCR_W - TITLE_HEIGHT, 0, TITLE_HEIGHT, TITLE_HEIGHT);
[_titleAddBtn addTarget:self action:@selector(titleAddButtonPress:) forControlEvents:UIControlEventTouchUpInside];
}
return _titleAddBtn;
}
//详情控制器-新闻
- (NewsDetailViewController *)newsDetailVC{
if (!_newsDetailVC) {
_newsDetailVC = [[NewsDetailViewController alloc]init];
}
return _newsDetailVC;
}
#pragma mark----------UICollectionViewDelegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
//计算出当前x轴的偏移量
CGFloat disX = scrollView.contentOffset.x;
//计算出当前显示的标题的下标
int index = disX / SCR_W;
/*
2 -- 让标题滚动视图上的按钮跟着变化
*/
// 选中的按钮变化
if (index > _currentIndex - 200) {
[self.titleScrView scrollRectToVisible:CGRectMake(TITLE_BTN_WIDTH*(index+1), 0, TITLE_BTN_WIDTH, TITLE_HEIGHT) animated:YES];
}else{
[self.titleScrView scrollRectToVisible:CGRectMake(TITLE_BTN_WIDTH*(index-1), 0, TITLE_BTN_WIDTH, TITLE_HEIGHT) animated:YES];
}
/*
3.数据变化
*/
if (index != _currentIndex - 200) {
_newsStart = 0;
[self getURLDatasWithChannel:_titleArr[index] start:_newsStart];
}
[self changeSelectButtonAndDownLineWithButtonTag:index + 200];
}
#pragma mark----------UICollectionViewDataSource
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
return _titleArr.count;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
NewsCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:COLLECTION_CELL_REUSE forIndexPath:indexPath];
if (cell == nil) {
cell = [[NewsCollectionViewCell alloc]initWithFrame:CGRectMake(0, 0, SCR_W, SCR_H-TITLE_HEIGHT)];
}
//为cell中的表格视图设置代理
cell.newsTable.dataSource = self;
cell.newsTable.delegate = self;
//为cell中的下拉刷新视图设置回调代码块
cell.mjHeadView.beginRefreshingBlock = ^(MJRefreshBaseView *refreshView) {
_newsStart = 0;
[self getURLDatasWithChannel:_titleArr[_currentIndex-200] start:_newsStart];
};
//为cell中的上拉刷新视图设置回调代码块
cell.mjFootView.beginRefreshingBlock = ^(MJRefreshBaseView *refreshView) {
_newsStart += 15;
[self getURLDatasWithChannel:_titleArr[_currentIndex-200] start:_newsStart];
};
return cell;
}
#pragma mark -UITableViewDelegate
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
//获取当前cell对应的新闻数据
News *selectNews = _contentArr[indexPath.row];
self.newsDetailVC.passNew = selectNews;
[self.navigationController pushViewController:self.newsDetailVC animated:YES];
}
#pragma mark ----UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return _contentArr.count;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *identifier = @"tableCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:identifier];
}
News *oneNew = _contentArr[indexPath.row];
cell.textLabel.text = oneNew.title;
[cell.imageView sd_setImageWithURL:[NSURL URLWithString:oneNew.pic] placeholderImage:[UIImage imageNamed:@"40"] completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
}] ;
return cell;
}
#pragma mark - 请求网络数据方法
- (void)getURLDatasWithChannel:(NSString *)channel start: (int)start{
//显示等待指示器
[self.newsCollectView showIdicatorMBProgressHUD];
//显示状态栏指示器
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
URLService *urlSer = [[URLService alloc]initWithCompletion:^(id data, BOOL success) {
//停止等待指示器
dispatch_async(dispatch_get_main_queue(), ^{
//停止MBProgressHUD刷新
[self.newsCollectView hideIdicatorMBProgressHUD];
//停止状态栏指示器
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
//停止下拉刷新和上拉刷新
for (NewsCollectionViewCell *cell in self.newsCollectView.visibleCells) {
if (cell.mjHeadView.isRefreshing) {
[cell.mjHeadView endRefreshing];
}
if (cell.mjFootView.isRefreshing) {
[cell.mjFootView endRefreshing];
}
}
});
//根据返回的数据,做提示
if (!success) {
dispatch_async(dispatch_get_main_queue(), ^{
[self.view showTextStyleMBProgressHUDWithTitle:@"网络请求失败"];
});
}else{
if (start == 0) {
//刚开始加载或下拉刷新,对表格数据重新赋值
_contentArr = [data mutableCopy];
}else{
[_contentArr addObjectsFromArray:data];
}
dispatch_async(dispatch_get_main_queue(), ^{
for (NewsCollectionViewCell *cell in self.newsCollectView.visibleCells) {
[cell.newsTable reloadData];
}
});
}
}];
[urlSer getNewsByChannel:channel start:start];
}
#pragma mark - viewDidLoad
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
_titleArr = [@[
@"头条",
@"新闻",
@"财经",
@"体育",
@"娱乐",
@"军事",
@"教育",
@"科技",
@"NBA",
]mutableCopy];
self.view.backgroundColor = [UIColor whiteColor];
[self.view addSubview:self.titleScrView];
[self.view addSubview:self.titleAddBtn];
UIView *view = [[UIView alloc]init];
[self.view addSubview:view];
[self.view addSubview:self.newsCollectView];
//获取网络数据
_currentIndex = 200;
_newsStart = 0;
[self getURLDatasWithChannel:_titleArr[_currentIndex - 200] start:_newsStart];
//让表格的下拉刷新视图开始刷新
for (NewsCollectionViewCell *cell in self.newsCollectView.visibleCells) {
[cell.mjHeadView beginRefreshing];
}
}
- (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
NewsCollectionViewCell.h
#import
#import "MJRefresh.h"
@interface NewsCollectionViewCell : UICollectionViewCell
@property (nonatomic,strong)UITableView *newsTable;
//刷新控件
//下拉刷新
@property (nonatomic,strong)MJRefreshHeaderView *mjHeadView;
//上拉刷新
@property (nonatomic,strong)MJRefreshFooterView *mjFootView;
@end
NewsCollectionViewCell.m
#import "NewsCollectionViewCell.h"
@implementation NewsCollectionViewCell
- (instancetype)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
self.newsTable = [[UITableView alloc]initWithFrame:CGRectMake(0, 0, SCR_W, SCR_H-44-108)style:UITableViewStylePlain];
[self.contentView addSubview:self.newsTable];
//给表格视图添加"下拉刷新"和"上拉刷新"视图
self.mjHeadView = [[MJRefreshHeaderView alloc]initWithScrollView:self.newsTable];
self.mjFootView = [[MJRefreshFooterView alloc]initWithScrollView:self.newsTable];
}
return self;
}
@end
NewsDetailViewController.h
#import
@interface NewsDetailViewController : BaseViewController
@property (nonatomic,strong)News *passNew;
@end
NewsDetailViewController.m
#import "NewsDetailViewController.h"
#import "LoginViewController.h"
@interface NewsDetailViewController ()
@property (nonatomic,strong)UIWebView *webView;
@end
@implementation NewsDetailViewController
-(UIWebView *)webView{
if (!_webView) {
_webView = [[UIWebView alloc]initWithFrame:CGRectMake(0, 0, SCR_W, SCR_H)];
_webView.delegate = self;
}
return _webView;
}
#pragma mark -UIWebViewDelegate
- (void)webViewDidStartLoad:(UIWebView *)webView{
}
- (void)webViewDidFinishLoad:(UIWebView *)webView{
[self.view hideIdicatorMBProgressHUD];
}
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error{
[self.view hideIdicatorMBProgressHUD];
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.view.backgroundColor = [UIColor whiteColor];
[self addShareButtonToNavigationRightBarItem];
[self.saveBtn addTarget:self action:@selector(saveButtonPress:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:self.webView];
}
#pragma mark - 触发方法
- (void)saveButtonPress:(id)sender{
NSLog(@"*********执行收藏");
//隐藏弹出的收藏视图
[self hidePopView];
//如果没有登录
if (![[UserDataBase sharedDataBase]userHadLogin]) {
LoginViewController *loginVC = [[LoginViewController alloc]init];
[self presentViewController:loginVC animated:YES completion:nil];
}
//登录过
else{
//执行收藏
BOOL success = [[NewsDataBase sharedDataBase]addNews:self.passNew];
if (success) {
[self.view showTextStyleMBProgressHUDWithTitle:@"收藏成功"];
}
else{
[self.view showTextStyleMBProgressHUDWithTitle:@"收藏失败"];
}
}
}
- (void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
if (self.webView) {
[self.webView removeFromSuperview];
self.webView = nil;
}
[self.view addSubview:self.webView];
NSString *urlStr = self.passNew.url;
NSURL *url = [NSURL URLWithString:urlStr];
NSURLRequest *req = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:6.0];
[self.webView loadRequest:req];
[self.view showIdicatorMBProgressHUD];
}
-(void)viewWillDisappear:(BOOL)animated{
[super viewWillDisappear:animated];
[self.webView stopLoading];
self.webView = nil;
}
- (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