V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX  ›  jox  ›  全部回复第 9 页 / 共 21 页
回复总数  406
1 ... 5  6  7  8  9  10  11  12  13  14 ... 21  
2014-11-27 21:15:48 +08:00
回复了 F2Sky 创建的主题 问与答 优酷能不能给个说法?
我有个手机号是在移动工作的朋友给的,没有名字,也不用我充值,每月基本话费10块钱,朋友给我整了个什么计划,每个月都会返钱,正好把那个基本费用给抵掉了,我就用这个手机号来进行一切需要用手机号码注册的网络活动
@q84629462 网络图片下载下来之后都要自己裁剪的,会有哪个第三方的网站给你提供免费的裁剪服务啊?除非你请求的API返回的图片都是放在他们家的服务器上,并且有明确的接口提供缩略图,否则你在只有一个url的情况下只能自己做裁剪,难不成你还要parse每个图片的url看看这个url指向的网站是否提供缩略图服务?这不是搞笑呢吗?人家凭什么提供API帮你裁剪图片啊?你又不是拿着图片去别人的网站在线操作,你是想直接发送一个图片的url和指定你希望得到的尺寸,你就想让别人帮你裁剪图片再发给你?做梦呢?这些我觉得是常识,你怎么会希望有人提供这种服务呢?


如果你不使用text kit来进行排版的话,直接把html丢给text view或者web view,这些图片什么时候被加载你是没办法控制的,也许你可以像上面那个哥们说的,使用url protocol对每个发送的请求进行检查,但是你都说了是论坛的app,那么这个论坛的api返回的html里的图片就有可能来自世界上任意一台电脑,你的程序拿到的只是一个url而已,你甚至不知道这个url指向的是否是有效的资源,那么你除了尝试从这个url下载资源以外你还能做什么?你只能在图片成功下载下来之后再进行裁剪,再作为数据返回给之前发送请求的对象。绕了一圈之后既不会节省流量,也不会使你的应用响应速度变快。而且还要面对因为使用text view和web view渲染图片带来的性能问题,text view渲染html的速度非常慢,论坛返回的数据是一个列表,即使你使用table view也会至少有两三个web view存在于内存中,如果连续有几个帖子的内容很短,可能会有五六个web view存在于内存中,如果某个帖子的内容字数稍微多一点的话,再配合图片,你的应用的内存占用会很高,而且渲染的速度也不会很理想,很有可能会导致滑动时候的卡顿,这些你都要解决。

在我看来这样做很麻烦
--
NSMutableAttributedString *string = [[NSMutableAttributedString alloc] initWithData:[html dataUsingEncoding:NSUnicodeStringEncoding] options:options documentAttributes:nil error:&error];

[string enumerateAttribute:NSAttachmentAttributeName inRange:NSMakeRange(0, string.length) options:0 usingBlock:^(id value, NSRange range, BOOL *stop) {
if (value) {
NSTextAttachment *ment = value;
ment.image = [UIImage imageNamed:@"noavatar"];
}
}];
--

这是15L的代码,如果这里的变量html指向的数据是html字符串,那么哪来的NSTextAttachment属性?你怎么知道那个enumerate block里的value的类型一定是NSTextAttachment呢?你用UIImage的imageNamed这个方法,当然会读取图片了,但是你根本不知道ment这个指针指向的对象的类型是什么,所以你不能保证ment一定有个image属性,事实上在这里你什么都不知道,完全就是在胡搞

你要这样构造包含附件的富文本

--

NSMutableAttributedString *richText = [[NSMutableAttributedString alloc] initWithString:@"rich text with image attachment: "];
NSTextAttachment *attachment = [[NSTextAttachment alloc] init];
attachment.image = image; // suppose image exists
attachment.bounds = CGRectZero; // configure size of attachment
[richText appendAttributedString:[NSAttributedString attributedStringWithAttachment:attachment]];

--

然后你可以直接把这个richText丢给text view,让text view使用默认的配置来渲染这个包含附件的富文本,你也可以使用text kit或者core text来渲染。text kit会自动帮你进行排版,你只需要创建text kit的几个核心对象并把它们组合起来,然后使用richText作为text storage,剩下的都交给text kit来做。我建议你再好好看看我回复你的内容,如果你发现你并没有真正看明白我在说什么,说明你需要看文档了。

