XCode8 真机测试打包,让发布测试更轻松

iOS- *全的真机测试教程

%title插图%num

I love you not because of who you are,but because of who I am when I am with you

想要上架的同学请看:《iOS-*全的App上架教程》

因为*近更新了Xcode 8 ,证书的创建都大同小异,只是在Xcode 8中的设置有一些变化,我就在下面补充,如有什么疑问,请联系我。。

 同样可以在Build Setting 的 sign中设置证书,但是有点麻烦,建议就在General中设置证书,比较方便,还可以查看错误的地方。

%title插图%num

444444444.png

准备

  • 开发者账号

    自从Xcode7 出来之后,一般的真机测试不需要 开发者账号,也就不需要看这篇教程,只有app具有 “推送”等功能的时候,要真机测试就必须要开发者账号和设置证书。苹果只是让你体验一下它的基本功能,要深入还是要花钱的。

  • 待测试的项目

真机测试步骤

  • 一、创建App ID
  • 二、创建证书请求文件 (CSR文件)
  • 三、根据CSR创建开发者证书(CER)(开发、测试用的Develope证书)
  • 四、添加设备(Devices)
  • 五、根据Devices创建Provisioning Profiles配置文件 (PP文件)
  • 六、设置Xcode 然后真机调试

重点

  • 使用P12 文件 使多台Mac进行真机调试(或者发布) 【重点】

一、创建App ID

  • 1.打开苹果开发者网,点击“Account”登录会员中心。
%title插图%num
%title插图%num
%title插图%num
  • 2.填写信息创建app ID
    %title插图%num

    点击+创建ID
%title插图%num
%title插图%num

*个选项:明确的app id 与项目中的Bundle Identifier相对应
如果你打算将应用程序中加入Game Center,或在应用中使用应 用内购买,进行数据保护,使用iCloud,或者想要给你的应用程序一个唯一的配置文件,你就必须申请Explicit App ID。

第二个选项:通用app id可以在所有不需要明确id的app中使用
淘宝上卖的真机调试证书就是这个

%title插图%num
%title插图%num
%title插图%num

二、创建证书请求文件(CSR文件)

创建CSR文件请看《iOS-*全的App上架教程》的第二点这里就不多说了

三、根据CSR创建开发者证书(CER)

1、 找到Certificates ,点击All,然后点击右上角 + 号

%title插图%num

2 、 点击Developement中的iOS App Developement选项

%title插图%num

3. 点击Continue

%title插图%num

4. 点击Continue

%title插图%num

5. 点击choose File.. 选择创建好的证书请求文件:CertificateSigningRequest.certSigningRequest 文件,点击Generate

%title插图%num

6. 点击Download下载创建好的发布证书(cer后缀的文件),然后点击Done,你创建的发布证书就会存储在帐号中

%title插图%num

7. 双击安装。如果安装不上,可以直接将证书文件拖拽到钥匙串访问的列表中

四、添加设备

1、点击+添加设备到开发者账号中,为制作PP文件做准备

%title插图%num

Name:设备的描述 可以随便填 方便你记忆
UDID:设备的标号

2、获取UUID(这里随便提供一种方法获取UUID)
将iPhone手机插入到电脑上 ,打开iTunes,然后按如图操作

%title插图%num
%title插图%num
%title插图%num

3、填入UUID就OK了

五、根据Devices创建Provisioning Profiles配置文件 (PP文件)

1、找到Provisioning Profiles ,点击All,然后点击右上角 + 号

%title插图%num

2、 选择iOS App Developement,点击Continue

%title插图%num

3、在App ID 这个选项栏里面找到你刚刚创建的:App IDs(Bundle ID) 类型的套装,点击Continue

%title插图%num

4、选择你刚创建的发布证书(或者生成p12文件的那个发布证书),点击Continue

%title插图%num

5、选择设备

%title插图%num

注意:wildCard格式的证书没有推送,PassCard等服务的应用,慎重选择。因为PP证书的开发者证书需要真机调试,所以我们需要绑定真机,这里因为之前添加过一些设备,所以这里就可以直接全选添加,如果没有的话,需要将真机的udid复制出来在此添加。在发布的PP文件中,是没有这一步的。

6、在Profile Name栏里输入一个名字(这个是PP文件的名字,可随便输入,在这里我用工程名字,便于分别),然后点击Generate

%title插图%num

7、然后点击下载 ,将其下载下来

双击就添加到Xcode中,这样在真机调试或者发布时,就可以分别有不同的PP证书与其对应。其实可以不用下载保存


六、设置Xcode 真机调试

1、设置Bundle ID 和 申请的appid 一致

%title插图%num

2、设置Debug的CER证书
3、配置证书描述文件(PP文件)

%title插图%num

4、选择真机 进行真机调试


使用P12 文件 使多台Mac进行真机调试 (或者发布)【重点】

1、为什么要使用P12文件

当我们用大于三个mac设备开发应用时,想要申请新的证书,如果在我们的证书里,包含了3个发布证书,2个开发证书,可以发现再也申请不了开发证书和发布证书了(一般在我们的证书界面中应该只有一个开发证书,一个发布证书,没必要生成那么多的证书,证书一般在过期之后才会重新添加。)

