赞
踩
https://devforums.apple.com/thread/239351
https://devforums.apple.com/message/1063293#1063293
NSLog(@"设备ID:%@",[[UIDevice currentDevice] uniqueIdentifier]);
中国区苹果开发者客服电话:4006701855
Android:http://www.androiddevtools.cn/
http://blog.csdn.net/andy1219111/article/details/22716315
为了提高网站的安全性,一般会在比较敏感的部分页面采用https传输,比如注册、登录、控制台等。像Gmail、网银等全部采用https传输。
https/ssl 主要起到两个作用:网站认证、内容加密传输和数据一致性。经CA签发的证书才起到认证可信的作用,所有有效证书均可以起到加密传输的作用。
浏览器与SSL证书
上图是IE和Chrome上对https的不同表现。
Chrome 网站安全性指示器说明:http://support.google.com/chrome/bin/answer.py?hl=zh&answer=95617
SSL最主要应用是在浏览器和Web服务器之间,尽管不限于此。当然,安全本身是重要的内在属性。但在表面上看,部署SSL 就是为了让用户浏览器里看起来更安全一些,以增加用户的信任感。所以很多企业更把它当作门面,而签发机构也为此卖高价,尤其是国内的价格明显高于国外的。
实际上SSL证书也可以做客户端认证,用户拥有自己特有的证书,用它可以证明自己的身份,当然也就用不着用户名和密码了。但这种用的很少,一般web服务器也不支持。
内容加密传输更安全,如果只是为了加密,使用自签发的证书也可以,但浏览器无法验证证书,所以会给出一个非常吓人的警告,所以自签发证书不适合给外人使用,只适合内部使用,把这个证书 加入到自己的信任列表或忽略证书验证即可,以后就不会继续拦截了。
证书需要被少数一级或二级 CA 认证才有效。计算机安全中的信任就是一个信任链的关系,信任链最顶端的被称为根证书。
自签发的证书在技术上是完全一样的,仅用于加密传输是没问题的。但是不能被外人信任,所以一般仅用于内部使用。除了自签发不被信任,如果证书过期、已被吊销或者非证书所代表的域名也都是不被信任的,导致证书验证出错。
用于网站的证书需要被大众信任,所以不能自签发的证书,那就申请(购买)一个吧。
申请证书
1.证书类别
按证书包含域名数量分为:
注意:SSL所说的单个域名是一个完整的域名,一个子域名就算一个,而非一个顶级域名。
如果网站有很多子域名,只需要申请真正需要的域名证书。
按验证的类别分:
个人或小站点可用一类或二类,企业一般用二类认证,少数企业会用到EV认证。
2. 证书价格
看了看网上SSL证书的价格,便宜的一般都是10美元左右一个子域名/每年,按不同类别、不同品牌等价格在几十美元到几百美元一年。比如能显示绿色地址栏的EV证书和通配符证书贵一些。国内自己的或代理的,比国外贵不少,动辄几千元。其实就是由可信源认证了一下,类似于办证,用起来没什么差别,并非越贵越好。
3. 签发机构(“卖家”)
国外常见的SSL提供商有:Thawte,Go Daddy,VeriSign,RapidSSL,GeoTrust(QuickSSL),StartSSL,Comodo。
StartSSL、Go Daddy的比较便宜,GeoTrust、Comodo的价格适中,Thawte和VeriSign的价格较贵。
VeriSign现在归属赛门铁克,在国内是由天威诚信代理的。世界真小,天威诚信就在我很多年以前的东家(启明星辰)大楼里,地下一层是他们的机房,我还进去过一次。
4. 免费的StartSSL
唯一免费的是StartSSL,其它的一般只提供30免费试用。
但 StartSSL 提供的免费证书是一类的、仅对域名和email进行验证,不对组织做验证(也就是面向自然人的,非面向组织机构的),不过
仅作为域名验证和数据加密也够了,并且浏览器也认它,一般人也不会去看你的证书级别。适合个人和初创网站使用,以后有钱了再申请个收费的替换即可。
我很顺利地申请到了免费的StartSSL证书,分别用在两个子域上。
最后,证书签发给你后,最主要是保护好私钥证书,这个丢失或泄漏就完了。因为如果被别人利用也就毫无安全性了,需要向证书签发机构申请撤销证书并申请新的证书,这当然也是要收费的。
应用规划、配置和调整
并不是说有了SSL证书就没事了,还要考虑应用中的使用问题,需要规划、服务器配置、应用调整等多个环节。
SSL比 http 要消耗更多cpu资源(主要是在建立连接的阶段,之后还要对内容加密),所以对一般网站,只需要对部分地方采用https,大部分开放内容是没必要的,具体取决于你的业务要求。比如对于很多安全要求较低的网站,完全不用https也是可接受的。
某些页面是同时支持 http 和 https ,还是只支持 https、强制 https?
同时支持就是用户用什么协议访问都可以,那么用户的请求主要就是由页面本身的链接引导来的,因为一般用户不会自己特意去修改地址栏的。
一般我们的网站可以做成同时支持http和https,都可以访问。但是这就容易有后面说的混合内容或混合脚本的问题。
还可以规划为部分页面支持 https,一般公开页面不用https,只是将部分地方的链接改为 https 就可以了。专门期望以 https 访问的页面中,引用的绝对URL可以明确的使用 https链接。
是否强制 https ?对于安全性高的网站或网站中的部分页面,可以强制使用https访问, 即使用户在地址栏里手工把 https 改为 http, 也会被自动重定向回 https 上。比如可以通过配置web服务器 rewrite 规则将这些 http url 自动重定向到对应的 https url 上(这样维护比较简单),而不用改应用。
解决混合内容问题(http和https)
混合内容是指:在https的页面中混合了非https的资源请求,比如图片、css、js 等等。如果是混合了非 https 的 js 代码,则被称为混合脚本。
混合内容的危害:如果只是混合了不安全的图片和css,那么受中间人攻击篡改,一般只会影响页面的显示,危害相对小一点。如果是混合了不安全的 js 代码,则这个不安全的 js 可以完全访问和修改页面中的任何内容,这是非常危险的。
另请参看,Chrome对混合脚本危害的说明与提示:Trying to end mixed scripting vulnerabilities
所以,只有页面本身和所有引用的资源都是 https 的浏览器才认为是安全的,只要其中引用了非安全资源(即使图片),浏览器都会给出不安全的提示,特别是有 js 的情况。如果浏览器提示不安全,那样我们就达不到原来目的了。我们费了半天功夫去申请 SSL 证书,配置Web服务器,最后如果因为混合内容而前功尽弃就太糟了。咱继续努力吧,想办法让所有引用资源都是安全的。
理论上,混合了第三方的内容,即使是SSL的第三方内容也不是很好。因为用户信任的是你,而不是第三方,即使第三方也支持https,但你能保证第三方就绝对安全吗。不引用任何第三方才是绝对安全的,但这样太严格了,安全其实也是一个 tradeoff 的问题,需要考虑很多方面的平衡。还好,起码现在浏览器认为已经是安全的了。
引用第三方文件的问题(如 CDN 分发的文件)
简单地说,这个问题要么有第三方提供 https 支持,要么不用它(用自己本地的)。
一般我们会引用由 CDN 分发的文件,比如某个 js 库文件,而不用访问自己网站上的,这样借助 CDN 网络可以加快速度,这当然很好。
但是,如果我们在页面中使用绝对 URL 直接引用这个文件就无法自动使用 https 了!出现了混合协议内容,浏览器又该“变脸”了。
当SSL 遇上CDN 或 其它第三方文件就有点麻烦,因为很多CDN还不支持SSL。如果支持 https 的话就可以直接用 https 的绝对URL了,即使是同时支持http 和 https 的页面,这样做也不算太浪费,起码解决了问题。
因为CDN的云文件提供者,一般为每个cdn用户创建一个单独的子域名来使用,这样的话,CDN提供者要想支持 https 就必须支持所有可能的子域名,因此要求CDN提供方使用那种通配符子域名的证书。
相对 URL、绝对 URL 与 只缺协议的URL(Protocol Relative URL)
相对路径比较简单,自动匹配用户请求的 http 或 https 协议。
但是绝对 url 则不成,因为绝对 url 已经明确地写上了协议: http://www.example.com/jquery.js 。
这个问题还有一个办法解决,你一定没见过这种形式: //www.example.com/jquery.js
哈哈,一个缺少协议的URL(实际上还算是相对URL),这种形式可以在浏览器中被正确补充上合适的协议!很多人都用这种方法。
但是,这里有点小问题,IE7 和 IE8 处理这种缺少协议的URL的css 文件时,同一个css文件会下载两次,详见Steve的文章 。
JS 自动判断当前协议
现在我们经常用 js 来加载其它 js 文件或 其它别的文件,如果是请求是相对URL则没问题,如果是绝对URL怎么办?
其实 js 脚本可以这样:document.location.protocol 等于 'http:' 还是 'https:' 来判断。例如在 Google Analytics 的嵌入代码中:
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
应用程序中如何判断访问协议
对于动态页面,如 jsp、php等,也是可以动态判断当前是否使用了 https 协议的。所以应用可以根据动态判断,来生成不同的引用 URL。这样虽然有点麻烦,但也算是解决了自动识别协议的问题,当然相对路径总是不需要处理的。
比如在 jsp 中:
注意,如果 tomcat 部署在其它web服务器代理的后面,需要正确配置好才能返回正确结果,见本文最后一部分。
同源策略的问题
最后提醒一点:http 和 https是不同源的!即使后面的内容都一样。所以 ajax 发请求的时候要使用正确协议的绝对URL才行。
相对URL的 ajax 请求没关系。
Nginx 配置
小结一下 Nginx 配置SSL注意的问题,详细安装配置内容请参考其它资料,如官方 SSL模块 和 https配置文档。
1. 首先检查一下是否已安装了 SSL模块,因为默认是不包含的。
用 nginx -V 命令检查一下。如果没有ssl模块则需要重新安装(建议升级到最新版本),注意安装时加上ssl 选项:
./configure --with-http_ssl_module
另外,nginx需要依赖 openssl 提供ssl支持,这个也要有。
2. nginx.conf 中的典型配置示例
listen 80;
listen 443 ssl;
ssl_certificate cert.pem; #修改具体文件
ssl_certificate_key ssl.key; #修改具体文件
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_protocols SSLv2 SSLv3 TLSv1;
ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
ssl_prefer_server_ciphers on;
上面第2-4项是关键。这些配置放在 server 块就可以对其中的所有 location 生效了,并且同时支持 http 和 https 。或者把 http 和 https 分开配置也很常见。
3. 合并证书配置文件
和Apache配置不同,Nginx需要将服务器证书和ca证书链合并到一个文件中,作为 ssl_certificate 配置的内容。
例如,按照证书链从下向上的顺序,我有三个证书:
把它们的内容按顺序连接到的一个文件中,每个内容另起一行,中间没有空行或空格。
4. 避免启动时输入密码
配好之后,启动nginx 要你输入密钥的密码。这是因为 ssl_certificate_key 配置对应的文件(也就是 startssl 给你的私钥文件)内容是加密的,需要输入你创建这个时设置的密码才能解密。这样私钥虽然很安全,但是每次重启服务都要输入一次密码也太麻烦了。其实,只要证书改为解密了的内容,就可以避免每次输入密码。用如下命令即可:
openssl rsa -in ssl.key -out newssl.key 输入密码,就生成了解密后的私钥内容,使用这个就OK了。
但是就像前面说的,一定要在服务器上保护好它,例如:
chmod 400 ssl.key (仅root可读)
5. 优化SSL配置
SSL 很消耗 CPU 资源,尤其是在建立连接的握手阶段。一是通过开启 keepalive 可以重用连接。二是可以重用和共享ssl session,见上面ssl_session相关配置。
独立Tomcat+SSL
Tomcat 是很常见的 Java应用服务器,当然也可以作为独立的 Web服务器,所有用户请求直接访问 tomcat。
如果 Tomcat 作为独立的Web服务器,那么就需要配置Tomcat就可以了,文档参考这里 和 这个。主要是配置存放证书的 Keystore 和 连接器Connector。
Java的keystore
keystore 是 Java 中专用并内置的一个类似于 openssl 的工具,一个 keystore 文件就是一个“保险箱”(database),专门存放证书和密钥,和相关的管理功能:生成自签发的证书、密钥、导入导出等。可以通过 keytool 命令或 Java api 交互。
利用keytool 命令将你的证书导入进去。
Tomcat中Connector
tomcat中有三种 Connector 实现:block、nio 和 APR。前两者使用Java SSL(这需要 keystore 的配置 ),APR使用OpenSSL(不需要用keystore,直接指定证书),配置略有不同。
Nginx+Tomcat+SSL
实际上,大规模的网站都有很多台Web服务器和应用服务器组成,用户的请求可能是经由 Varnish、HAProxy、Nginx之后才到应用服务器,中间有好几层。而中小规模的典型部署常见的是 Nginx+Tomcat 这种两层配置,而Tomcat 会多于一台,Nginx 作为静态文件处理和负载均衡。
如果Nginx作为前端代理的话,则Tomcat根本不需要自己处理 https,全是Nginx处理的。用户首先和Nginx建立连接,完成SSL握手,而后Nginx 作为代理以 http 协议将请求转给 tomcat 处理,Nginx再把 tomcat 的输出通过SSL 加密发回给用户,这中间是透明的,Tomcat只是在处理 http 请求而已。因此,这种情况下不需要配置 Tomcat 的SSL,只需要配置 Nginx 的SSL 和 Proxy。
在代理模式下,Tomcat 如何识别用户的直接请求(URL、IP、https还是http )?
在透明代理下,如果不做任何配置Tomcat 认为所有的请求都是 Nginx 发出来的,这样会导致如下的错误结果:
如果程序中把这些当实际用户请求做处理就有问题了。解决方法很简单,只需要分别配置一下 Nginx 和 Tomcat 就好了,而不用改程序。
配置 Nginx 的转发选项:
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
配置Tomcat server.xml 的 Engine 模块下配置一个 Value:
<Valve className="org.apache.catalina.valves.RemoteIpValve" remoteIpHeader="X-Forwarded-For"
protocolHeader="X-Forwarded-Proto" protocolHeaderHttpsValue="https"/>
配置双方的 X-Forwarded-Proto 就是为了正确地识别实际用户发出的协议是 http 还是 https。X-Forwarded-For 是为了获得实际用户的 IP。
这样以上5项测试就都变为正确的结果了,就像用户在直接访问 Tomcat 一样。
UIGraphicsBeginImageContext创建一个基于位图的上下文(context),并将其设置为当前上下文(context)。方法声明如下
void UIGraphicsBeginImageContext(CGSize size);
size为新创建的位图上下文的大小。它同时是由UIGraphicsGetImageFromCurrentImageContext函数返回的图形大小。
该函数的功能同UIGraphicsBeginImageContextWithOptions的功能相同,相当与UIGraphicsBeginImageContextWithOptions的opaque参数为NO,scale因子为1.0。
UIGraphicsBeginImageContextWithOptions
函数原型为:
void UIGraphicsBeginImageContextWithOptions(CGSize size, BOOL opaque, CGFloat scale);
size——同UIGraphicsBeginImageContext
opaque—透明开关,如果图形完全不用透明,设置为YES以优化位图的存储。
scale—–缩放因子
UIImageC处理
1、等比缩放
C代码 - (UIImage *) scaleImage:(UIImage *)image toScale:(float)scaleSize {
2、自定义大小
C代码
3、处理某个特定的view
只要是继承UIView的object 都可以处理
必须先import QuzrtzCore.framework
C代码
4、存储图片
4.1、存储到app的文件里
把要处理的图片以image.png的名字存储到app home地下的Document目录中
C代码
4.2、存储到手机的图片库中
C代码
获取当前app的名称和版本号
C代码
UILabel根据text自动调整大小
C代码
直接拨打有分机号的电话
C代码
一些有关图像处理的代码片段
- (UIImage *)rescaleImage:(UIImage *)img ToSize:(CGSize)size; //图片缩放裁剪
- (UIImage*)transformWidth:(CGFloat)width height:(CGFloat)height; //改变大小
+ (UIImage *)addImage:(UIImage *)image1 toImage:(UIImage *)image2; //合并图片
+ (UIImage *)imageFromImage:(UIImage *)image inRect:(CGRect)rect; //裁剪部分图片
+ (void)imageSavedToPhotosAlbum:(UIImage *)image
didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo; //保存图片到媒体库
零)重新设置图片的尺寸
- (UIImage *)rescaleImage:(UIImage *)img ToSize:(CGSize)size {
CGRect rect = CGRectMake(0.0, 0.0, size.width, size.height);
UIGraphicsBeginImageContext(rect.size);
[img drawInRect:rect]; // scales image to rect
UIImage *resImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return resImage;
}
-)根据给定得图片,从其指定区域截取一张新得图片
-(UIImage *)getImageFromImage{
//大图bigImage
//定义myImageRect,截图的区域
CGRect myImageRect = CGRectMake(10.0, 10.0, 57.0, 57.0);
UIImage* bigImage= [UIImage imageNamed:@"k00030.jpg"];
CGImageRef imageRef = bigImage.CGImage;
CGImageRef subImageRef = CGImageCreateWithImageInRect(imageRef, myImageRect);
CGSize size;
size.width = 57.0;
size.height = 57.0;
UIGraphicsBeginImageContext(size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextDrawImage(context, myImageRect, subImageRef);
UIImage* smallImage = [UIImage imageWithCGImage:subImageRef];
UIGraphicsEndImageContext();
return smallImage;
}
二) 合并两张图片
- (UIImage *)addImage:(UIImage *)image1 toImage:(UIImage *)image2 {
UIGraphicsBeginImageContext(image1.size);
// Draw image1
[image1 drawInRect:CGRectMake(0, 0, image1.size.width, image1.size.height)];
// Draw image2
[image2 drawInRect:CGRectMake(0, 0, image2.size.width, image2.size.height)];
UIImage *resultingImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return resultingImage;
}
三) 捕捉屏幕截图
CALayer实例使用Core Graphics的renderInContext方法可以将视图绘制到图像上下文中以便转化为其他UIImage实例。前提先#import
+ (UIImage *) imageFromView: (UIView *)theView { // draw a view's contents into an image context UIGraphicsBeginImageContext(theView.frame.size); CGContextRef context = UIGraphicsGetCurrentContext(); [theView.layer renderInContext:context]; UIImage *theImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return theImage; }
注:UIGraphicsBeginImageContext(CGSize size)创建一个基于位图的上下文(context),并将其设置为当前上下文。函数功能与UIGraphicsBeginImageContextWithOptions相同,相当于该方法的opaque参数为NO,scale因子为1.0。而UIGraphicsEndImageContext()方法是移除栈顶的基于当前位图的图形上下文。
视图添加倒影效果
const CGFloat kReflectPercent = -0.25f; const CGFloat kReflectOpacity = 0.3f; const CGFloat kReflectDistance = 10.0f; + (void)addSimpleReflectionToView:(UIView *)theView { CALayer *reflectionLayer = [CALayer layer]; reflectionLayer.contents = [theView layer].contents; reflectionLayer.opacity = kReflectOpacity; reflectionLayer.frame = CGRectMake(0.0f,0.0f,theView.frame.size.width,theView.frame.size.height*kReflectPercent); //倒影层框架设置,其中高度是原视图的百分比 CATransform3D stransform = CATransform3DMakeScale(1.0f,-1.0f,1.0f); CATransform3D transform = CATransform3DTranslate(stransform,0.0f,-(kReflectDistance + theView.frame.size.height),0.0f); reflectionLayer.transform = transform; reflectionLayer.sublayerTransform = reflectionLayer.transform; [[theView layer] addSublayer:reflectionLayer]; }
另一:使用Core Graphics创建倒影
+ (CGImageRef) createGradientImage:(CGSize)size { CGFloat colors[] = {0.0,1.0,1.0,1.0}; //在灰色设备色彩上建立一渐变 CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray(); CGContextRef context = CGBitmapContextCreate(nil,size.width,size.height,8,0,colorSpace,kCGImageAlphaNone); CGGradientRef gradient = CGGradientCreateWithColorComponents(colorSpace,colors,NULL,2); CGColorSpaceRelease(colorSpace); //绘制线性渐变 CGPoint p1 = CGPointZero; CGPoint p2 = CGPointMake(0,size.height); CGContextDrawLinearGradient(context,gradient,p1,p2,kCGGradientDrawsAfterEndLocation); //Return the CGImage CGImageRef theCGImage = CGBitmapContextCreateImage(context); CFRelease(gradient); CGContextRelease(context); return theCGImage; }
//Create a shrunken frame for the reflection
+ (UIImage *) reflectionOfView:(UIView *)theView WithPercent:(CGFloat) percent { //Retain the width but shrink the height CGSize size = CGSizeMake(theView.frame.size.width, theView.frame.size.height * percent); //Shrink the View UIGraphicsBeginImageContext(size); CGContextRef context = UIGraphicsGetCurrentContext(); [theView.layer renderInContext:context]; UIImage *partialimg = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); //build the mask CGImageRef mask = [ImageHelper createGradientImage:size]; CGImageRef ref = CGImageCreateWithMask(partialimg.CGImage,mask); UIImage *theImage = [UIImage imageWithCGImage:ref]; CGImageRelease(ref); CGImageRelease(mask); return theImage; } const CGFloat kReflectDistance = 10.0f; + (void) addReflectionToView: (UIView *)theView { theView.clipsToBounds = NO; UIImageView *reflection = [[UIImageView alloc] initWithImage:[ImageHelper reflectionOfView:theView withPercent:0.45f]]; CGRect frame = reflection.frame; frame.origin = CGPointMake(0.0f, theView.frame.size.height + kReflectDistance); reflection.frame = frame; // add the reflection as a simple subview [theView addSubView:reflection]; [reflection release]; }
关于图片缩放的线程安全和非线程安全操作.
非线程安全的操作只能在主线程中进行操作,对于大图片的处理肯定会消耗大量的时间,如下面的方法
方法 1: 使用 UIKit
+ (UIImage*)imageWithImage INCLUDEPICTURE "http://www.61ic.com/Mobile/UploadFiles_9667/201103/20110309123315372.gif" /* MERGEFORMATINET UIImage*)image scaledToSize INCLUDEPICTURE "http://www.61ic.com/Mobile/UploadFiles_9667/201103/20110309123315372.gif" /* MERGEFORMATINET CGSize)newSize;
{
// Create a graphics image context
UIGraphicsBeginImageContext(newSize);
// Tell the old image to draw in this new context, with the desired
// new size
[image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
// Get the new image from the context
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
// End the context
UIGraphicsEndImageContext();
// Return the new image.
return newImage;
}
此方法很简单, 但是,这种方法不是线程安全的情况下.
方法 2: 使用 CoreGraphics
+ (UIImage*)imageWithImage INCLUDEPICTURE "http://www.61ic.com/Mobile/UploadFiles_9667/201103/20110309123315372.gif" /* MERGEFORMATINET UIImage*)sourceImage scaledToSize INCLUDEPICTURE "http://www.61ic.com/Mobile/UploadFiles_9667/201103/20110309123315372.gif" /* MERGEFORMATINET CGSize)newSize;
{
CGFloat targetWidth = targetSize.width;
CGFloat targetHeight = targetSize.height;
CGImageRef imageRef = [sourceImage CGImage];
CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);
CGColorSpaceRef colorSpaceInfo = CGImageGetColorSpace(imageRef);
if (bitmapInfo == kCGImageAlphaNone) {
bitmapInfo = kCGImageAlphaNoneSkipLast;
}
CGContextRef bitmap;
if (sourceImage.imageOrientation == UIImageOrientationUp ||sourceImage.imageOrientation == UIImageOrientationDown) {
bitmap = CGBitmapContextCreate(NULL, targetWidth,targetHeight,CGImageGetBitsPerComponent(imageRef),CGImageGetBytesPerRow(imageRef), colorSpaceInfo, bitmapInfo);
} else {
bitmap = CGBitmapContextCreate(NULL, targetHeight, targetWidth,CGImageGetBitsPerComponent(imageRef),CGImageGetBytesPerRow(imageRef), colorSpaceInfo, bitmapInfo);
}
if (sourceImage.imageOrientation == UIImageOrientationLeft) {
CGContextRotateCTM (bitmap, radians(90));
CGContextTranslateCTM (bitmap, 0, -targetHeight);
} else if (sourceImage.imageOrientation ==UIImageOrientationRight) {
CGContextRotateCTM (bitmap, radians(-90));
CGContextTranslateCTM (bitmap, -targetWidth, 0);
} else if (sourceImage.imageOrientation == UIImageOrientationUp) {
// NOTHING
} else if (sourceImage.imageOrientation == UIImageOrientationDown){
CGContextTranslateCTM (bitmap, targetWidth, targetHeight);
CGContextRotateCTM (bitmap, radians(-180.));
}
CGContextDrawImage(bitmap, CGRectMake(0, 0, targetWidth,targetHeight), imageRef);
CGImageRef ref = CGBitmapContextCreateImage(bitmap);
UIImage* newImage = [UIImage imageWithCGImage:ref];
CGContextRelease(bitmap);
CGImageRelease(ref);
return newImage;
}
这种方法的好处是它是线程安全,加上它负责的 (使用正确的颜色空间和位图信息,处理图像方向) 的小东西,UIKit 版本不会。
如何调整和保持长宽比 (如 AspectFill 选项)?
它是非常类似于上述,方法,它看起来像这样:
+ (UIImage*)imageWithImage INCLUDEPICTURE "http://www.61ic.com/Mobile/UploadFiles_9667/201103/20110309123315372.gif" /* MERGEFORMATINET UIImage*)sourceImage scaledToSizeWithSameAspectRatio INCLUDEPICTURE "http://www.61ic.com/Mobile/UploadFiles_9667/201103/20110309123315372.gif" /* MERGEFORMATINET CGSize)targetSize;
{
CGSize imageSize = sourceImage.size;
CGFloat width = imageSize.width;
CGFloat height = imageSize.height;
CGFloat targetWidth = targetSize.width;
CGFloat targetHeight = targetSize.height;
CGFloat scaleFactor = 0.0;
CGFloat scaledWidth = targetWidth;
CGFloat scaledHeight = targetHeight;
CGPoint thumbnailPoint = CGPointMake(0.0,0.0);
if (CGSizeEqualToSize(imageSize, targetSize) == NO) {
CGFloat widthFactor = targetWidth / width;
CGFloat heightFactor = targetHeight / height;
if (widthFactor > heightFactor) {
scaleFactor = widthFactor; // scale to fit height
}
else {
scaleFactor = heightFactor; // scale to fit width
}
scaledWidth = width * scaleFactor;
scaledHeight = height * scaleFactor;
// center the image
if (widthFactor > heightFactor) {
thumbnailPoint.y = (targetHeight - scaledHeight) * 0.5;
}
else if (widthFactor < heightFactor) {
thumbnailPoint.x = (targetWidth - scaledWidth) * 0.5;
}
}
CGImageRef imageRef = [sourceImage CGImage];
CGBitmapInfo bitmapInfo = CGImageGetBitmapInfo(imageRef);
CGColorSpaceRef colorSpaceInfo = CGImageGetColorSpace(imageRef);
if (bitmapInfo == kCGImageAlphaNone) {
bitmapInfo = kCGImageAlphaNoneSkipLast;
}
CGContextRef bitmap;
if (sourceImage.imageOrientation == UIImageOrientationUp ||sourceImage.imageOrientation == UIImageOrientationDown) {
bitmap = CGBitmapContextCreate(NULL, targetWidth, targetHeight,CGImageGetBitsPerComponent(imageRef),CGImageGetBytesPerRow(imageRef), colorSpaceInfo, bitmapInfo);
} else {
bitmap = CGBitmapContextCreate(NULL, targetHeight, targetWidth,CGImageGetBitsPerComponent(imageRef),CGImageGetBytesPerRow(imageRef), colorSpaceInfo, bitmapInfo);
}
// In the right or left cases, we need to switch scaledWidth and scaledHeight,
// and also the thumbnail point
if (sourceImage.imageOrientation == UIImageOrientationLeft) {
thumbnailPoint = CGPointMake(thumbnailPoint.y, thumbnailPoint.x);
CGFloat oldScaledWidth = scaledWidth;
scaledWidth = scaledHeight;
scaledHeight = oldScaledWidth;
CGContextRotateCTM (bitmap, radians(90));
CGContextTranslateCTM (bitmap, 0, -targetHeight);
} else if (sourceImage.imageOrientation ==UIImageOrientationRight) {
thumbnailPoint = CGPointMake(thumbnailPoint.y, thumbnailPoint.x);
CGFloat oldScaledWidth = scaledWidth;
scaledWidth = scaledHeight;
scaledHeight = oldScaledWidth;
CGContextRotateCTM (bitmap, radians(-90));
CGContextTranslateCTM (bitmap, -targetWidth, 0);
} else if (sourceImage.imageOrientation == UIImageOrientationUp) {
// NOTHING
} else if (sourceImage.imageOrientation == UIImageOrientationDown){
CGContextTranslateCTM (bitmap, targetWidth, targetHeight);
CGContextRotateCTM (bitmap, radians(-180.));
}
CGContextDrawImage(bitmap, CGRectMake(thumbnailPoint.x,thumbnailPoint.y, scaledWidth, scaledHeight), imageRef);
CGImageRef ref = CGBitmapContextCreateImage(bitmap);
UIImage* newImage = [UIImage imageWithCGImage:ref];
CGContextRelease(bitmap);
CGImageRelease(ref);
return newImage;
}
App store 2015最新审核标准公布
以下是更新后的审核指南(修改部分红色字体标出):
1.条款和条件
1.1为AppStore开发程序,开发者必须遵守ProgramLicenseAgreement(PLA)、人机交互指南(HIG)以及开发者和苹果签订的任何其他协议和合同。以下规则和例证旨在帮助开发者的程序能获得AppStore的认可,而不是修改或删除任何其他协议中的条款。
2.功能
2.1崩溃的程序将会被拒绝。
2.2存在错误的程序将会被拒绝。
2.3跟开发者宣传不符的程序将会被拒绝。
2.4无应用文档或隐藏功能与描述不符的程序将会被拒绝。
2.5使用非公开API的程序将会被拒绝。
2.6在指定容器范围外读写数据的程序将会被拒绝。
2.7以任何方式或形式下载代码的程序将会被拒绝。
2.8安装或运行其他可执行代码的程序将会被拒绝。
2.9Demo版、trial版和test版的程序将会被拒绝。Beta版应用程序可通过TestFlight提交,并且必须遵守相关指南。(此前并未允许Beta版通过TestFlight提交)
2.10iPhone程序必须不经修改就能以iPhone分辨率和2倍iPhone3GS的分辨率在iPad上运行。
2.11与AppStore已有程序重复的应用可能会被拒绝,特别是数量很多的情况下,比如手电筒应用和爱经应用。
2.12没有显著用途、不独特的应用程序或者与网站简单捆绑的应用有可能被拒;不提供任何持久娱乐价值的程序可能会被拒绝。
2.13内容主要是营销材料或广告的程序将会被拒绝。
2.14包含欺骗或虚假功能,却有没有标明的应用程序将会被拒绝。
2.15大于100MB无法通过蜂窝网络下载的应用(AppStore会自动禁止)。
2.16多任务程序使用后台服务仅限于几种目的:VoIP、音频播放、地理位置、完成任务以及本地提醒等。
2.17应用程序只允许使用iOSWebKit框架和WebKitJavascript浏览web内容。
2.18鼓励酗酒或使用违禁药物,或引诱青少年饮酒或吸烟的程序将会被拒绝。
2.19提供错误的系统诊断或不精确的设备数据的应用将会被拒绝。
2.20向AppStore上传大量相似版本程序的开发者将会从iOS开发者计划中除名。
2.21简单一首歌曲或者一部影片应用要提交到iTunesstore,书籍类应用应该提交到iBookstore。
2.22随意根据环境(如定位或者运营商)限制用户使用的应用会被拒。
2.23应用必须遵守iOS数据储存指导方针(iOSDataStorageGuidelines),否则应用将被拒。
2.24存放在Newsstand的应用必须遵守开发者项目许可协议(ProgramLicenseAgreement)的表1、表2以及表3,否则应用将会被拒。
2.25类似Appstore,或者基于购买或者促销的目的而展示其他应用的应用将会被拒绝。(限制更加严格,此前经过特殊审核批准(比如健康管理、航空以及其他无障碍需求等),或者为特殊群体用户提供具有重大意义的附加值的应用是可以通过的)
2.26只有当app是出于特殊审核需要(比如健康管理、航空以及无障碍需求等)或为特殊群体用户提供具有重大意义的附加值时,才可以展示和推荐自身以外的其他应用程序,否则应用程序将会被拒绝。
3.元数据(名称、描述、评级、排名等)近来厂商踩雷屡见不鲜,此部分请详细阅读
3.1应用或者元数据中提到其他任何移动平台将会被拒。
3.2带有占位符文本的程序将会被拒绝
3.3应用程序的名称、描述、截图或者预览与应用的内容和功能不相关将会被拒绝。(此前仅对描述有所限制)
3.4为了不混淆用户,iTunesConnect中的应用名称应该和展示在设备上的应用名称一致。
3.5不同尺寸的appicon要一致,否则会造成混淆。
3.6图标、截图以及预览不符合4+年龄评级的程序将会被拒绝。(增加了对预览的限制)
3.7目录与类型不适合于程序内容的程序将会被拒绝。
3.8开发者有责任为其程序指定适合的评级。不相称的评级可能会由苹果公司修改。
3.9开发者有责任为其程序指定恰当的关键字。不恰当的关键词可能会被苹果公司修改/删除。
3.10试图通过伪造评论或者付费评论的方式在AppStore中操纵或者其欺骗用户评论(或者采用其他不正当方式)以提升排名的开发者将会被苹果从iOS开发者计划中除名。
3.11在安装或打开应用之前,推荐用户重启iOS设备的应用将会被拒。
3.12提交审核的应用程序应包含能正常运行的URL,比如支持服务URL和隐私政策URL。
3.13应用程序的截图、预览或者营销文本没有清晰地指出附加内容或项目需要额外单独购买(比如使用IAP)将会被拒绝。
3.14App预览仅能使用从应用程序捕获的视频屏幕、旁白、文本以及designoverlays,否则应用程序将会被拒绝。
3.15添加App预览的应用程序,未经许可展示真人个人信息将会被拒绝。
3.16App预览仅能使用在所有选定地区内经过授权许可、用于此目的的音乐。
3.17App预览包含未经授权的通过app播放的内容(比如iTunesplaylist和YouTube流媒体)的应用将会被拒绝。
4.位置
4.1在收集、传输或使用位置数据之前未通知并获得用户同意的程序将会被拒绝。
4.2将基于位置的API用于车辆、飞机或其他设备的自动控制或自主控制的应用程序将会被拒绝。
4.3使用基于位置的API用于应急服务的应用程序将会被拒绝。(此处进行了描述修改,未着重指出调度和车队管理)
4.4当与提供的功能或服务密切相关,或者为支持经过授权的广告时,应用程序才可以使用位置数据。
5.推送通知
5.1不使用苹果推送通知(APN)应用接口提供推送通知的程序将会被拒绝。
5.2未从苹果获得PushApplicationID便擅自使用APN服务的程序将会被拒绝。
5.3在首次推送消息或者要求运行推送通知之前未获得用户许可的应用将会被拒绝。
5.4使用推送通知发送敏感个人信息或机密信息的程序将会被拒绝。
5.5使用推送通知发送非请求消息,或用于钓鱼或群发垃圾信息用途的程序将会被拒绝。
5.6应用程序不可使用推送通知发送广告、促销或任何类型的直销信息。
5.7应用程序不能向使用推送通知服务的用户收取费用。
5.8使用推送通知会过多利用APN服务的网络流量或带宽或给设备带来过度负担的程序将会被拒绝。
5.9如果应用程序传送病毒、文件、计算机代码或程序,并且对APN服务的正常运行造成损害或中断,那么该程序将会被拒绝。
6.游戏中心
6.1向终端用户或任意第三方显示玩家ID的程序将会被拒绝。
6.2将玩家ID用于任何未经游戏中心条款批准用途的程序将会被拒绝。
6.3试图进行反向搜索、跟踪、关联、挖掘、获得或利用玩家ID、别名或通过游戏中心获得其他信息的开发者将会iOS开发者计划除名。
6.4游戏中心信息(例如排行榜分数),只能用于游戏中心批准的应用程序中。
6.5利用游戏中心服务发送非请求信息,或用于钓鱼或群发垃圾邮件的程序将会被拒绝。
6.6过多使用游戏中心网络流量或带宽的应用程序将会被拒绝。
6.7如果程序能够传送病毒、文件、计算机代码或程序,并且对游戏中心服务的正常运行造成损害或中断,该程序将会被拒绝。
7.广告
7.1人工刷广告浏览量或者广告点击率的应用程序将会被拒绝。
7.2包含空iAd广告的应用程序将会被拒绝。
7.3主要设计目的在于显示广告的应用程序将会被拒绝。
8.商标与商品外观
8.1应用程序必须遵守”GuidelinesforUsingAppleTrademarksandCopyrights”和”AppleTrademarkList”中说明的所有条款与条件。
8.2任何误导和暗示苹果公司是该应用程序来源或提供商,或者苹果公司以任何形式表示认可其质量或功能的应用程序将会被拒绝。
8.3与目前已有苹果产品或者广告主题外观相似或混淆的应用程序将会被拒绝。
8.4在应用程序名称中将苹果产品名拼错的应用程序(例如,GPSforIphone,iTunz)将会被拒绝。
8.5应用程序不得使用受保护的第三方材料(比如商标、版权以及专利),不能违反第三方使用条款。必须提供使用这些材料的授权许可。
8.6若无明确授权许可,从第三方来源处(比如YouTube、SoundCloud以及Vimeo等)下载音乐或者视频内容的应用程序将会被拒绝。
9.媒体内容
9.1不使用媒体播放器框架(MediaPlayerFramework)获取音乐库中媒体内容的应用程序将会被拒绝。
9.2用户界面模仿任何iPod或者iTunes界面的应用程序将会被拒绝。
9.3通过蜂窝网络传输的音频流内容每5分钟不得超过5MB。
9.4通过蜂窝网络传输超过10分钟的视频流内容必须使用HTTPLiveStreaming协议,并且要包含一个基线为192kbps或者更低的HTTP实时流。
10.用户界面
10.1应用程序必须遵守苹果的《iOSHumanInterfaceGuidelines》中所有的条款和条件。
10.2外观与iPhone自带应用(比如AppStore、iTunesStore和iBookstore)相似的应用程序将会被拒绝。
10.3未能按苹果《iOSHumanInterfaceGuidelines》描述正确使用系统提供的项目(比如按钮、图标)的应用将会被拒绝。
10.4创建桌面/主屏幕环境或者模拟multi-App插件体验的应用程序将会被拒绝。
10.5修改音量大小和铃声/静音等标准开关功能的应用程序将会被拒绝。
10.6苹果和我们的客户高度推崇简单、精致、富有创造性以及经过精心设计的界面。虽然需要付出更多,但却非常值得。苹果设立了很高的门槛。如果你的用户界面太过复杂或者水准不高,可能会被拒绝。
11.购买与货币流通
11.1使用AppStore以外的渠道解锁或开启附加属性和功能的应用程序将会被拒绝。
11.2使用应用内支付系统(IAP)以外的系统购买内容、功能或服务的应用软件将会被拒绝。
11.3使用IAP购买实物商品或者用于该软件之外的商品和服务的应用软件将会被拒绝。
11.4使用IAP购买积分(信用点)或者其他货币必须在本应用中消费。
11.5使用IAP购买已过期积分或其他货币的应用软件将会被拒绝。
11.6使用IAP订阅的内容至少要持续7天,而且允许在用户的其他iOS设备间共享。
11.7使用IAP购买项目的应用程序必须指派正确的购买类型。
11.8使用IAP购买iOS内置功能(如照相机,陀螺仪)的应用程序将会被拒绝。
11.9含有超过限定时间的内容或服务的应用程序将会被拒绝,除经特定批准的内容(比如电影、电视节目音乐以及书籍)。
11.10保险类应用程序必须免费,要遵守发布地区的法律,并且不能使用IAP。
11.11一般而言,你的应用程序越贵,我们的评审会越深入。(对不起,我们国产大部分是免费网游)
11.12提供订阅功能的应用必须使用IAP,苹果将会按照DeveloperProgramLicenseAgreement中的约定与开发者按30/70比例分成。
11.13在应用内使用跳转至外部购买或订阅链接的应用将会被拒,比如”buy”按钮跳转至一个购买电子书的web页面。
11.14只要应用内没有跳转至外部购买、订阅的按钮或链接,苹果允许这些应用读取或展示经批准的、在应用外购买或订阅内容(特别是杂志、报纸、书籍、音频、音乐、视频以及云存储内容)。苹果只能通过应用程序内的购买获得一部分收益。
11.15应用程序可以只使用自动更新订阅期刊(报纸、杂志)、商业应用程序(企业类、效率类、专业创意类以及云存储类)和媒体类应用程序(视频、音频、声音),否则应用程序将被拒绝。
11.16当与特定的经过审核的实体产品(比如玩具)结合使用时,应用程序可以使用获得批准的附加特性和功能,只要附加功能完全依赖于该硬件产品(比如一款用于控制望远镜的应用程序)或者也可以在不使用实物产品的情况下使用应用程序,比如成就奖励或者使用IAP。
11.17如果应用功能遵照各州和联邦法律,那么应用可以用来促进被认可的虚拟货币的流通。
12.抓取和聚合
12.1从苹果网站(例如apple.com、iTunesStore、AppStore、iTunesConnect以及AppleDeveloperPrograms等)抓取任何信息或者使用苹果网站内容和服务进行排名的应用程序将会被拒绝。
12.2应用软件可以使用获得批准的苹果RSSfeeds,例如iTunesStoreRSSfeeds。
12.3只是简单的网页剪切、内容整合或者收集链接的应用程序可能会被拒绝。
13.损害设备
13.1怂恿用户以可能造成损害的方式使用苹果设备的应用软件将会被拒绝。
13.2快速耗光设备电量或产生过多热量的应用软件将会被拒绝。
13.3能导致用户人身伤害的app将会被拒绝。
14.人身攻击
14.1涉及诽谤、人身攻击性质以及内容狭隘卑鄙的应用软件或者打击特定个人或组织的应用软件将会被拒绝。
14.2职业政治讽刺家和幽默作家不受这一条款约束。(开门,查水表)
14.3展示用户创作内容(UGC)的应用程序必须提供一个过滤不良资讯的方法,一个用户可以标记侵犯性内容的机制,以及可以阻止辱骂用户的能力。
15.暴力(此前传禁枪的消息并未在条款中明确指出)
15.1应用程序中出现人或动物被杀、致残以及枪击、刺伤、拷打等受伤情形的真实画面将会被拒绝。
15.2出现描绘暴力或虐待儿童等内容的应用程序将会被拒绝。
15.3游戏中出现的”敌人”不可指向一个特定种族、文化、一个真实存在的政府、企业或者其他任何现实中的实体。
15.4对武器进行真实描述以怂恿非法使用或滥用这些武器的应用程序将会被拒绝。
15.5包含俄罗斯轮盘赌博内容的游戏将会被拒。
16.令人反感的内容
16.1应用程序中出现过于令人反感或者低俗的内容将会被拒绝。
16.2在设计上激怒用户或令人感到厌恶的应用程序将会被拒绝。
17.隐私
17.1在未经用户事先许可,或未告知用户如何使用信息以及在何处使用信息的情况下,应用程序不能传输用户数据。
17.要求用户共享电子邮箱地址和出生日期等私人信息才可使用其功能的应用程序将会被拒绝。
17.3仅出于遵守适用的儿童隐私法规的目的,应用程序可以要求用户的出生日期(或者使用其他年龄评级机制),但是必须包括一些有用的功能或者娱乐价值,不管用户年龄大小。
17.4收集、传输以及分享未成年用户个人信息(比如名字、地址、邮件、位置、照片、视频、绘画、聊天信息以及其他个人数据,或者与以上所述相关的永久性标示符)的应用程序必须遵守应用儿童隐私法规,并且必须包含隐私条款。
17.5包含账号注册或者访问用户现有账号的应用程序必须包含隐私策略,否则将会被拒绝。
18.色情
18.1含有色情素材,也就是《韦氏词典》中定义的”旨在激发情欲,对性器官或性行为的明确描述或展示,而无关美学或情绪感受”的程序将会被拒绝。
18.2包含用户频繁提供的色情内容的应用程序(比如以前的“ChatRoulette”程序)将会被拒绝。
19.宗教,文化与种族
19.1涉及宗教、文化或种族群体的引用或评论包含诽谤性、攻击性或狭隘内容,或会使特定群体遭受伤害或暴力的应用程序将会被拒绝。
19.2程序可以包含或引用宗教经文,程序所提供的引用或翻译必须准确且不会引起误导。评论应该有教育意义,可以令人开阔眼界,而不应有煽动性。
20.竞赛、赌博、彩票以及抽奖
20.1彩票抽奖和竞赛必须由应用程序的开发者或者app所属公司发起。
20.2应用程序必须展示彩票抽奖和竞赛的正式规则,并声明苹果不是发起者,也没有以任何方式参与活动。
20.3开发者运营一款具有抽奖性质的应用必须经过法律允许,并且抽奖应用必须具备以下特征:报酬、运气以及奖品。
20.4允许用户在应用中直接购买彩票或彩券的应用将会被拒。
20.5提供真钱游戏(比如体育、扑克牌、赌场游戏、赛马以及彩票)的应用程序必须有应用程序适用地区当地必要的许可和允许,必须限制在这些区域,必须可以从AppStore免费下载。
20.6使用IAP购买信誉或者货币,且结合真钱游戏的应用将会被拒绝。
21.慈善与援助
21.1包含可以向已认证的慈善组织捐赠功能的应用程序必须是免费的。
21.2捐赠款项的募集必须通过Safari浏览器访问web页面或是手机短消息完成。
22.法律要件
22.1应用程序必须遵守所有发布地区当地法律,开发者有义务了解并遵守所有当地法律。
22.2包含虚假,欺诈或误导性陈述的程序将会被拒绝。
22.3任何用于招徕、促进或鼓励犯罪或明显鲁莽行为的应用程序将会被拒绝。
22.4支持非法文件共享的程序将会被拒绝。
22.5被设计用以非法赌博工具的应用程序(包括点算牌)将会被拒绝。
22.6具有匿名或恶作剧拨打电话或发送类似短信/彩信功能的程序将会被拒绝。
22.7任何开发暗中收集用户密码或用户私人数据程序的开发者将会从iOS开发者计划中除名。
22.8包含非执法机构发布的DUI检查点信息,或者怂恿/协助酒后驾车的应用将会被拒绝。
22.9计算药剂用量的应用程序必须由药品制造商或者认可机构发布,比如医院、保险公司以及高校。
22.10.在未授权的情况下使用iTunes音乐预览的应用程序将会被拒绝。
23.Passbook
23.1PassbookPasses可被用来支付或者接收支付,传递商业信息或者提供验证(比如电影票、飞机票、优惠券以及其他),但把PassbookPasses用于其他用途的应用程序可能会遭到拒绝,并且会被撤销Passbook证书。
23.2Passes必须包含有效的pass发行人有效的联系资料,否则app将会被拒绝,并且Passbook证书也会被取消。
23.3Passes必须经过实体签名,并基于其名字、商标或者品牌进行分发,否则应用程序将会被拒绝,而Passbook证书也可能会被撤销。
24.儿童类别
24.1儿童类别中的应用程序必须包含隐私政策,必须遵守适用的儿童隐私法规。
24.2儿童类别中的应用程序不允许包括行为广告(比如app内部基于用户行动的服务广告),任何在应用程序中展示的上下文广告必须适合儿童。
24.3儿童类别中的应用程序必须得到家长许可或使用parentalgate才能链接至应用程序外部或进行交易。
24.4儿童类别中的应用程序必须标明”5岁以下,6-8岁或者9-11岁”。
25.扩展
25.1包含扩展的应用程序必须遵照AppExtensionProgrammingGuide要求。
25.2包含扩展的应用程序必须提供某些功能(辅助屏幕,附加设置),否则将会被拒绝。
25.3如果扩展的视图中包含营销推广、广告或者IAP内容,那么包含该扩展的应用将会被拒绝。
25.4键盘扩展必须提供一个切换至下个键盘的方法。
25.5键盘扩展必须具有离线访问功能,否则将会被拒绝。
25.6键盘扩展必须提供和AppExtensionProgrammingGuide描述一致的数字和十进键盘类型,否则将会被拒绝。
25.7提供键盘扩展的应用必须拥有基本的功能分类和隐私政策,否则将会被拒绝。
25.8提供键盘扩展的应用程序只允许收集用户活动以增强键盘扩展在iOS设备上的功能,否则将会被拒绝。
26.HomeKit
26.1使用HomeKit框架的应用程序必须有提供家庭自动化服务的主要目的。
26.2使用HomeKit框架的应用程序必须在营销文本中说明用途,同时必须提供隐私政策,否则将会被拒绝。
26.3应用程序不允许将从HomeKitAPI收集的数据用于广告宣传或者其他基于使用的数据挖掘。
26.4出于其他目的使用从HomeKitAPI收集的数据,而不是用于提高用户体验或者家庭自动化功能中硬件/软件性能,这类应用将会被拒绝。
27.HealthKit
27.1使用HealthKit或者ResearchKit框架(出于健康目的用于进行人体生物学研究的框架)的应用程序,必须遵守其所有适用区域的法律,以及iOSDeveloperProgramLicenseAgreement中的3.3.28和3.39条款。(增加了对于ResearchKit框架的支持)
27.2将虚假或者错误的数据写入HealthKit的应用程序将会被拒绝。
27.3使用HealthKit框架的应用程序在iCloud中储存用户健康信息将会被拒绝。
27.4应用程序不允许将通过HealthKitAPI收集的用户数据用作广告宣传或者基于使用的数据挖掘目的,除了改善健康、医疗、健康管理以及医学研究目的。
27.5未经用户许可与第三方分享通过HealthKitAPI获得的用户数据的应用程序将会被拒绝。
27.6使用HealthKit框架的应用程序必须在营销文本中说明集成了Healthapp,同时必须在app用户界面清楚阐释HealthKit的功能。
27.7使用HealthKit框架的应用程序必须提供隐私政策,否则将会被拒绝。
27.8提供诊断、治疗建议,或者控制诊断疾病的硬件,或者治疗疾病的应用程序,若没有根据要求提供书面的监管审批,将会被拒绝。
27.9收集人体生物学研究相关数据的应用程序必须要获得参与者的许可,对于未成年人,应用程序要得到其父母或者监护人的许可。许可内容必须包括:(a)研究的性质、目的以及持续性;(b)参与流程、风险以及受益(福利);(c)信息的机密性和数据处理(包括与任何与第三方的共享);(d)参与者问题切入点;(e)取消方法(新增)
28.TestFlight
28.1应用程序仅能使用TestFlight对以公开发布为目的的应用进行beta版测试,且必须遵守完整的AppReviewGuidelines。
28.2当版本中包含的内容或功能有重大变化时,使用TestFlight的应用程序必须提交审核。
28.3使用TestFlight的应用程序不允许分发给测试者,以作为任何形式的补偿。
29.ApplePay
29.1使用ApplePay的应用程序必须在出售任何商品或者服务之前为用户提供所有材料的购买信息,否则将会被拒绝。使用ApplePay进行定期付款的应用程序必须提供最低限度续费期限,付费将持续直至被取消,每个阶段所付款额,费用付款归属,以及如何取消等。(增加了对于定期付款的规定)
29.2使用ApplePay的应用程序必须正确使用ApplePayHumanInterfaceGuidelines中的ApplePay标识和用户界面元素,否则将会被拒绝。
29.3使用ApplePay作为购买机制的应用程序所提供的商品或服务不能触犯任何交付地范围内的法律,也不能用作任何非法目的。
29.4使用ApplePay的应用程序必须提供隐私政策,否则将会被拒绝。
29.5只有为了促进或提高商品和服务的交付,或者依照法律要件,使用ApplePay的应用程序才能与第三方分享通过ApplePay获得的数据。
苹果企业开发者账号注册申请($299的账号)
一、提供材料
法人个人资料
法人双币信用卡(信用卡类型,信用卡号,有效期,卡后三位,信用卡户名,信用卡地址)
法人联系方式(苹果会打电话给法人确认是否本人申请或者委托员工申请)
公司电话(苹果会打电话给公司确认是否在申请)
公司营业执照复印件(电子版)
公司英文名
公司地址中英文
公司网站地址(苹果会去确认网址)
申请人Apple ID(申请人可以是法人本人,也可以是公司其他人)
申请人邮箱
申请人联系方式
二、申请费用
$299的账号
三、申请周期
30天左右
四、申请步骤
1.准备相关的申请材料
2.申请公司的Duns编码
3.Duns编码申请完成后的14个工作日,就可以申请账号。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。