你认为的最麻烦的办法在我看来是最简单的办法,iOS平台图文混排大家都是这么做的,你检索一下iOS图文混排就知道了,当然,你也可以使用web view来渲染html,你可以使用一个html wrapper,然后使用css来控制排版,这样的话就是web kit在帮你做parse,typesetting,loading image, render这四个步骤的工作了,可是你确定要在你的应用里使用一个浏览器来渲染一小段html文本吗?如果你需要在多个地方显示html文本,比如在一个table view里,你怎么确定web view的高度是多少呢?

我看了你的另一个问有没有提供缩略图服务的帖子,我真是无语了。你知道你在要求什么吗?你在要求别人帮你从另一个地方下载图片,然后再帮你生成一个缩略图版本的图片传给你,然后猜猜what's the best part?for free!!如果是你你会接受这种要求吗?假设真有人傻到愿意提供这种服务,并且牛逼到能够很好地提供这种服务,你得到的这个缩略图需要多长时间你考虑过没?本来是Server->Client->resize的一个过程被你搞成了Server->Server->resize->Client,常识啊兄弟,你真的是一名程序员吗?你真的清楚自己在干什么吗?
“分割html再解析,关键在哪里截断html字符串,会有截断html标签的可能,这也是个难题。。。”

我又看了一下你的回复,上面我引用的这个,额,这不是难题。。。。现在的难题是你需要了解一些常识性的东西。。。

假设你得到了这样的一个字符串:

dude check this <img src="/images/huge_rack"> out!!!

你可以认为这个字符串是一段html,经过parser处理之后你得到的数据结构可能是这样的:

(tree, (
(text, "dude check this "),
(img, nil, ((src, "/images/huge_rack"))),
(text, " out!!!")
))

这个数据结构有三个子节点,第一个节点的类型是text,值是字符串"dude check this "
第二个节点的类型是img,值为空,包含一个类型为src的属性,属性的值为字符串"/images/huge_rack"

第三个节点的类型又是text,以此类推,如果你需要处理的数据都是这种结构的话,一个循环就够了,否则你就得采用深度优先的方式递归地遍历这个数据结构。

你遍历这个数据结构,并根据每个节点的类型执行相应的动作将其转化成NSAttributedString,然后交给text kit来负责排版,你负责下载图片(如果有的话)。text kit排版完之后在某个时间点会根据用户的操作会把排好版的字形渲染到屏幕上,这期间或者之后如果你从网上下载到了图片,你就要问text kit哪些地方它帮你为附件留了空,你把下载并裁剪好的图片插入或者绘制到这些空里。

额,我只能帮你到这里了,按照我说的方法的话就是这么做。
2014-11-27 00:11:38 +08:00
回复了 jox 创建的主题 iDev 这个挺逗的, text from code
@PrideChung 好吧,其实如果你不说,我都想不起来有NSNumber这个类型,我就当时看苹果的那个programming with objective c里提到过这个类型,实际写程序的时候我从来没用过,因为UIKit里很多类的跟数字有关的属性类型都是NSInteger或者NSUInteger,我也就跟着用了,对我来说我只需要一个变量来保存数字,NSInteger用着没啥问题,就用了,没想太多
2014-11-27 00:02:17 +08:00
回复了 jox 创建的主题 iDev 这个挺逗的, text from code
@PrideChung 这个跟32位和64位有关系吗?NSInteger的类型是long,long的实现到底是32位还是64位的这个是跟平台有关的。

我当时是想用数字构造字符串,只是想消灭警告而已,NSInteger是long,会出现这个警告似乎是因为整型非负数字常量的类型是unsigned long,而xcode似乎不能确定表达式num - 10的类型是哪个?似乎xcode对类型的判断非常的严格,如果不明确表达式的类型的话就会遇到这种警告。

实际上这样做也挺好,像C就有很多implicit的类型转换,有的时候可能会造成一些难以察觉的bug,所以xcode大概就减少这样的类型转换了吧。不过并不是所有的情况都是如此,比如使用%d格式来匹配i / 2这样的表达式就不会报警告,其中i的类型是int。当初第一次遇到这个警告的时候着实浪费了我足足好几分钟的时间,其实num - 10的类型是啥我根本不关心,因为那个数字最大也没多少,使用NS开头的类型只是为了让代码保持一致性而已,xcode非得这么严格我也是没办法
2014-11-26 23:38:47 +08:00
回复了 jox 创建的主题 iDev 这个挺逗的, text from code
@11 这个我遇到过,浪费了我将近5分钟的时间