%title插图%num

这时候,再点击“+”时,就会发现点击不了开发和发布证书,也就是添加不了开发证书和发布证书了:

%title插图%num

2、P12文件能解决什么问题
为了不能添加证书的问题我们有2个解决方案

  • *种方法——“revoke”(不推荐):

    将以前的证书“revoke”掉,
    然后重新生成一个新的证书。
    这种方法是可以的,但是会造成相应的ProvisioningProfiles(PP文件)失效,这是小问题。但是又要重新申请证书甚至描述文件很浪费时间,所以不提倡这种做法。

    %title插图%num
  • 第二种方法——“.p12”(推荐):

    我们的每一个证书都可以生成一个.p12文件,这个文件是一个加密的文件,只要知道其密码,就可以供给所有的mac设备使用,使设备不需要在苹果开发者网站重新申请开发和发布证书,就能使用。

3、P12文件是如何使用的

注意:一般.p12文件是给与别人使用的,本机必须已经有一个带秘钥的证书才可以生成.p12文件

  • 导出一个带有私钥的证书(这里我选择调试证书 也就是调试的CER证书 ,其实也可以是 发布证书,只不过那就不用于调试 而是用于上架了)。然后点击导出
    %title插图%num
  • 填好名字和储存位置,点击储存
%title插图%num
  • 填写该P12文件证书的密码,点“好”
    %title插图%num
  • 然后生成P12文件
    %title插图%num
  • 其实P12文件不仅是真机测试的时候用,上架的时候也会用,P12文件的使用方法,调试和上架是一样的。*简单的理解就是:把P12文件当做CER文件使用,调试就当调试CER,上架就当发布CER使用。

    使用
    调试:就是把该教程的第三步创建调试证书省略,将其换成P12文件即可
    上架:把《iOS-*全的App上架教程》的第三步穿件发布证书省略,将其换成P12文件即可。

centos7 搭建FTP服务器以及遇到的坑

1:安装vsftpd

yum install vsftpd -y

2:启动vsftpd

service vsftpd start

加入开机启动

chkconfig vsftpd on

启动后可以看到系统监听21端口

netstat -nltp | grep 21

3:vsftpd的文件说明

vsftpd.conf: 主要配置文件

ftpusers:配置禁止访问ftp服务器的用户列表

user_list:配置用户访问控制

4:配置阻止匿名用户访问和切换根目录

vi /etc/vsftpd/vsftp.conf

找到以下两处并按下面的样子修改

# 禁用匿名用户
anonymous_enable=NO
# 禁止切换根目录
chroot_local_user=YES

#开启以下配置

chroot_local_user=YES
chroot_list_enable=YES
# (default follows)
chroot_list_file=/etc/vsftpd/chroot_list     #如果没有此文件则创建此文件,不需要添加内容

文件末尾添加

allow_writeable_chroot=YES

不添加此项,连接ftp服务器的时候会报500 OOR。。。。

5:创建ftp用户

useradd ftpuser

为用户设置密码

echo “ftpuser123” | passwd ftpuser –stdin

6:限制上步创建的用户只能通过ftp访问

usermod -s /sbin/nologin ftpuser

7:为用户分配主目录

用以下命令创建,但是该目录不能上传文件

mkdir -p /home/ftp/pub

创建欢迎文件

echo “Welcome to use FTP service.” > /home/ftp/welcome.txt

设置访问权限

chmod a-w /home/ftp && chmod 777 -R /home/ftp/pub

设置为用户主目录

usermod -d /home/ftp ftpuser

8:保存后重启vsftpd

service vsftpd restart

9:配置防火墙

在防火墙的配置文件中开启21端口,并重启防火墙

上述步骤即可完成vsftpd搭建,但是客户端只能通过主动模式访问vsftpd,例如使用filezilla需要将传输模式的默认模式改为主动模式才能访问ftp服务器,如果发现可以正常登陆但是无法将目录列出来,就是这个原因.如果需要直接可以访问的话,需要将ftp服务器开启被动模式

1:修改配置文件

vi /etc/vsftpd/vsftpd.conf

2:在末尾添加

pasv_enable=YES
pasv_min_port=30000
pasv_max_port=31000

3:重启vsftpd并将上述的30000端口至31000端口开启,

-A INPUT -m state –state NEW -m tcp -p tcp –dport 30000:31000 -j ACCEPT

备注:过程虽然不难,但遇到的坑比较多,按照很多网上的文章进行配置,*后都是各种错误,刚开始是无法连接,发现没有给用户设置主目录,

当找到问题后修改,可以连接上但是发现权限不够(忘记给目录赋值权限),而且竟然发现创建的用户可以直接通过ssh连接到服务器,这样子就

失去了我想要的,安全性也大大降低了,总之问题很多,*头疼的还是提示已经登陆但是无法将目录展示出来,经过自己分析日志发现是模式不对,

希望大家可以借鉴参考,尽量少入点坑

CentOS7环境下搭建ftp服务器

查看是否安装ftp rpm -qa | grep vsftpd
安装ftp yum -y install vsftpd
卸载 rpm -e vsftpd
启动 /bin/systemctl start vsftpd.service
重启 /bin/systemctl restart vsftpd.service
查看状态 /bin/systemctl status vsftpd.service
开机自启chkconfig vsftpd on

