NSString计算字符数 微博字数

http://www.alibuybuy.com/posts/21567.html

先看看新浪、腾讯、网易、搜狐四大门户的微博给出的设计方案:

新浪:140个汉字,280英文字母

腾讯:140个汉字,140英文字母

网易:163个汉字,163英文字母

搜狐:中英文都没限制,可以写1万字以上的小说

新浪、腾讯表面上都抄袭了Twitter,为什么说表面?因为Twitter的140个字符,指的是英文。不同的是,新浪对英文的处理是两个字符算1个字,腾讯是1个字符算1个字,于是同样用英文表达时,新浪的容量是腾讯的2倍,也是Twitter的2倍

虽然大家都是抄袭,腾讯显然是保留了英文用户使用Twitter的习惯,新浪则把英文输入的容量扩大为2倍。

那么,哪种设计更合理一些?

为了解决这个问题,先从Twitter的设计说起,为什么是140个字符?Google了半天,经历了无数次“连接被重置”后,总算找到了一点能说服我的结论,大概归纳到以下几个解释:

1.人脑每次处理信息有限,最多140个英文字符

人类的头脑有认知局限,每次只能处理一定量的信息,德国的一位数学家计算出的这个数字是:160个英文字母,他把这一数字作为手机短信息的标准。

因为每条Tweet都要包含作者、时间、来源等额外信息,去掉大约20个字母的这些附加信息,每条Tweet的文本被限制在140个字符。

想起了邓巴数字:人类智力将允许人类拥有稳定社交网络的人数是148人,四舍五入大约是150人。有点类似,对不对?

2.每条短信息的限制为140个英文字符

Twitter的发展很大程度上依赖于手机网络,手机短信也成为最自然的发送Tweet的方式,将每条Tweet限制在一条短信之内,更符合手机用户的习惯

美国运营商控制的每条短信的字数限制是多少?这个我没法测试,只晓得中国移动和联通控制的每条短信息为70个汉字,140个英文字符,欢迎其他朋友提供信息。

3. 限制会促使作者专注于表达核心内容

这个和第1条不同,从作者的角度考虑,如何把一件事、一个想法表达清楚,其实不需要长篇大论,限定字数会让你的表达更专注于核心内容,能用一句话交代清楚的内容,绝不拖沓。

同样的道理也存在在设计领域:限制往往带来创新

Twitter的设计大概基于以上3点,部分也是我的猜想,有待求证。

从上面分析可以看到,四大门户对Twitter的抄袭都停留在了表面,理想的设计方案应该是:

每条微博字数限制:中文70字,英文140字母,中文标点占2字符,英文标点占1字符

基于这种失败的抄袭,相信习惯了Twitter界面的用户,阅读下面这条写满了140了汉字的新浪微博,应该会感觉到信息量过大,且拖沓,没有了Tweets的轻灵。

上代码

// U-00000000 – U-0000007F: 0xxxxxxx

// U-00000080 – U-000007FF: 110xxxxx 10xxxxxx

// U-00000800 – U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx

// U-00010000 – U-001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

// U-00200000 – U-03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx

// U-04000000 – U-7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx


//
//  NSString+Weibo.h
//  MMBangADDemoProject
//
//  Created by CuiPanJun on 15-1-29.
//  Copyright (c) 2015年 CuiPanJun. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface NSString (Weibo)

// 字符数
-(NSUInteger)charLength;

// 微博字数
-(NSUInteger)weiboLength;

-(NSString *)substringToIndexForWeibo:(NSUInteger)index;

@end


实现文件


//
//  NSString+Weibo.m
//  MMBangADDemoProject
//
//  Created by CuiPanJun on 15-1-29.
//  Copyright (c) 2015年 CuiPanJun. All rights reserved.
//

#import "NSString+Weibo.h"

@implementation NSString (Weibo)