NSInteger num = 10;
NSLog(@"%ld", num - 10);

然后有警告,说类型和格式不匹配,问我是不是要改成%lu?好吧,我改成:

NSLog(@"%lu", num - 10);

还是不行,说类型和格式不匹配,我就郁闷了,最后我发现我得改成这样:

NSLog(@"%lu", (unsigned long)(num - 10));

当时我就无语了。。。。xcode,你是在玩我呢吗?
@q84629462 lazy loading手动实现还是很困难的,你要借助UIScrollView,获取当前SCrollVIew的bounds的值,假设你只使用一个text view来渲染文本,那么你就要判断text view的哪部分在当前scroll view 的bounds里,然后只渲染这部分的内容,我猜你是要写v2ex的iOS客户端是吗?如果是的话,你可以不用自己实现,使用uitableview或者collection view就行,那个自带lazy loading的机制。

虽然parse html借助工具很简单,不过你大概得了解一下词法分析和语法分析的概念,使用工具parse html得到的是一个树状的数据结构,人们叫这种数据结构为DOM(Document Object Model),你需要遍历这个数据结构然后将其转化成你需要的另外一种数据结构,在你遇到的这个问题里,你需要将DOM转化成NSAttributedString,然后再使用text kit进行排版和渲染
@PrideChung lz似乎是想写v2ex的客户端?这样看来v2ex的API返回的数据也是html咯?

v2ex的帖子内容似乎只支持图片这一种html tag,那parse的话就很简单了,借助已有的工具根本不用自己做什么,拼凑一下就能用了,如果只是简单的图文混排的话就更容易了,使用text kit的话连定制都用不到,直接用就行了,我觉得完全没难度啊。

不过也可能是因为我不了解你说的这个urlprotocol的缘故,总之我的话就是parse html,然后使用text kit来排版和渲染html,html里如果有img标签的话就直接下载,然后裁剪和渲染,这样子。
@q84629462 这不是异想天开,这是lazy loading,你如果要渲染大量的html文本的话,lazy loading不是“异想天开”,而是你必须要实现的,要么借助uitableview,要么你自己实现,否则内存占用会成为很严重的一个问题,iOS下几乎所有的view都使用CALayer来渲染内容,Core Animation会cache生成的render数据,这些数据非常占内存,光渲染一大段文字就需要将近20M的内存,如果你不能确定将要渲染多少数据的话,图片必须经过裁剪再使用,而且也必须使用lazy loading的策略,否则内存占用轻轻松松就会破百。
@q84629462 文字的排版的确是很艰深的一个问题领域,不过你要处理的这个问题非常非常的简单,就用text kit就能解决,另外,请不要使用正则表达式来parse html,html是context free的语言,你不能使用正则表达式来处理html。

网上已经有写好的代码可以很简单地parse html,我说的那个hpple就很好用,请千万不要使用正则表达式来处理HTML,不信你可以试试,我保证你会后悔的
@PrideChung 。。。。。。。。。。我觉得操作网络请求更麻烦,core text是不太好用(其实也还行),但是text kit很简单啊,如果使用textview的话只需要parse一下html就可以了,不使用textview直接用text kit渲染也挺简单的啊,一共也没几行代码,怎么会麻烦呢?
@PrideChung 我不知道,我也刚接触iOS开发没多久,我没用过你说的这个NSURLProtocol,需要进行network call的时候我使用的是iOS7出来的NSURLSession,用起来挺简单的,按照你说的这种拦截网络请求怎么感觉那么别扭呢?程序得到一个url,程序想要得到这个url指向的资源,直接向这个url发送网络请求不就好了吗,替换url干啥啊。。。。

即使能够拦截网络请求,你也不能保证你从网上得到的一段html文本里面的某个img tag里的src指向的图片资源一定有对应的缩略图版本,即使有你也不一定知道对应的缩略图版本的url是什么