创建ftp用户 useradd -d /home/test test
限定用户不能登录,只能ftp usermod -s /sbin/nologin test
设置用户密码 passwd test

chmod -R 777 /home/test

vi /etc/selinux/config

SELINUX=disabled

vi /etc/vsftpd/vsftpd.conf

anonymous_enable=NO (修改)
chroot_local_user=NO(修改)
chroot_list_enable=YES (修改)
chroot_list_file=/etc/vsftpd/chroot_list (修改)
allow_writeable_chroot=YES (新增)
userlist_deny=NO (新增)
reverse_lookup_enable=NO (新增)

vim /etc/vsftpd/chroot_list将test加入进去
vim /etc/vsftpd/user_list将test加入进去

FileZilla下载链接:https://pan.baidu.com/s/1Wh1GcDh0gnlbp2PtMQgbOg
提取码:6okg
%title插图%num

【*新】Xcode 8 打包教程

相信iOS开发者们更新了iOS 10之后除了吐槽越来越像安卓之外,吐槽的更多的也是Xcode的一系列问题,本次Xcode 的变化无非是 大概以下三点:
       1.各种其妙log的打印
       2.一些权限的添加
       3.证书添加了自动管理证书功能
       4.打包的问题
      关于*个和第二个的问题,我着重要说的是打包发版的问题,因为我是Xcode 8出来后第二天我就适配完毕打包上线的.
      *个要说的是关于证书的问题,Xcode 8 为了帮助开发者更好的管理证书,合理的Automatically manager signing就是自动管理证书的,勾选之后,在弹出的弹框中选择Enable  Automatic, 然后Team 选项None为我们公司的证书,然后下方的Provisioning 和Signing 都是会自动选择的.
%title插图%num
如果下方的描述文件和证书报错,那么就去从新生成一下.接下来就说打包的问题.
 Xcode 8 打包的时候我们是不用去Build Settings 中的code sign 中像之前一样修改的,这里什么都不用修改,并且我们的General中看到的Signing 还是开发环境下的,然后我们直接在Product 中选择Archive来打包,
%title插图%num
然后选择Export来导出包,选择*个Save for iOS  App Store Deployment 来导出包:
%title插图%num
%title插图%num
这个时候我们发现我们没有手动修改证书没有修改描述文件,并且在*张图中还是Signing 还是开发环境,就是这样的,Xcode 在帮我们自动管理.我曾今也尝试着在勾选了自动管理证书后,手动再去修改证书和描述文件,结果发现报错,报错的意思就是不能在选择了自动管理证书之后还去手动修改.没错,Xcode 就是自动来管理证书和描述文件的,包括我们真机调试和虚拟机的时候,我们的Xcode都是不需要做任何调整和修改的.(敲完才发现,全是英文标点….)
注意,如果你们在上传以后,提示此构建版本无效,那么多数就是你们权限设置有问题,并且你们还没有绑定邮箱,你们上传之后,苹果会帮你审核的,如果没问题会发邮件告诉你,如果有问题也会发邮件告诉你,如果你们没有绑定邮箱,会发现有了问题之后不知道啥问题,就会以为是上传的问题,其实不是,如图就是权限没有描述的问题和推送的问题:
%title插图%num
问题多数都是权限添加的问题,你添加了全选之后,那个key也是要填写的,还有就是有个警告就是打开推送:
%title插图%num

iPhone 6/6Plus UI界面设计和适配尺寸规范

iPhone 6/6Plus UI界面设计和适配尺寸规范

发布于: 2014 年 12 月 10 日 by admin

对于iPhone 6/6Plus UI界面设计和适配尺寸规范的相关教程和知识点,网上已经有很多了,而且大部分都是可以值得去参考和学习。

而今天25学堂来跟大家分享的必定是关于APP设计新手容易理解的iPhone 6/6Plus UI界面设计和适配尺寸规范。  也可以说是,目前移动APP设计行业内,小公司里面APP设计师如何用一套UI界面设计稿来解决所有的iphone机型。

下面这张图是iphone手机的所有机型大全:

今天25学堂只讲ios系统上面的UI界面设计和适配尺寸规范。安卓的后面再继续,总之懒人也有懒人的办法。欢迎来喷!

2014年,iPhone 6, iPhone 6 Plus发布后,iphone APP设计不得了考虑适配所有iPhone机型啦。

下面来看老谭老师聊聊一些关于iPhone 6/6Plus UI界面设计和适配尺寸规范的经验和干货。

*种办法

如果以iphone5s 为基准设计稿,适配iphone6 或者是iphone 6 plus的方法和技巧。

当旧的iPhone 5程序运行在iPhone 6上面,假如没有经过适配。旧程序自动等比放大,铺满新手机,旧程序也可以正常运行。这种方案可算是自动适配。但因为旧程序拉伸了,整体看起来有点虚,也不能更好利用大屏空间。

一套设计稿适配的前提:设计稿必须为矢量的。图片除外。比如图标,线、点、颜色块等元素都是矢量或者形状。

分为两步走:

如果是一些常规界面:比如以文字、列表为主的界面,大部分是指布局相对简单的界面。不用设计师怎么切图的界面,这些基本可以让ios程序员完成适配即可。显示效果也不会太差。

如果是一些定制界面:此时设计师应该手动为大屏幕重新调整设计。另外设计一些大图或者是大的图标,以满足适配iphone6.或者iphone plus

前提是你们的ios程序员需要了解苹果公司的一个工具:Auto Layout

Auto Layout (Auto Layout Guide: Introduction),可以理解成 iOS 上的 CSS,如果设计师用 Auto Layout 提供的排版语言描述出 UI 布局,那不同尺寸的 iPhone 只要同一份设计稿就可以了。

总之:适配iPhone 6/6Plus UI界面设计的要点:

1、针对iphone6  可以用高度不变,横向拉伸。或者等比拉伸

2、全矢量作图。

3、定制界面或图片位图必须额外制作大图。

4、工具栏、状态栏、导航栏的高度规范和设计字体大小等均以2:3的比例放大即可。

5、iphone的5/5S/6/6P的屏幕比例为9:16,所以比例这个问题现在不是很大,但因 

Plus增加横版显示,所以建议对于一些用户量较高的软件进行重绘。

 

第二种版本 

以iphone6  为基准设计稿,适配iphone5 或者是iphone 6 plus的方法和技巧。

第三种版本:以iphone6 plus 为基准设计稿,适配iphone5 或者是iphone 6的方法和技巧。

iphone6 plus 的设计尺寸是1242*2208px   

解决方法:①简单粗暴的等比例缩放图片尺寸,也就是说直接把现在有的图片资源调整为0.5倍,如果全部用路径画图,会简单许多,直接调整大小即可。

设计尺寸是:1242*2208px 这个尺寸是比较大的,对于哪些电脑配置不够好的小伙伴们可以按照上面的2种做法。

如果你的是mac电脑,直接使用Sketch轻松做到,6和5的切图可以用一套,ppi都是326,6+的话导出3x图就ok。

 

 *后,给app设计师9点建议吧!

1、以后的应用程序,都使用AutoLayout, 不要再用*对定位。

2、使用类似网页的方式来设计界面。

3、设计师好,程序员也好,尽量使用点这个单位进行思考,而不要使用像素。比如,你需要做44 x 66个点的按钮,2x模式,就乘以2, 3x模式就乘以3。这样的思考方式可以大致估计到真实的物理长度。44个点,就是手机上导航栏,工具栏的高度。假如用像素思考,容易使得做出的图片过大或者过小。

4、非矢量素材,就可以做尺寸*大的,之后再进行缩小。比如你需要兼容3x的屏幕,就直接做*高那种图片。

5、而当使用Flash之类的矢量工具来做素材的时候,应该直接做点那个尺寸。比如44 x 66个点的按钮。就建立一个44 x 66的场景。之后再导出成2倍图,3倍图,因为矢量放大不失真。不要建立一个3x的场景,导出成大图片,再进行缩小,这样就容易失真。更理想的是直接使用矢量图。

6、假如是那种导航栏,工具栏之类的背景图,需要横跨整个屏幕。可以只切一小块,让程序拉伸,拉伸方式是保持两边的像素不动,只拉伸*中间的一列像素。需要拉伸的话,横方向就不要出现一些渐变色。

7、按钮的点击区域,不应该少于44像素,就算按钮的图片看起来比较小,也应该使得点按钮周围的透明区也有反应。

8、可以按照你当前*方便测试机子的型号来做一些主要预览图,效果图。比如你手头有iPhone 5,可以按照iPhone 5的尺寸,320 x 568个点,需要兼容iPhone 6 Plus,就使用3x的模式。这样方便将图片放进手机里面看实际的效果。有多个测试机,就选较大的,之后再进行一些细调。假如支持iPhone 6 Plus的横屏模式,需要另外处理。

9、上面说的是应用的处理方式,游戏会有些特殊。现在很多游戏,按照1136 x 768的像素尺寸来设计场景,这样可以同时兼容iPad和iPhone,并只使用一份图。iPad 1x模式下尺寸是1024 x 768像素,iPhone 6在2x模式下,是1136 * 640。这种尺寸,可以简单将场景居中显示,各自将场景拉伸到*大。

阿里云Centos7.x负载均衡服务器间代码定时同步

环境:Centos7.X
负载均衡的代码主/从rsync定时同步

A服务器(主服务器):

安装rsync:yum install rsync -y
vi /etc/rsyncd.conf

strict modes = yes

port = 873

uid = root

gid = root

use chroot = no

max connection = 5

timeout = 600

pid file = /var/run/rsyncd.pid

lock file = /var/run/rsyncd.lock

log file = /var/log/rsyncd.log

hosts allow = 172.18..X.X #内网B服务器

[www.XXX.com-rsync] #此段的名称,在B服务器同步时需指定

path = /home/wwwdata/www.XXX.com

ignore errors

read only = no

list = no

hosts allow = 172.18.X.X #内网B服务器

auth users = root

secrets file = /etc/rsyncd.password

设置同步时需要的账号密码

vi /etc/rsyncd.password
root:123456
chmod 600 /etc/rsyncd.password