-(NSUInteger)charLength{
    
    NSUInteger length = 0;
    char *cStr = (char *)[self cStringUsingEncoding:NSUTF8StringEncoding];
    NSUInteger strBytesLength = [self lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
    unsigned char *p = (unsigned char*)cStr;
    for (int i=0 ; i<strBytesLength 😉 {
        if(*p >= 0xF0 && *p < 0xF8){
            
            p += 4;
            i += 4;
            
            length ++;
            
        }else if (*p >= 0xE0 && *p < 0xF0) {
            
            p += 3;
            
            i += 3;
            
            length += 2;
            
        }
        
        else if(*p >= 0xB0 && *p < 0xF0) {
            
            p += 2;
            
            i += 2;
            
            length ++;
            
        }else{
            
            p += 1;
            
            i ++;
            
            length ++;
            
        }
        
    }
    
    return length;
}



NSUInteger charLength2WeiboLength(NSUInteger charLength);

-(NSUInteger)weiboLength{
    
    NSUInteger charLength = [self charLength];
    
    return charLength2WeiboLength(charLength);
    
}

NSUInteger charLength2WeiboLength(NSUInteger charLength){
    
    NSUInteger weiboLength = 0;
    
    if (charLength%2) {
        weiboLength = charLength/2 + 1;
    }else{
        weiboLength = charLength/2;
    }
    
    return weiboLength;
}


// 如何正确截取字符串

-(NSString *)substringToIndexForWeibo:(NSUInteger)index{
    
    NSUInteger unicodeCharLength = self.length;
    
    NSUInteger charLength = self.charLength;
    
    NSUInteger weiboLength = [self weiboLength];
    
    if (weiboLength < index) {
        
        return self;
        
    }else{
        
        NSMutableString *mutableStr = [NSMutableString stringWithString:self];
        
        while (weiboLength > index) {
            NSString *lastStr = [mutableStr substringFromIndex:unicodeCharLength-1];
            [mutableStr deleteCharactersInRange:NSMakeRange(unicodeCharLength-1, 1)];
            unicodeCharLength--;
            charLength -= [lastStr charLength];
            weiboLength = charLength2WeiboLength(charLength);
        }
        
        return mutableStr;
    }
}

-  (NSUInteger)charNumber:(NSString*)strtemp {
    
    NSUInteger strlength = 0;
    
    char* p = (char*)[strtemp cStringUsingEncoding:NSUnicodeStringEncoding];
    
    for (NSUInteger i=0 ; i<[strtemp lengthOfBytesUsingEncoding:NSUnicodeStringEncoding] ;i++) {
        
        if (*p) {
            p++;
            strlength++;
        } else {
            p++;
        }
        
    }
    
    return strlength;
}

@end


UIWebView content height

当UIWebView 资源加载完成后(具体什么时候,另外开一篇博客讨论),会调用delegate方法:

-(void)webViewDidFinishLoad:(UIWebView *)aWebView;

在此方法中可以通过aWebView.scrollView.contentSize.height获得适合当前内容的高度,但是这个方法在某些情况下是错误的。

因为苹果的延迟渲染策略,如果view没用在渲染树上的时候,很多操作都会被忽略,比如这里的 aWebView,它并没有去渲染它的内容,甚至没有去计算这些html需要多大空间(aWebView.scrollView.contentSize)。所以,如果aWebView不在渲染树上,aWebView.scrollView.contentSize的值应该就是初始化aWebView时frame.size(总之不是最终正确的contentSize)。如果此时再把aWebView加到渲染树中,它的contentSize就会变成正确值。

所以,可以先将webview添加到渲染树中(找个在渲染树上的view,[view: addSubView:webview];),把它的位置调到不可见的位置,比如CGRectMake(10000, 0, CGRectGetWidth(bounds), 568)。

做得更好的话,可以在keyWindow上弄个view,专门webview容器。大家可以自由发挥

iOS开发调试发布过程中一些非常实用的命令工具

1.使用Finder打开当前目录:open .

cuipanjun:apache2 cuipanjun$ pwd
/private/etc/apache2
cuipanjun:apache2 cuipanjun$ ls
ca.crt		httpd.conf	mime.types	other		server.key
extra		magic		original	server.crt	users
cuipanjun:apache2 cuipanjun$ open .
cuipanjun:apache2 cuipanjun$ 

2.查看ipa中可执行文件 或者 dSYM文件 UUID会用到: dwarfdump

dwarfdump –uuid YourApp.app/YourApp

dwarfdump –uuid YourApp.dSYM

3.otool

4.codesign

5./usr/libexec/PlistBuddy

6.atos

7.ld

8.xcodebuild
9.xcrun
10.lipo
11.nm
12.security 查看mobileprovision文件

Provisioning Profiles are encoded. To decode them and examine the XML you can use this via command line:

security cms -D -i #{@profilePath}

where #{@profilePath} is the filepath to your .mobileprovision file.

A fuller Ruby example is:

require ‘plist’
profile = `security cms -D -i #{@profilePath}`
xml = Plist::parse_xml(profile)
appID = xml[‘Entitlements’][‘application-identifier’]

iOS wireless distribution

1.准备好ipa包 和 manifest.plist文件

https://help.apple.com/deployment/ios/#/apda0e3426d7
以下是苹果关于 manifest文件的一些说明:

关于无线清单文件
清单文件是 XML plist 格式。iOS 设备使用该清单从您的 Web 服务器上查找、下载和安装应用程序。清单文件由 Xcode 创建,使用的是您在共享用于企业分发的归档应用程序时所提供的信息。

以下栏是必填项:

URL:应用程序 (.ipa) 文件的完全限定 HTTPS URL。

display-image:57 x 57 像素的 PNG 图像,在下载和安装过程中显示。指定图像的完全限定 URL。

full-size-image:512 x 512 像素的 PNG 图像,表示 iTunes 中相应的应用程序。

bundle-identifier:应用程序的包标识符,与 Xcode 项目中指定的完全一样。

bundle-version:应用程序的包版本,在 Xcode 项目中指定。

title:下载和安装过程中显示的应用程序的名称。

以下栏仅为“报刊杂志”应用程序的必填项:

newsstand-image:完整大小的 PNG 图像,显示在“报刊杂志”书架上。

UINewsstandBindingEdge and UINewsstandBindingType:这些键必须与“报刊杂志”应用程序 info.plist 中的键相符。

UINewsstandApp:表明相应的应用程序是“报刊杂志”应用程序。

示例清单文件中描述了您可以使用的一些可选键。例如,如果应用程序文件太大,并且想要在执行错误检验(TCP 通信通常会执行该检验)的基础上确保下载的完整性,可以使用 MD5 键。

通过指定项目数组的附加成员,您可以使用一个清单文件安装多个应用程序。

此附录末尾包含一个示例清单文件。

构建网站
将这些项目上传到网站上可供已认证的用户访问的区域:

应用程序 (.ipa) 文件

清单 (.plist) 文件

您的网站可以是链接到清单文件的单个页面。当用户轻按网站链接时,会下载清单文件,并触发下载和安装它所描述的应用程序。

以下是示例链接:


<a href="itms-services://?action=download-manifest&url=http://example.com/manifest.plist">Install App</a>

请勿添加归档应用程序 (.ipa) 的网站链接。载入清单文件时,设备会下载该 .ipa 文件。虽然 URL 的协议部分是 itms-services,但 iTunes Store 并不参与此过程。

此外,请确定 .ipa 文件可通过 HTTPS 进行访问,并且您的站点已使用 iOS 信任的证书进行了签名。如果自签名证书没有受信任的锚点并且无法由 iOS 设备验证,安装会失败。

设定服务器 MIME 类型
您可能需要配置 Web 服务器,让清单文件和应用程序文件可正确传输。

对于 OS X Server,请将以下 MIME 类型添加到 Web 服务的“MIME 类型”设置:

application/octet-stream ipa

text/xml plist

对于 IIS,请使用 IIS Manager 在服务器的“属性”页面中添加 MIME 类型:

.ipa application/octet-stream

.plist text/xml

无线应用程序分发故障诊断
如果无线应用程序分发失败,并显示“无法下载”信息:

请确定应用程序已正确进行签名。测试方法是使用 Apple Configurator 将它安装到设备上,然后查看是否发生错误。

请确定清单文件的链接是否正确,清单文件是否可供网络用户访问。

请确定 .ipa 文件(在清单文件中)的 URL 是否正确,并且该 .ipa 文件是否可供网络用户通过 HTTPS 访问。

网络配置要求
如果设备连接到封闭式内部网络,您应该允许 iOS 设备访问以下站点:

ax.init.itunes.apple.com:使用蜂窝移动网络下载应用程序时,设备会限制其当前文件大小。如果无法访问此站点,安装可能会失败。

ocsp.apple.com:设备会联系此网站,检查用来给预置描述文件签名的分发证书状态。

提供更新的应用程序
您自己分发的应用程序不会自动更新。有新版本可供用户安装时,应通知他们进行更新并指导他们安装应用程序。请考虑让应用程序检查更新,并在打开应用程序时通知用户。如果使用的是无线应用程序分发,您可以在通知中提供更新版应用程序的清单文件链接。

如果想要用户保留他们设备上储存的应用程序数据,请确保新版本与要替换的版本使用的捆绑标识符相同,并告知用户在安装新版本之前不要删除旧版本。如果捆绑标识符匹配,新版本会替换旧版本并保留设备上储存的数据。

分发预置描述文件自签发之日起 12 个月后过期。过期后,系统会删除描述文件,应用程序将不会启动。

预置描述文件过期之前,请前往 iOS Development Portal(iOS 开发门户)网站为应用程序创建新描述文件。对于首次安装应用程序的用户,请使用新预置描述文件创建新应用程序归档 (.ipa)。

如果用户已有该应用程序,您需要设定发布下一个版本的时间,并在该版本中包括新预置描述文件。如果不想这样做,您可以仅分发新的 .mobileprovision 文件,这样用户便不必再次安装该应用程序。新的预置描述文件会覆盖应用程序归档中已有的描述文件。

您可以使用 MDM 安装和管理预置描述文件,然后用户通过应用程序更新或使用 MDM 进行下载并安装。

如果分发证书过期,应用程序将不会启动。分发证书自签发之日起三年内有效,或者在您的企业开发者计划成员资格过期之前一直有效,二者以先到者为准。若要防止证书过期,请确保在成员资格过期之前先进行续订。

两个证书可同时处于活跃状态,并且彼此独立。第二个证书提供了一个重叠期,让您能够在第一个证书过期前更新应用程序。从 iOS Dev Center 请求第二个分发证书时,请确保不要撤销第一个证书。

证书验证
用户首次打开应用程序时,系统会通过联系 Apple 的 OCSP 服务器来验证分发证书。如果证书已撤销,应用程序将不会启动。如不能联系 OCSP 服务器,或不能从 OCSP 服务器获得响应,这种情况不会视为撤销。为了验证状态,设备必须能够访问 ocsp.apple.com。请参阅“网络配置要求”。

OCSP 响应会在设备上缓存一段时间(由 OCSP 服务器指定),当前为 3 到 7 天之间。在重新启动设备和缓存的响应过期之前,将不会再次检查证书的有效性。如果当时收到撤销命令,系统将阻止应用程序运行。

撤销分发证书会导致使用该证书签名的所有应用程序失效。只有万不得已时才应撤销证书,比如确定专用密钥已丢失或确信证书已遭破解。

示例应用程序清单文件


<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <!-- array of downloads.-->
  <key>items</key>
  <array>
   <dict>
    <!-- an array of assets to download -->
     <key>assets</key>
      <array>
       <!-- software-package: the ipa to install.-->
        <dict>
         <!-- required. the asset kind.-->
          <key>kind</key>
          <string>software-package</string>
          <!-- optional. md5 every n bytes. will restart a chunk if md5 fails.-->
          <key>md5-size</key>
          <integer>10485760</integer>
          <!-- optional. array of md5 hashes for each "md5-size" sized chunk.-->
          <key>md5s</key>
          <array>
            <string>41fa64bb7a7cae5a46bfb45821ac8bba</string>
            <string>51fa64bb7a7cae5a46bfb45821ac8bba</string>
          </array>
          <!-- required. the URL of the file to download.-->
          <key>url</key>
          <string>https://www.example.com/apps/foo.ipa</string>
        </dict>
        <!-- display-image: the icon to display during download.-->
        <dict>
         <key>kind</key>
         <string>display-image</string>
         <!-- optional. indicates if icon needs shine effect applied.-->
         <key>needs-shine</key>
         <true/>
         <key>url</key>
         <string>http://www.example.com/image.57x57.png</string>
        </dict>
        <!-- full-size-image: the large 512x512 icon used by iTunes.-->
        <dict>
         <key>kind</key>
         <string>full-size-image</string>
         <!-- optional. one md5 hash for the entire file.-->
         <key>md5</key>
         <string>61fa64bb7a7cae5a46bfb45821ac8bba</string>
         <key>needs-shine</key>
         <true/>
         <key>url</key><string>http://www.example.com/image.512x512.jpg</string>
        </dict>
      </array><key>metadata</key>
      <dict>
       <!-- required -->
       <key>bundle-identifier</key>
       <string>com.example.fooapp</string>
       <!-- optional (software only) -->
       <key>bundle-version</key>
       <string>1.0</string>
       <!-- required. the download kind.-->
       <key>kind</key>
       <string>software</string>
       <!-- optional. displayed during download; typically company name -->
       <key>subtitle</key>
       <string>Apple</string>
       <!-- required. the title to display during the download.-->
       <key>title</key>
       <string>Example Corporate App</string>
      </dict>
    </dict>
  </array>
</dict>
</plist>

有关描述文件键和属性的更多信息,请参阅 iOS Developer Library(iOS 开发者资源库)网站上的《Configuration Profile Key Reference》(配置描述文件键参考)。

2.启用web服务器(我用的苹果自带的apache Server version: Apache/2.2.26 (Unix)
Server built: Dec 10 2013 22:09:38)的https功能

以下内容摘自:http://www.cnblogs.com/tonykan/p/3508139.html

x509证书链
x509证书一般会用到三类文件,key,csr,crt。
Key 是私用密钥,openssl格式,通常是rsa算法。
csr是证书请求文件,用于申请证书。在制作csr文件的时候,必须使用自己的私钥来签署申请,还可以设定一个密钥。
crt是CA认证后的证书文件(windows下面的csr,其实是crt),签署人用自己的key给你签署的凭证。

1. key的生成

openssl genrsa -des3 -out server.key 2048

这样是生成rsa私钥,des3算法,openssl格式,2048位强度。server.key是密钥文件名。为了生成这样的密钥,需要一个至少四位的密码。可以通过以下方法生成没有密码的key:

    openssl rsa -in server.key -out server.key

server.key就是没有密码的版本了。(好像不行,还是要输入密码)

2. 生成CA的crt

openssl req -new -x509 -key server.key -out ca.crt -days 3650

生成的ca.crt文件是用来签署下面的server.csr文件。

3. csr的生成方法:

openssl req -new -key server.key -out server.csr

需要依次输入国家,地区,组织,email。最重要的是,有一个common name,可以写你的名字或者域名。如果为了https申请,这个必须和域名吻合,否则会引发浏览器警报。生成的csr文件交给CA签名后形成服务端自己的证书。

4. crt生成方法
CSR文件必须有CA的签名才可形成证书.可将此文件发送到verisign等地方由它验证,要交一大笔钱,何不自己做CA呢.

openssl x509 -req -days 3650 -in server.csr -CA ca.crt -CAkey server.key -CAcreateserial -out server.crt

输入key的密钥后,完成证书生成。-CA选项指明用于被签名的csr证书,-CAkey选项指明用于签名的密钥。-CAserial指明序列号文件,而-CAcreateserial指明文件不存在时自动生成。
最后生成了私用密钥:server.key和自己认证的SSL证书:server.crt

修改httpd.conf文件

注意修改的地方主要有:
打开这一行:
Include /private/etc/apache2/extra/httpd-ssl.conf

修改/private/etc/apache2/extra/httpd-ssl.conf文件里,设置证书文件地址的参数:

# Server Certificate:
# Point SSLCertificateFile at a PEM encoded certificate. If
# the certificate is encrypted, then you will be prompted for a
# pass phrase. Note that a kill -HUP will prompt again. Keep
# in mind that if you have both an RSA and a DSA certificate you
# can configure both in parallel (to also allow the use of DSA
# ciphers, etc.)
# Some ECC cipher suites (http://www.ietf.org/rfc/rfc4492.txt)
# require an ECC certificate which can also be configured in
# parallel.
SSLCertificateFile “/private/etc/apache2/server.crt”
#SSLCertificateFile “/private/etc/apache2/server-dsa.crt”
#SSLCertificateFile “/private/etc/apache2/server-ecc.crt”

# Server Private Key:
# If the key is not combined with the certificate, use this
# directive to point at the key file. Keep in mind that if
# you’ve both a RSA and a DSA private key you can configure
# both in parallel (to also allow the use of DSA ciphers, etc.)
# ECC keys, when in use, can also be configured in parallel
SSLCertificateKeyFile “/private/etc/apache2/server.key”
#SSLCertificateKeyFile “/private/etc/apache2/server-dsa.key”
#SSLCertificateKeyFile “/private/etc/apache2/server-ecc.key”

我就没修改httpd-ssl.conf里的设置,直接把server.cert server.key放到对应的目录 /private/etc/apache2/ 下

3.在网站目录下 新建xxx.html文件,作为下载落地页

html内容可以很简单:

Install App

把url=http://example.com/manifest.plist 这个参数换成我的服务器对应的url如:https://amadman.org/manifest.plist。
要注意manifest.plist里 所有的url都要使用https协议


url
https://amadman.org/apps/foo.ipa

下面的图片url也用https
(这里有个巨坑,图片是必填项,而且url指向的图片必须存在,否则都会报错,说无法下载,被自己坑了一天)

4.将ca.cert分发给用户

我是通过email途径发送的,可以将ca.cert放在网站目录,客户端可以通过访问https://amadman.org/ca.cert下载

XCode Image Assets Slicing

Apple Doc:

Specifying a Resizable Area of an Image

Use the Xcode Slicing feature to specify the dimensions of a resizable center area of the image and to optionally specify end caps, which are areas of the image that should not be filled by the resizable area.

bullet

  1. Select an asset catalog to display its contents.

  2. In the set list, select the set containing the image to slice.

  3. In the set viewer, select the image representation to slice, and choose Editor > Show Slicing.

    ../Art/XC_AC_H_slicing_start__2x.png
  4. Click the Start Slicing button that is displayed over the center of the image.

  5. Click the appropriate button for the slicing operation you want to perform—horizontal, vertical, or both horizontal and vertical.

    Use the Zoom In and Zoom Out buttons to increase or decrease the magnification of the image.

    ../Art/XC_AC_H_slicing_types_2x.png
  6. Drag the inner slicing handle to specify a resizable center area.

    In the horizontal slicing example shown below, the resizable area is the 2-pixel-wide sliver specified between the left slicing handle and the inner slicing handle. At runtime, the resizable area replaces the opaque area of the image.

    ../Art/XC_AC_H_slicing_resizeable_area_2x.png
  7. Drag the outer slicing handles to adjust the size of the end caps.

  8. Use the Attributes inspector to fine-tune the size of the areas and to specify whether the resizable center area should stretch or tile.

To improve app performance, you can use resizable images for the background of many UI elements, including buttons, tab bars, and popovers. For example, you can create a resizable image that includes four end caps to define the four corners of a button. When the image is resized to fill the button’s background area, the portions defined by the end caps are drawn unchanged.

Slicing is available only for projects with a target destination greater than iOS 7 or OS X 10.10.

坑:
在设置了slicing之后不起作用,后来才发现 deployment target 必须设置为 iOS7 或以上才起作用。
http://stackoverflow.com/questions/21791759/xcode-images-assets-asset-catalog-slicing-been-ignored-and-images-still-distored