我觉得正确的做法就是先parse html,然后使用得到的src属性里的url试图从网上下载这个url指向的资源,如果下载成功,那么就使用image I/O框架提供的API将图片裁剪成合适的缩略图尺寸得到图片的数据,然后再考虑是否要cache,然后再想办法渲染图片。如果下载失败,那就不渲染,这个逻辑不是更简单吗?
@PrideChung 我不是来问问题的,我是被lz召唤过来的,webview的use case是用来渲染某个url的,webview的frame是固定的,相当于在应用里嵌入了个浏览器,类似html里的iframe,不需要考虑排版

但是lz要使用缩略图来渲染图片,这就涉及到了排版,只能使用text kit或者core text来实现
@PrideChung uiwebview很占内存,uiwebview不是用来渲染文本的,而且使用uiwebview的话不能控制排版,只有全部加载完之后才能知道准确的尺寸,如果一段html里有多个img tag的话,这些图片的请求是没法控制的,而且还得使用javascript,蛋疼的要死。

直接parse html得到图片的url之后自己控制网络请求就很简单了,uiwebview是用来显示网页的,不是用来处理使用html作为数据结构传输的数据的。
2014-11-26 21:21:12 +08:00
回复了 dopcn 创建的主题 iDev stringWithFormat 性能很差,有哪些比较好的替代方案?
ಠ_ಠ ಠ_ಠ ಠ_ಠ ಠ_ಠ ಠ_ಠ
text kit不是“NSAtrributedString和NSTextAttachment”,text kit是一整套的文字排版方案,NSAtrributedString是text kit能够处理的数据类型,NSTextAttachment是text kit接受的数据类型的其中一种属性。你能说出这种话说明你根本不理解text kit,再去看看文档和相关的资料吧,你只有理解了text kit的排版过程你才能解决你遇到的这个问题,不难的,看看文档就行了
当然有区别了,你是直接把html丢给text view然后就不管了,至于text view到底用的什么方法渲染html你是完全不清楚的,我说的是你自己使用text kit手动控制排版。
忘了说了,如果使用text kit的话,你要自己parse html文本,将其转化成attributed string,你可能得写个简单的parser,这个挺简单的,借助别人写的一些工具就行,这个http://www.raywenderlich.com/14172/how-to-parse-html-on-ios 里面的那个hpple就不错,用的是libxml,速度非常快,因为会将html转化成dom树,用起来也很方便,递归地遍历dom树就行了
。。。。。。。。

你使用了document attribute,我不是这样实现的,所以不清楚如果使用document attribute的话要怎么实现图片的点击事件。我不建议你这么做,这样真的很慢,不仅要把字符串转化成NSData,而且还有parse和render html的开销,我不清楚内部是怎么做的,我非常怀疑这样做的话实际上会调用web kit,我刚开始接触这个问题的时候也尝试过使用document attribute,慢的要死。

正确的做法是使用text kit或者core text,建议使用text kit,把图片作为富文本的附件和文本绑定,设定附件的尺寸,然后用text kit的layout manager算出附件的rect,然后再渲染图片,你如果使用textview渲染文本的话,iOS7之后textview有个delegate方法可以捕捉到图片和超链接的点击事件:

textView:shouldInteractWithTextAttachment:inRange:

你还可以创建个gesture recognizer和textview绑定,然后在action里使用layout manager得到图片的信息,如果你不使用textview渲染文本的话,可以在touchesBegan:withEvent:那四个方法里响应tap事件,上面提到的layout manager获取图片信息的方法是这个:
boundingRectForGlyphRange:inTextContainer:

如果你打算渲染gif的话,不要配置NSTextAttachment的image属性,只配置bounds属性,然后或者直接画或者使用UIImageView渲染,如果全是静态图片的话,直接配置image属性就行。

至于图片的缓存和缩略图方面你要自己实现,text kit就是用来对文本进行排版和渲染的,core text也可以,但是text kit用起来简单很多,text kit是在core text的基础上做的封装,记得如果一段文本里图片特别多的话你要注意图片的尺寸不要太高,不然会发生文字不显示的问题。。。
1 ... 5  6  7  8  9  10  11  12  13  14 ... 21  
关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1364 人在线   最高记录 6679   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 17ms · UTC 17:36 · PVG 01:36 · LAX 09:36 · JFK 12:36
Developed with CodeLauncher
♥ Do have faith in what you're doing.