Centos7.x防火墙默认不是iptables,是firewalld,因此要通过firewalld将rsync的873端口开放给B服务器

开放873端口:firewall-cmd –permanent –add-port=873/tcp
检查是否开启成功:firewall-cmd –permanent –query-port=873/tcp
重启防火墙:firewall-cmd –reload

启动:rsync –daemon –config=/etc/rsyncd.conf
开机启动:echo ‘/user/bin/rsync –daemon –config=/etc/rsyncd.conf’ >> /etc/rc.local
B服务器(从服务器)

设置同步密码(此处应与A服设置的访问密码一致)

vi /etc/rsyncd.password
123456
chmod 600 /etc/rsyncd.password

写同步脚本:vi rsync_xxx

#!/bin/bash
/usr/bin/rsync -avzP –delete –progress –password-file=/etc/rsyncd.password root@172.18.0.X.X::www.XXX.com-rsync home/wwwdata/www.XXX.com
chmod u+x rsync_xxx

定时同步:

定时同步:crontab -e
*/1 * * * * /home/wwwdata/rsync-from-106-www.XXX.com >> /home/wwwdata/_bk/crontab_www_`date+\%Y\%m\%d`.log 2>&1
重新加载:service crond reload
查看执行日志:tail -f /var/log/cron
查看自定义日志:cat /home/wwwdata/_bk/crontab_www_2016-12-24.log

交互设计:iOS原型尺寸规范

*近公司安排我带一下新来的交互设计师,我想给他制定一份交互设计规范。这样一来,即使新来的交互设计师没什么基础,也可以根据这一份规范,做出大致标准的原型图。

因为Ui设计稿是先做iPhone6的,方便向上适配iPhone6Plus,也方便向下适配iPhone5和iPhone4的尺寸。所以,交互设计稿的尺寸,就按照iPhone6的尺寸来做。

 

在这里我还是要推荐下我自己建的iOS开发学习群:680565220,群里都是学ios开发的,如果你正在学习ios ,小编欢迎你加入,今天分享的这个案例已经上传到群文件,大家都是软件开发党,不定期分享干货(只有iOS软件开发相关的),包括我自己整理的一份2018*新的iOS进阶资料和高级开发教程

1、 iPhone6的界面布局是:屏幕是4.7英寸的,设计稿的大小为750x1334px。
状态栏(status bar):就是电量条,其高度为:40px;
导航栏(navigation):就是顶部条,其高度为:88px;
主菜单栏(submenu,tab):就是标签栏,底部条,其高度为:98px;
内容区域(content):就是屏幕中间的区域,其高度为:1334px-40px-88px-98px=1108px
截图如下:

推荐3款测量工具为:MarkMan马克鳗,Dorado标注,PXcook像素大厨。

 

2、关于iPhone6的图标的尺寸:
导航栏的图标高度为44px左右,标签栏的图标尺寸为50x50px左右,*大为96x64px。
关于iPhone6的文字的尺寸:

导航栏的文字大小*大值是34px,标签栏的图标下方的文字大小为20px。内容区域的文字大小是:24px,26px,28px,30px,32px,34px。
3、(iPhone6设计稿尺寸是@2x),做原型图的时候,可以做成@2x的,即750x1334px;也可以做成@1x的,即375*667px。
4、设置界面的图标高度和开关滑动按钮的图标高度:58px。

 

5、关于颜色,自从我做了3套高保真的交互原型图之后,发现后面还是改成画线框图来的快。
线框图的黑白灰之纯美,有利于专心布局界面,而不用在意界面的颜色搭配。

黑白灰颜色常用的数值是:

文字黑色#282828
文字深灰色#656565
文字浅灰色#98989
边框浅灰色#C3C3C3
背景淡灰色#f2f2f2
按钮背景纯白色#ffffff
6、常用的可点击高度,在iPhone6的原型图上,统一成88px。在iPhone6设计稿中,88px是一个常用的设计尺寸。

 

7、搜索栏的高度,在iPhone6的原型图上,统一成58px。在iPhone6设计稿中,58px是一个常用的设计尺寸。

 

8、在iPhone6设计稿中,界面元素之间的常用距离,亲密距离:20px;疏远距离:30px。
疏远距离:比如,所有元素距离手机屏幕*左边的距离。
亲密距离:比如,左边图标与右边文字之间的距离。

9、原型设计中,需要考虑不同屏幕尺寸的苹果手机,在@1x的情况下的适配情况。比如:
iPhone5在@2x屏幕尺寸是,640x1136px;对应的@1x,屏幕尺寸就是320x568px;
iPhone6在@2x屏幕尺寸是:750x1334px;对应的@1x,屏幕尺寸就是375x667px;
iPhone6Plus在@3x屏幕尺寸是:750x1334px;对应的@1x,屏幕尺寸就是414x736px;

 

10、iPhone6Plus的@3x,iPhone6的@2x, iPhone5的@2x的介绍
iPhone6Plus是5.5英寸屏幕,1242x2208px-@3x的像素分辨率,逻辑分辨率是414x736pt-@1x。物理尺寸是1080x1920px。这个物理尺寸,也是安卓机目前*流行的大屏设计稿尺寸。
iPhone6是4.7英寸屏幕,750x1334px-@2x的像素分辨率,逻辑分辨率是375x667pt-@1x。
iPhone5是4英寸屏幕,640x1135px-@2x的像素分辨率,逻辑分辨率是320x568pt-@1x。

 

