欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Oc 新闻接口请求数据UI布局

程序员文章站 2022-06-14 15:23:01
...

添加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 <UIKit/UIKit.h>
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 <Foundation/Foundation.h>
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 <Foundation/Foundation.h>
#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 <Foundation/Foundation.h>

@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 <Foundation/Foundation.h>
#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 <UIKit/UIKit.h>

@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 ()<UICollectionViewDelegate,UICollectionViewDataSource,UITableViewDataSource,UITableViewDelegate>
{
    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 <UIKit/UIKit.h>
#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 <UIKit/UIKit.h>

@interface NewsDetailViewController : BaseViewController
@property (nonatomic,strong)News *passNew;
@end

NewsDetailViewController.m

#import "NewsDetailViewController.h"
#import "LoginViewController.h"
@interface NewsDetailViewController ()<UIWebViewDelegate>
@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