iphone小说类软件用UIPageViewController实现

这个项目已经写了很久了,最近才有空放上来,是我刚开始学习iphone时候的作品,在线小说阅读器。

主要使用了UIPageViewController实现。重点和难点在于每一页中文字占据空间的处理。

根据MVC的做法,首先定义了一个文章内容的实体类Data


@interface NovelContent : NSObject

@property(nonatomic,copy) NSString* sid;//章节id
@property(nonatomic,copy) NSString* chapterName;//章节名
@property(nonatomic,retain) NSMutableString* contentString;//当前章节的内容
@property(nonatomic,retain) NSMutableArray* imageArray;//插图连接序列
@property(nonatomic,strong) NSMutableArray* pageOffset;//当前章节偏移量序列
@property(nonatomic) NSInteger totalPageNum;//总页数
@property(nonatomic) unsigned long long contentSize;//内容总容量

//页数偏移量转换操作
-(NSUInteger)getOffsetWithPage:(NSUInteger)pageNum;
-(NSUInteger)getPageWithOffset:(NSUInteger)offset;

//小说内容数据库操作
+(BOOL)creatTableWithDB:(FMDatabase*)dbase;
-(BOOL)insertContentIntoDB;
+(NovelContent*)queryContentWithID:(NSString*)sid;
+(BOOL)deleteAllRecord;

@end


然后把网络下载的章节保存在本地缓存里,根据文章的文件句柄和设定的字体大小计算文章偏移量

- (unsigned long long)indexOfPage:(NSFileHandle *)handle textFont:(UIFont *)font{
	unsigned long long offset = [handle offsetInFile];
	unsigned long long fileSize = currentNovel.contentSize;
	NSUInteger MaxWidth = maxPageWidth, MaxHeigth = maxPageHeight;
	
	BOOL isEndOfFile = NO;
	NSUInteger length = 64;//截取长度,这个数越小,计算的偏移量越精准,相对运算速度越慢
	NSMutableString *labelStr = [[NSMutableString alloc] init];
	do{
		for (int j=0; j<3; j++) {
			if ((offset+length+j) > fileSize) {
				offset = fileSize;
				isEndOfFile = YES;
				break ;
			}
			[handle seekToFileOffset:offset];
			NSData *data = [handle readDataOfLength:j+length];
			if (data) {
				NSString *iStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
				if (iStr ) {
					NSString *oStr = [NSString stringWithFormat:@"%@%@",labelStr,iStr];
					
					CGSize labelSize=[oStr sizeWithFont:font
									  constrainedToSize:CGSizeMake(MaxWidth,1000)
										  lineBreakMode:UILineBreakModeWordWrap];
					if (labelSize.height-MaxHeigth > 0 && length != 1) {
                        //如果初次截取的字符占的size比预设高度大,则截取长度减半再截
						if (length <= 5) {
							length = 1;
						}else {
							length = length/(2);
						}
					}else if (labelSize.height > MaxHeigth && length == 1) {
                        //截取最后一个字符刚好比预设高度大,判断为文章末尾
						offset = [handle offsetInFile]-length-j;
						[handle seekToFileOffset:offset];
						offset = [self fixOffserWith:handle];
						isEndOfFile = YES;
					}else if(labelSize.height <= MaxHeigth ) {
						[labelStr appendString:iStr];
						offset = j+length+offset;
					}
					break ;
				}
			}
		}
		if (offset >= fileSize) {
			isEndOfFile = YES;
		}
	}while (!isEndOfFile);
	return offset;
}


然后根据偏移量算出每页需要显示的字符串

NSData *data  = [handle readDataOfLength:length];
NSString *content = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

注:length为每一页的偏移量


偏移量就相当于当前文章的总页数,每一页要显示的字符串也算出来了,xcode上自带了UIPageViewController的Demo,demo中我们知道UIPageViewController类中每一页相当于一个UIViewController。

参考Demo我在类中加上delegate

@protocol NovelEngineDelegate <NSObject>

@optional
-(void)addNovelContent:(NSString*)content;//添加每一页内容
-(void)threadProgress:(float)num;//反馈当前进程
-(void)loadComplete:(NSUInteger)totalNum;//加载完成提示

@end

根据MVC的做法,定义一个Controller:

@interface ModelControllerEx : NSObject<UIPageViewControllerDataSource,NovelEngineDelegate>
{
	UIFont *modelFont; //字体大小(与分页有关)
}

@property (nonatomic,retain) NSMutableArray *pageData;

//根据页数查找视图
-(DataViewController *)viewControllerAtIndex:(NSUInteger)index;
//根据当前视图判断页数
-(NSUInteger)indexOfViewController:(DataViewController *)viewController;

-(id)initWithContent:(NovelContent *)novel font:(UIFont*)font;
-(void)reset;
@end

目的就是用来关联上Data和View,然后

self.pageViewController = [[UIPageViewController alloc] initWithTransitionStyle:UIPageViewControllerTransitionStylePageCurl navigationOrientation:UIPageViewControllerNavigationOrientationHorizontal options:nil];
    self.pageViewController.delegate = self;
    
    DataViewController *startingViewController = [modelController viewControllerAtIndex:0];
    NSArray *viewControllers = @[startingViewController];
    [self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:NULL];
    
    self.pageViewController.dataSource = modelController;
    
    [self addChildViewController:self.pageViewController];
    [self.view addSubview:self.pageViewController.view];
    
    CGRect pageViewRect = self.view.bounds;
    if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) {
        pageViewRect = CGRectInset(pageViewRect, 40.0, 40.0);
    }
    self.pageViewController.view.frame = pageViewRect;
    
    [self.pageViewController didMoveToParentViewController:self];

做小说类型的软件,如果想加载处理得更快的话按我的做法是先初始同步加载前三页,然后之后的页面放到后台线程继续加载。




评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值