【综上所述】iPhone6的原型规范如下:
界面尺寸布局:满屏尺寸750x1334px
高度电量条高度40px,导航栏高度88px,标签栏高度98px;
各区域图标大小导航栏图标44px,标签栏图标50px;
各区域文字大小电量条文字22px,导航栏-文字32px,标签栏字20px;
常用的文字大小:32px,30px,28px,26px,24px,22px,20px;
常用的颜色:背景浅灰色#f2f2f2,文字深黑色#323232,边框色深灰#CCCCCC;
常用可点击区域的高度:88px;
单行文字的背景框的高度:88px,双行则为:176px,三行则为:264px;
常用间距:亲密距离:20px;疏远距离:30px,其它距离:10px,44px等;
按钮和文本框,原型图做成直角的,圆角半径是多少,由Ui来设计;
这种情况,需要修改原型。单个页面的逻辑流程图或用户学习使用时间,超过其它页面平均数的3倍以上;
以上规范具备如下的一个条件,即可修改:
准备有已经上线的截屏参考页面;
产品和开发协商修改。

python配置国内pip源

python配置国内pip源

发现问题:
你安装了python,但是通过pip下载包很慢。
例如:你要下载pandas、numpy等较大的包,但是下载很慢,等了好久竟然超时了。

原因分析:
安装了官方pip后,默认配置的是国外的pip库,因此下载就会很慢。

解决方案:
配置国内的pip源,个人习惯清华大学的pip源。强烈建议使用这种命令行的方式,经过笔者试验,linux/windows均使用。完美了!

常用的国内pip源:
https://pypi.tuna.tsinghua.edu.cn/simple
http://mirrors.aliyun.com/pypi/simple/
http://pypi.douban.com/simple/

国内常用的开源软件镜像站点:
https://mirrors.tuna.tsinghua.edu.cn/help/pypi/

临时使用
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple some-package
1
设为默认
step1:升级pip版本
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pip -U
1
step2: 设置默认pip源
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
1
如果本地配置了多个python,只想给某个python升级,你只要python -m pip xxxx就行了。

step3:开始使用pip
D:\cmder
λ C:\Python38\python.exe -m pip install –upgrade pip
Looking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple
Collecting pip
Downloading https://pypi.tuna.tsinghua.edu.cn/packages/fe/ef/60d7ba03b5c442309ef42e7d69959f73aacccd0d86008362a681c4698e83/pip-21.0.1-py3-none-any.whl (1.5 MB)
|████████████████████████████████| 1.5 MB 327 kB/s
Installing collected packages: pip
Attempting uninstall: pip
Found existing installation: pip 20.2.3
Uninstalling pip-20.2.3:
Successfully uninstalled pip-20.2.3
Successfully installed pip-21.0.1

D:\cmder
λ C:\Python38\python.exe -m pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
Writing to C:\Users\robin\AppData\Roaming\pip\pip.ini

D:\cmder
λ pip –version
pip 21.0.1 from c:\python38\lib\site-packages\pip (python 3.8)

D:\cmder
λ pip install pandas
Looking in indexes: https://pypi.tuna.tsinghua.edu.cn/simple
Requirement already satisfied: pandas in c:\python38\lib\site-packages (1.2.3)
Requirement already satisfied: python-dateutil>=2.7.3 in c:\python38\lib\site-packages (from pandas) (2.8.1)
Requirement already satisfied: pytz>=2017.3 in c:\python38\lib\site-packages (from pandas) (2021.1)
Requirement already satisfied: numpy>=1.16.5 in c:\python38\lib\site-packages (from pandas) (1.20.2)
Requirement already satisfied: six>=1.5 in c:\python38\lib\site-packages (from python-dateutil>=2.7.3->pandas)

Android 监听应用程序安装和卸载

*、             新建监听类:BootReceiver继承BroadcastReceiver

publicclass BootReceiver extends BroadcastReceiver {
@Override

public void onReceive(Context context,Intent intent) {
//接收广播:系统启动完成后运行程序

if(intent.getAction().equals(“android.intent.action.BOOT_COMPLETED”)) {
Intent newIntent = new Intent(context,WatchInstall.class);

newIntent.setAction(“android.intent.action.MAIN”);             newIntent.addCategory(“android.intent.category.LAUNCHER”);           newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);            context.startActivity(newIntent);

}

//接收广播:设备上新安装了一个应用程序包后自动启动新安装应用程序。

if(intent.getAction().equals(“android.intent.action.PACKAGE_ADDED”)) {
String packageName =intent.getDataString().substring(8);

System.out.println(“—————” + packageName);

Intent newIntent = new Intent();

newIntent.setClassName(packageName,packageName+ .MainActivity”);

newIntent.setAction(“android.intent.action.MAIN”);            newIntent.addCategory(“android.intent.category.LAUNCHER”);             newIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

context.startActivity(newIntent);

}

//接收广播:设备上删除了一个应用程序包。

if(intent.getAction().equals(“android.intent.action.PACKAGE_REMOVED”)){
System.out.println(“********************************”);

}

}

