iOS 小说阅读器APP 仿追书神器

最近正好有空,花两周多写了个基本的小说阅读器,仿照追书神器,数据源和UI都是抓追书神器,实现了书籍搜索、排行榜、自动缓存、下载等功能;最后会给出github链接,欢迎star,交流,参考学习...
下面整理一下开发中遇到的一些问题:

  1. UIPageViewController
    UIPageViewControllerUIPageViewControllerTransitionStylePageCurl模式没有什么问题,在UIPageViewControllerTransitionStyleScroll模式下,第一次向后滑动时也会响应获取前一页的方法,这个需要注意一下;然后更换章节的时候,调用setViewControllers:direction:animated:completion:方法,这时候UIPageViewController没有清空其内部缓存,它认为已经知道前/后一个页面的存在,不会调用dataSource的代理方法,这时候会导致章节错误;现在的处理方法如下:
     __weak typeof(self) wself = self;
    [_pageViewController setViewControllers:@[[self readPageViewWithChapter:_chapter page:_page]] direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:^(BOOL finished) {
        if (finished && !wself.isPageCurlStyle) {
            dispatch_async(dispatch_get_main_queue(), ^{
                [wself.pageViewController setViewControllers:@[[wself readPageViewWithChapter:wself.chapter page:wself.page]] direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:nil];
            });
        }
    }];

网上有文章说这样处理可能会crash,但是现在没有测试到,而且他的是网易新闻那种,谁试用了会crash的话可以联系我(主要这种解决方式简单,不然自己撸个轮子感觉太麻烦了);

  1. 小说分页
    分页主要采用CoreText中的两个方法:CTFramesetterCreateFrameCTFrameGetVisibleStringRange,具体参数和作用方法里都有介绍;代码如下:
- (void)pagingWithBounds:(CGRect)bounds {
    _pageArr = @[].mutableCopy;
    YReaderSettings *settings = [YReaderSettings shareReaderSettings];
    NSString *content = settings.isTraditional ? self.traditionalStr : self.body;
    NSMutableAttributedString *attr = [[NSMutableAttributedString  alloc] initWithString:content attributes:settings.readerAttributes];
    CTFramesetterRef frameSetter = CTFramesetterCreateWithAttributedString((__bridge CFAttributedStringRef) attr);
    CGPathRef path = CGPathCreateWithRect(bounds, NULL);
    CFRange range = CFRangeMake(0, 0);
    NSUInteger rangeOffset = 0;
    do {
        CTFrameRef frame = CTFramesetterCreateFrame(frameSetter, CFRangeMake(rangeOffset, 0), path, NULL);
        range = CTFrameGetVisibleStringRange(frame);
        rangeOffset += range.length;
        [_pageArr addObject:@(range.location)];
        if (frame) {
            CFRelease(frame);
        }
    } while (range.location + range.length < attr.length);
    if (path) {
        CFRelease(path);
    }
    if (frameSetter) {
        CFRelease(frameSetter);
    }
    _pageCount = _pageArr.count;
    _attributedString = attr;
}

这里一个主要问题是实际显示如果和计算分页时的CGRect相同,可能会少显示一行,处理为程序中显示的Rect会比计算时高度增加一点,防止由于行高或者CTFrameGetVisibleStringRange计算与实际显示之间的误差。

3.获取电池电量
[[UIDevice currentDevice] batteryLevel]获取电池电量不准,替代方法如下:

- (double)getCurrentBatteryLevel {
    UIApplication *app = [UIApplication sharedApplication];
    if (app.applicationState == UIApplicationStateActive || app.applicationState==UIApplicationStateInactive) {
        Ivar ivar = class_getInstanceVariable([app class],"_statusBar");
        id status  = object_getIvar(app, ivar);
        for (id aview in [status subviews]) {
            int batteryLevel = 0;
            for (id bview in [aview subviews]) {
                if ([NSStringFromClass([bview class]) caseInsensitiveCompare:@"UIStatusBarBatteryItemView"] == NSOrderedSame) {
                
                    Ivar ivar=  class_getInstanceVariable([bview class],"_capacity");
                    if (ivar) {
                        batteryLevel = ((int (*)(id, Ivar))object_getIvar)(bview, ivar);
                        NSLog(@"电池电量:%zi %%",batteryLevel);
                        if (batteryLevel > 0 && batteryLevel <= 100) {
                            return batteryLevel/100.0;
                        }
                    }
                }
            }
        }
    }
    return 0;
}

4.简体转繁体
这里的方法比较麻烦,拿到所有简体和繁体的文字,找出要替换文字在简体中的位置,用繁体中对应位置的文字一一替换,不知道谁有没有更好的方法;

- (NSString *)transformToTraditionalWith:(NSString *)string {
    NSMutableString *mutableStr = string.mutableCopy;
    NSInteger length = [string length];
    for (NSInteger i = 0; i< length; i++) {
        NSString *str = [string substringWithRange:NSMakeRange(i, 1)];
        NSRange gbRange = [self.simplifiedStr rangeOfString:str];
        if(gbRange.location != NSNotFound) {
            NSString *tString = [self.traditionalStr substringWithRange:gbRange];
            [mutableStr replaceCharactersInRange:NSMakeRange(i, 1) withString:tString];
        }
    }
    return mutableStr.copy;
}

5.其他功能

首页
书籍详情

阅读设置等

本来准备GIF图,但是简书只能上传5M以下文件,详细功能可下载GitHub源码看:
项目地址:https://github.com/yanxuewen/YReaderDemo

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,835评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,598评论 1 295
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,569评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,159评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,533评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,710评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,923评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,674评论 0 203
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,421评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,622评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,115评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,428评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,114评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,097评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,875评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,753评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,649评论 2 271

推荐阅读更多精彩内容

  • 1、通过CocoaPods安装项目名称项目信息 AFNetworking网络请求组件 FMDB本地数据库组件 SD...
    X先生_未知数的X阅读 15,937评论 3 118
  • 这是2018年5月初的北京城某小区,停车场就是院里路边树下,此车停留了3天,已是惨不忍睹 罪魁众多祸首可数,风沙雾...
    慵懒也醉阅读 248评论 0 0
  • 也许大学都是类似的吧,校门有几家超市,商品胡乱地摆着。小饭馆最是热闹,每到饭点便弥漫起油烟气。网吧至少会有两三家开...
    我才是横笛吹雨阅读 175评论 1 1
  • 今天是开学第三天。 开学后,我发现孩子们变了许多:赵智淳长高了,相子萱、雨轩掉了门牙。李文昊读课文不再单字蹦,而且...
    林下泉声阅读 337评论 1 4
  • 最近在app上帮忙做了一个日志发布的功能模块,最开始敷衍,因为不是属于我的产品线,听起来是个超级简单的功能,在实际...
    墨韵书香阅读 412评论 0 3