本文章只是在个人学习IOS开发中所写的Demo,仅供IOS开发新手入门参考。仅需实现一款豆瓣读书App的简单功能,包括搜索书籍,查看书籍列表以及书籍详情页。
1.开发环境:
mac OS 10.13.4、Xcode9.3.1、Objective-C
2.使用cocoapods管理第三方工具和类库
怎么安装就不说了,直接贴链接 http://www.code4app.com/article/cocoapods-install-usage
要使用到的第三方类库,AFNetworking和SDWebImage
在Podfile文件中编辑添加pod 'AFNetworking','~>3.1.0' pod 'SDWebImage','~>4.3.0'
# Uncomment the next line to define a global platform for your project
platform :ios, '9.0'
target 'DoubanDemo' do
# Uncomment the next line if you're using Swift or would like to use dynamic frameworks
# use_frameworks!
pod'AFNetworking','~>3.1.0'
pod'SDWebImage','~> 4.3.0'
# Pods for DoubanDemo
target 'DoubanDemoTests' do
inherit! :search_paths
pod 'Cedar', git: 'https://github.com/pivotal/cedar.git'
# Pods for testing
end
target 'DoubanDemoUITests' do
inherit! :search_paths
# Pods for testing
end
end
在xcode项目目录下运行命令pod install --no-repo-update自动下载依赖
3.代码思路:使用AFNetworking请求http://api.douban.com/v2/book/search接口,传入参数q和count表示关键字和结果条数,本地接收后拥NSMutableArray来存储书籍信息实体。再使用TableViewController渲染出列表,并为cell添加点击事件,跳转到书籍详情页,同时把书籍信息传递到页面。TableViewCell中需要网络异步加载图片,使用SDWebImage来实现这一部分。
4.在右边的Main.storyboard中拖入NavigationController,将NavigationController自带的Root View Controller删除,将自己的ViewController设置为Root View Controller,并将navigation controller设置为为入口,在ViewController中添加SearchBar,TableView等控件,设置书籍详情页面的布局。storyboard布局如下
书籍实体类,http请求返回的是json数据,再BookInfo中手动写了构造方法去解析json。BookInfo.m
//
// BookInfo.m
// DoubanDemo
//
// Created by dave.luo on 2018/5/23.
// Copyright © 2018年 dave.luo. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "BookInfo.h"
@implementation BookInfo
@synthesize bid;
@synthesize subtitle;
@synthesize author;
@synthesize pubdate;
@synthesize image;
@synthesize translator;
@synthesize catalog;
@synthesize pages;
@synthesize publisher;
@synthesize title;
@synthesize url;
@synthesize author_intro;
@synthesize summary;
@synthesize price;
-(id)initWithJson:(id)data{
bid=data[@"id"];
subtitle=data[@"subtitle"];
author=data[@"author"];
pubdate=data[@"pubdate"];
image=data[@"image"];
translator=data[@"translator"];
catalog=data[@"catalog"];
pages=data[@"pages"];
publisher=data[@"publisher"];
title=data[@"title"];
url=data[@"url"];
author_intro=data[@"author_intro"];
summary=data[@"summary"];
price=data[@"price"];
return self;
}
@end
Book的Service类,再这里的代码中每次请求都只返回10条记录,读者可以自己修改重构。BookService.m
// BookService.m
// DoubanDemo
//
// Created by dave.luo on 2018/5/23.
// Copyright © 2018年 dave.luo. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <AFNetworking/AFNetworking.h>
#import "BookService.h"
#import "BookInfo.h"
@implementation BookService
@synthesize books;
@synthesize block;
//请求书籍搜索服务
-(void)getRequestWithURL:(NSString *)urlStr withKey:(NSString *)keyWord withTableView:(UITableView *)tableView withData:(NSMutableArray *)datas{
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
NSLog(@"%@",keyWord);
[datas removeAllObjects];
NSDictionary *dict=@{
@"q":keyWord,
@"count":@10
};
manager.responseSerializer = [AFJSONResponseSerializer serializer];
[manager GET:urlStr parameters:dict progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject){
//NSMutableArray *books=[NSMutableArray new];
NSArray *json= responseObject[@"books"];
for(id book in json){
BookInfo *b = [[BookInfo alloc]initWithJson:book];
NSLog(@"%@",b.author[0]);
[datas addObject:b];
}
[tableView reloadData];
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error){
NSLog(@"返回失败");
NSLog(@"%@",error);
}];
}
@end
BookTableViewCell类继承了UITableViewCell类,在这里你可以调整cell的布局,通过layoutSubviews方法来固定cell中ImageView的图片大小,防止图片出现异常
//
// BookTableViewCell.m
// DoubanDemo
//
// Created by dave.luo on 2018/5/24.
// Copyright © 2018年 dave.luo. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "BookTableViewCell.h"
@implementation BookTableViewCell
@synthesize lbPrice;
@synthesize bookTitle;
@synthesize subtitle;
@synthesize author;
-(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{
if (self=[super initWithStyle:style reuseIdentifier:reuseIdentifier])
{
CGFloat height = self.frame.size.height;
CGFloat width = self.frame.size.width;
lbPrice = [[UILabel alloc]initWithFrame:CGRectMake(width-20, height+70, 100,20)];
bookTitle = [[UILabel alloc]initWithFrame:CGRectMake(170, 5, 200,50)];
subtitle = [[UILabel alloc]initWithFrame:CGRectMake(170, 45, 200,50)];
author = [[UILabel alloc]initWithFrame:CGRectMake(width-130, height+70, 100,20)];
[lbPrice setTextColor:[UIColor redColor]];
bookTitle.numberOfLines=0;
bookTitle.font = [UIFont systemFontOfSize:19];
subtitle.font = [UIFont systemFontOfSize:16];
subtitle.numberOfLines=0;
[self addSubview:bookTitle];
[self addSubview:lbPrice];
[self addSubview:subtitle];
[self addSubview:author];
}
return self;
}
-(void)layoutSubviews{
[super layoutSubviews];
self.imageView.bounds =CGRectMake(5,5,44,44);
self.imageView.frame =CGRectMake(15,10,115,155);
}
@end
ViewController里面绑定了storyboard中的TableView,实现UITableViewDatasource和UITableViewDelegate两个协议要实现的三个方法numberOfSectionsInTableView,numberOfRowsInSection,cellForRowAtIndexPath。再通过UISearchBarDelegate实现searchBar的搜索按钮点击事件,在点击事件当中,再调用一次请求方法即可。页面跳转的实现只需要实现didSelectRowAtIndexPath方法,通过获取storyboard中的目标Controller,这里我们要给storyboard中书籍详情页的Identifier确定一个id即可。
//
// ViewController.m
// DoubanDemo
//
// Created by dave.luo on 2018/5/23.
// Copyright © 2018年 dave.luo. All rights reserved.
//
#import <AFNetworking/AFNetworking.h>
#import <SDWebImage/UIImageView+WebCache.h>
#import "BookTableViewCell.h"
#import "BookService.h"
#import "BookDetailController.h"
#import "ViewController.h"
#import "BookInfo.h"
@interface ViewController ()<UITableViewDelegate,UITableViewDataSource,UISearchBarDelegate>
@end
@implementation ViewController
@synthesize books;
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
_searchBook.barTintColor=[UIColor colorWithRed:67/255.0 green:189/255.0 blue:86/255.0 alpha:1];
[self.navigationController setNavigationBarHidden:YES animated:YES];
url = @"https://api.douban.com/v2/book/search";
books = [[NSMutableArray alloc]init];
_searchBook.delegate=self;
_bookList.delegate=self;
_bookList.dataSource=self;
bookService = [[BookService alloc]init];
[bookService getRequestWithURL:url withKey:@"python" withTableView:_bookList withData:books];
}
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar{
NSString *key = searchBar.text;
if(![key isEqualToString:@""])
[bookService getRequestWithURL:url withKey:key withTableView:_bookList withData:books];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [self.books count];
}
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return 160;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
BookTableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:@"cellID"];
if(cell==nil){
cell = [[BookTableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"cellID"];
}
BookInfo *book = [books objectAtIndex:indexPath.row];
//cell.textLabel.text= book.title;
cell.subtitle.text = book.summary;
cell.lbPrice.text = book.price;
cell.bookTitle.text=book.title;
cell.author.text =book.author[0];
NSString *imgUrl = book.image;
[cell.imageView sd_setImageWithURL:[NSURL URLWithString:imgUrl] placeholderImage:[UIImage imageNamed:@"placeholder" ]];
//[cell.imageView setFrame:CGRectMake(0, 0, 40, 100)];
// [cell.imageView sd_setImageWithURL:[NSURL URLWithString:imgUrl] completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) {
//
// }];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
BookDetailController *detail = [self.storyboard instantiateViewControllerWithIdentifier:@"detailView"];
detail.book=[books objectAtIndex:indexPath.row];
[self.navigationController pushViewController:detail animated:YES];
}
@end
BookDetailController里面则负责接受和显示详情页的代码,这里就不贴代码了
项目代码已发到github上,https://github.com/ljp88571133/DoubanDemo 欢迎下载