第二、             修改AndroidManifest.xml配置文件

<?xmlversion=”1.0″ encoding=”UTF-8″?>

<manifestxmlns:android=”http://schemas.android.com/apk/res/android”

package=”org.me.watchinstall”>

<application>

<receiverandroid:name=”.BootReceiver”

android:label=”@string/app_name”>

<intent-filter>

<actionandroid:name=”android.intent.action.BOOT_COMPLETED”/>

<categoryandroid:name=”android.intent.category.LAUNCHER” />

</intent-filter>

<intent-filter>

<actionandroid:name=”android.intent.action.PACKAGE_ADDED” />

<actionandroid:name=”android.intent.action.PACKAGE_REMOVED” />

<data android:scheme=”package” />

<!– 注意!!这句必须要加,否则接收不到BroadCast –>

</intent-filter>

</receiver>

<activityandroid:name=”.WatchInstall”android:label=”WatchInstall”>

<intent-filter>

<actionandroid:name=”android.intent.action.MAIN”/>

<categoryandroid:name=”android.intent.category.LAUNCHER”/>

</intent-filter>

</activity>

</application>

</manifest>

python 在pdf文件中批量添加编码

python 在pdf文件中批量添加编码(DrawString中文解决,Rotation处理)

参考了好多资料和文章,然后各种无目的的尝试和实验,成功。希望可以帮到在办公室繁重办公的各位。

import PyPDF2, xlrd,io,os
import win32ui
from PyPDF2 import PdfFileReader, PdfFileWriter
from PIL import Image
import tkinter as tk
from tkinter import filedialog
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfgen import canvas
from reportlab.pdfbase.ttfonts import TTFont

fspec=”Excel 2003(*.xls)|*.xls”
dlg = win32ui.CreateFileDialog(1,None, “请选择索引excel表”, 1, fspec, None)
”’
请将文件路径放在xls文件第1个表的A列,将从第2行开始
将将要录入的代码放在B列
pdf文件与图片文件是分次处理,故不能统一编码,卡脖子的技术瓶颈已经在改代码中解决,可自行重构代码打到效果
”’
root=tk.Tk()
root.withdraw()
dlg.SetOFNInitialDir(‘d:/’) # 设置打开文件对话框中的初始显示目录
dlg.DoModal() # 显示文件对话框
filename = dlg.GetPathName() # 获取选择的文件名称
outDir=filedialog.askdirectory() # 获取选择的保存
outDir.replace(“/”,”\\”) # 格式化文件路径
print(outDir) # print输出路径
wb=xlrd.open_workbook(filename) # 打开索引表
sheet1 =wb.sheets()[0] # 获取索引表的*个表格
path=sheet1.col(0) # 读取表格*列的内容:合同文件路径
xulie=sheet1.col(1) # 读取表格第二列的内容:文件编号
‘print(path)’
print(“=======================================================”)
‘print(xulie)’
FontSize=16 # 设置字体大小
pdfmetrics.registerFont(TTFont(‘华光综艺_CNKI’, ‘HGZY_CNKI.TTF’)) # 注册中文字体包
for i in range(1,sheet1.nrows-1): # 遍历表格里的合同文件
file = os.path.splitext(path[i].value) # 获取文件名中的信息
filename, type = file
print(“Got-PDF-Path = %s”%path[i].value)
print(“Got-PDF-Index = %s”%xulie[i].value)
if type==”.pdf”: # 判断为pdf文件则进行下列操作:
PdfReader=PyPDF2.PdfFileReader(path[i].value) # 打开读取接口
pageCount=PdfReader.getNumPages() # 获取页面数
print(xulie[i].value,”-Pages = “,pageCount) # print页面数
writerObj = PdfFileWriter() # 新建写入接口(未指定写入目标)
for page in PdfReader.pages: # 遍历pdf文件中的每一页
print(“Page”,PdfReader.getPageNumber(page)+1,”/”,pageCount) # Print该页页码
Ohight = int(page.cropBox.upperRight[1]) # 获取页面高度(英文打错了但懒得改)
Owidth = int(page.cropBox.upperRight[0]) # 获取页面宽度
print(“Size = (Height:%s”%Ohight, “; Width:%s)”%Owidth,) # print页面长宽
packet = io.BytesIO() # 为画布创建IO流,申请空间
packet.seek(0) # 从0开始读写
can = canvas.Canvas(packet) # 创建画布,并绑定IO流
can.setFont(‘华光综艺_CNKI’,FontSize) # 设置字体和大小
xl = “%s” % xulie[i].value # 格式化编号内容
if page.mediaBox.getUpperRight_x() – page.mediaBox.getUpperLeft_x() > \
page.mediaBox.getUpperRight_y() – page.mediaBox.getLowerRight_y(): # 判断纵横
print(‘横向’)
BleedX = FontSize*2 # 设置空白处宽度
BleedY = 0 # 设置空白处高度
else: # 纵向同理
print(‘纵向’)
BleedX = 0
BleedY = FontSize*2
Owidth+=2*BleedX # 记录新的页面宽度
Ohight+=2*BleedY # 记录新的页面高度
can.translate(Owidth/2, Ohight/2) # 将画布的原点放置在页面中心
Bpage=writerObj.addBlankPage(Owidth,Ohight) # 创建新的页面
Bpage.mergeScaledTranslatedPage(page, 1, BleedX, BleedY) # 将旧页面居中贴到新页面上
can.drawString(Owidth / 2 – FontSize * len(xl), Ohight / 2 – FontSize, text=xl.encode(‘utf-8’))
# 往画布右上角写字
can.rotate(180) # 画布颠倒,准备再写字(为了处理上下颠倒的情况)
can.drawString(Owidth / 2 – FontSize * len(xl), Ohight / 2 – FontSize, text=xl.encode(‘utf-8’))
# 往画布右上角再写一次字
can.save() # 画布提交保存到IO流
textPg = PdfFileReader(packet) # 通过IO流创建写了编号的pdf
Bpage.mergePage(textPg.getPage(0)) # 将写了编号的pdf覆盖到输出的页面上

if writerObj.getNumPages() % 2 == 1: writerObj.addBlankPage() # 如果页面是单数,就加一页空白页,方便双面打印
outstream = open(outDir + “/%s.pdf”%xulie[i].value, ‘xb’) # 在选定的输出文件夹里新建文件和输出接口(IO流)
print(‘Saving as %s’%(outDir + “/%s.pdf”%xulie[i].value)) # print保存的路径
writerObj.write(outstream) # 将pdf输出到IO流里写入文件
outstream.close() # 关闭输出IO流,文件保存
else: # 处理图片文件
# 处理非pdf文件:将同编号的图片文件加入到同一个pdf文件中
# 表格字典化:
# 利用字典储存路径列表,键为编号
PathDict = {‘初始’:(0)} # 初始化字典:定义字符串(编码)的键,列表(文件路径)的内容
if PathDict.get(“%s” % xulie[i].value)==None: # 如果该序列键指向的内容为空(之前没有遍历到同编号的图片的话)
PathDict[“%s” % xulie[i].value]=list(“%s” % path[i].value) # 新建键和列表内容
else: # 如果已经有同编号的图片的话
PathDict[“%s” % xulie[i].value].append(“%s” % path[i].value) # 在列表里添加该图片的路径
del i # 删除之前i的赋值和格式(变量类型重置)
for i in PathDict.keys(): # 遍历字典里的键
packet = io.BytesIO() # 为画布创建IO流,申请空间
packet.seek(0) # 从0开始读写
can = canvas.Canvas(packet) # 创建画布,并绑定IO流
can.setFont(‘华光综艺_CNKI’, FontSize) # 设置字体和大小
for k in PathDict[i]: # 遍历键里的列表(图片路径)
img = Image.open(k, “r”) # 打开图片路径读取内容
can.setPageSize((img.size[0],img.size[1])) # 读取图片大小来设置画布大小
print(k,”:”,img.size) # print图片大小
can.drawImage(canvas.ImageReader(k),0,0) # 把图片印在画布上
Owidth=img.size[0] # 记录页面宽度为图片宽度
Ohight=img.size[1] # 记录页面高度为图片高度
page=PdfFileWriter.addBlankPage(Owidth,Ohight) # 新建一个跟图片同高同宽的页面
if img.size[0] > img.size[1]: # 判断图片方向
print(‘横向’)
BleedX = FontSize * 2 # 设置空白处宽度
BleedY = 0 # 设置空白处高度
else: # 纵向同理
print(‘纵向’)
BleedX = 0
BleedY = FontSize * 2
Owidth += 2 * BleedX # 记录下页面出血后的宽度
Ohight += 2 * BleedY # 记录下页面出血后的高度
can.translate(Owidth / 2, Ohight / 2) # 将画布放在新页面中心
Bpage = writerObj.addBlankPage(Owidth, Ohight) # 在输出pdf里新建新页面
Bpage.mergeScaledTranslatedPage(page, 1, BleedX, BleedY) # 把图片页面居中放到输出pdf的新页面中
can.drawString(Owidth / 2 – FontSize * len(i), Ohight / 2 – FontSize, text=i.encode(‘utf-8’)) # 写字
can.rotate(180) # 画布颠倒,准备再写字(为了处理上下颠倒的情况)
can.drawString(Owidth / 2 – FontSize * len(i), Ohight / 2 – FontSize, text=i.encode(‘utf-8’)) # 写字
can.save() # 画布提交保存到IO流
textPg = PdfFileReader(packet) # 通过IO流创建写了编号的pdf
Bpage.mergePage(textPg.getPage(0)) # 将写了编号的pdf覆盖到输出的页面上
if writerObj.getNumPages() % 2 == 1: writerObj.addBlankPage() # 如果*终pdf的页面是单数,就加一页空白页,方便双面打印
outstream = open(outDir + “/%s.pdf” % xulie[i].value, ‘xb’) # 在选定的输出文件夹里新建文件和输出接口(IO流)
print(‘Saving as %s’ % (outDir + “/%s.pdf” % xulie[i].value)) # print保存的文件
writerObj.write(outstream) # 将pdf输出到IO流里写入文件
outstream.close() # 关闭输出IO流,文件保存