2021年7月下旬流通领域重要生产资料市场价格变动情况

中国统计信息服务中心 卓创资讯   据对全国流通领域9大类50种重要生产资料市场价格的监测显示,2021年7月下旬与7月中旬相比,31种产品价格上涨,18种下降,1种持平。 2021年7月下旬流通领域重要生产资料市场价格变动情况  产品名称 单位 本期价格(元) 比上期 价格涨跌(元) 涨跌幅 (%) 一、黑色金属         螺纹钢(Φ16-25mm,HRB400E) 吨 5322.8 130.5 2.5 线材(Φ6.5mm,HPB300) 吨 5617.5 129.4 2.4 普通中板(20mm,Q235) 吨 5688.1 88.7 1.6 热轧普通薄板(3mm,Q235) 吨 5931.7 67.9 1.2 无缝钢管(219*6,20#) 吨 6151.8 106.6 1.8 角钢(5#) 吨 5615.0 83.8 1.5 二、有色金属         电解铜(1#) 吨 70879.1 1853.8 2.7 铝锭(A00) 吨 19443.1 231.9 1.2 铅锭(1#) 吨 15721.9 176.3 1.1 锌锭(0#) 吨 22476.3 50.6 0.2 三、化工产品         硫酸(98%) 吨 741.3 57.7 8.4 烧碱(液碱,32%) 吨 659.7 56.4 9.3 甲醇(优等品) 吨 2476.7 49.4 2.0 纯苯(石油苯,工业级) 吨 8119.0 -296.3 -3.5 苯乙烯(一级品) 吨 9370.5 7.9 0.1 聚乙烯(LLDPE,7042) 吨 8583.2 -6.0 -0.1 聚丙烯(T30S) 吨 8658.0 -67.3 -0.8 聚氯乙烯(SG5) 吨 9246.0 80.5 0.9 顺丁胶(BR9000) 吨 14133.1 22.4 0.2 涤纶长丝(FDY150D/96F) 吨 8062.5 26.8 0.3 四、石油天然气         液化天然气(LNG) 吨 4900.8 528.8 12.1 液化石油气(LPG) 吨 4474.0 85.7 2.0 汽油(95#国VI) 吨 8257.2 -58.5 -0.7 汽油(92#国VI) 吨 8016.3 -62.0 -0.8 柴油(0#国VI) 吨 6427.2 -69.6 -1.1 石蜡(58#半) 吨 7356.7 23.8 0.3 五、煤炭         无烟煤(洗中块) 吨 1400.0 0.0 0.0 普通混煤(4500大卡) 吨 773.1 23.8 3.2 山西大混(5000大卡) 吨 863.1 23.8 2.8 山西优混(5500大卡) 吨 943.1 23.1 2.5 大同混煤(5800大卡) 吨 968.1 23.1 2.4 焦煤(主焦煤) 吨 2181.3 124.2 6.0 焦炭(二级冶金焦) 吨 2506.8 -60.0 -2.3 六、非金属建材         普通硅酸盐水泥(P.O 42.5袋装) 吨 430.7 -6.9 -1.6 普通硅酸盐水泥(P.O 42.5散装) 吨 379.3 -7.1 -1.8 浮法平板玻璃(4.8/5mm) 吨 3064.8 109.4 3.7 七、农产品(主要用于加工)         稻米(粳稻米) 吨 3902.8 -15.4 -0.4 小麦(国标三等) 吨 2520.8 -6.7 -0.3 玉米(黄玉米二等) 吨 2634.1 -61.7 -2.3 棉花(皮棉,白棉三级) 吨 17706.7 561.5 3.3 生猪(外三元) 千克 15.5 -0.1 -0.6 大豆(黄豆) 吨 5204.2 -19.6 -0.4 豆粕(粗蛋白含量≥43%) 吨 3581.8 -24.5 -0.7 花生(油料花生米) 吨 8093.7 31.8 0.4 八、农业生产资料         尿素(小颗料) 吨 2822.5 21.8 0.8 复合肥(硫酸钾复合肥,氮磷钾含量45%) 吨 3097.7 72.7 2.4 农药(草甘膦,95%原药) 吨 50625.0 875.0 1.8 九、林产品         天然橡胶(标准胶SCRWF) 吨 12863.5 -83.8 -0.6 纸浆(漂白化学浆) 吨 5327.3 -93.0 -1.7 瓦楞纸(高强) 吨 4103.3 -34.5 -0.8 注:上期为2021年7月中旬。    附注   1.指标解释   流通领域重要生产资料市场价格,是指重要生产资料经营企业的批发和销售价格。与出厂价格不同,生产资料市场价格既包含出厂价格,也包含有经营企业的流通费用、利润和税费等。出厂价格与市场价格互相影响,存在时滞,两者的变动趋势在某一时间段内有可能会出现不完全一致的情况。   2.监测内容   流通领域重要生产资料市场价格监测内容包括9大类50种产品的价格。类别与产品规格说明详见附表。   3.监测范围   监测范围涵盖全国31个省(区、市)300多个交易市场的近2000家批发商、代理商、经销商等经营企业。   4.监测方法   价格监测方法包括信息员现场采价,电话、即时通讯工具和电子邮件询价等。   5.涨跌个数的统计   产品价格上涨、下降、持平个数按照涨跌幅(%)进行统计。   6.发布日期   每月4日、14日、24日发布上一旬数据,节假日顺延。 附表:流通领域重要生产资料市场价格监测产品规格说明表  序号 监测产品 规格型号 说明   一、黑色金属      1   螺纹钢 Φ16-25mm,HRB400E 屈服强度≥400MPa  2 线材 Φ6.5mm,HPB300 屈服强度≥300MPa  3 普通中板 20mm,Q235 屈服强度≥235MPa  4 热轧普通薄板 3mm,Q235 屈服强度≥235MPa  5 无缝钢管 219*6,20# 20#钢材,屈服强度≥245MPa  6 角钢 5# 屈服强度≥235MPa   二、有色金属      7 电解铜 1# 铜与银质量分数≥99.95%  8 铝锭 A00 铝质量分数≥99.7%  9 铅锭 1# 铅质量分数≥99.994% 10 锌锭 0# 锌质量分数≥99.995%   三、化工产品     11  硫酸 98% H2SO4质量分数≥98% 12 烧碱(液碱) 32% NaOH质量分数≥32%的离子膜碱 13 甲醇 优等品 水质量含量≤0.10% 14 纯苯(石油苯) 工业级 苯纯度≥99.8% 15 苯乙烯 一级品 纯度≥99.5% 16 聚乙烯(LLDPE) 7042 熔指:2.0±0.5g/10min 17 聚丙烯 T30S 熔指:3.0±0.9g/10min 18 聚氯乙烯 SG5 K值:66-68 19 顺丁胶 BR9000 块状、乳白色,灰分≤0.20% 20 涤纶长丝 FDY150D/96F 150旦,AA级   四、石油天然气     21 液化天然气 LNG 甲烷含量≥75%,密度≥430kg/m3 22 液化石油气 LPG 饱和蒸汽压1380-1430kPa 23 汽油 95#国VI 国VI标准 24 汽油 92#国VI 国VI标准 25 柴油 0#国VI 国VI标准 26 石蜡 58#半 熔点不低于58℃   五、煤炭     27 无烟煤 洗中块 挥发分≤8% 28 普通混煤 4500大卡 山西粉煤与块煤的混合煤,热值4500大卡 29 山西大混 5000大卡 质量较好的混煤,热值5000大卡 30 山西优混 5500大卡 优质的混煤,热值5500大卡 31 大同混煤 5800大卡 大同产混煤,热值5800大卡 32 焦煤  主焦煤 含硫量<1% 33 焦炭 二级冶金焦 12.01%≤灰分≤13.50%   六、非金属建材     34 普通硅酸盐水泥 P.O 42.5袋装 抗压强度42.5MPa 35 普通硅酸盐水泥 P.O 42.5散装 抗压强度42.5MPa 36 浮法平板玻璃 4.8/5mm 厚度为4.8/5mm的无色透明玻璃   七、农产品(主要用于加工)     37 稻米 粳稻米 杂质≤0.25%,水分≤15.5% 38 小麦 国标三等 杂质≤1.0%,水分≤12.5% 39 玉米 黄玉米二等 杂质≤1.0%,水分≤14.0% 40 棉花(皮棉) 白棉三级 纤维长度≥28mm,白或乳白色 41 生猪 外三元 三种外国猪杂交的肉食猪 42 大豆 黄豆 杂质≤1.0%,水分≤13.0% 43 豆粕 粗蛋白含量≥43% 粗蛋白≥43%,水分≤13.0% 44 花生 油料花生米 杂质≤1.0%,水分≤9.0%   八、农业生产资料     45 尿素 小颗料 总氮≥46%,水分≤1.0% 46 复合肥 硫酸钾复合肥 氮磷钾含量45% 47 农药(草甘膦) 95%原药 草甘膦质量分数≥95%   九、林产品     48 天然橡胶 标准胶SCRWF 杂质含量≤0.05%,灰分≤0.5% 49 纸浆 漂白化学浆 亮度≥80%,黏度≥600cm³/g 50 瓦楞纸 高强 80-160g/m2  

iOS人脸识别Demo

*近用过了支付宝的人脸识别登录,作为一个技术人员应该保持对技术探索、追求的学习心态。这两天就搜集各方资料学习了一下,但好像走了弯路/(ㄒoㄒ)/~~!!!这篇笔记记录一下自己的学习。

1、体验分析
首先思考的应该是人脸识别登录的流程。本人*次体验到的人脸识别技术的应用当然是支付宝。

支付宝开启人脸登录流程:首先是账号密码登录 —-> 然后在app内根据提示完成信息采集 —-> 信息采集完成后下次登录时就可以使用该功能了!

然后又找到另一款带有人脸识别登录功能app应用,其开启流程:账号密码登录后 —-> 在相关功能模块调用相机,拍摄较清晰的人脸照片进行上传 —-> 之后就可以使用了!!!

分析其登录流程:*步都是要密码验证登录,第二步需要采集当前账号的所属人面部信息,然后才可使用该功能。(应该算是一种辅助登录手段,毕竟没有使用人脸注册账号。但是真的很好用,省去了输入密码或忘记密码的麻烦)

在移动端开发此功能,(密码登录直接略过)我们应该首先考虑的是信息采集时的面部信息。那么*个要解决的问题就是识别出人脸,其次将信息上传至后台与该账号关联。下次登录时,将扫描到的人脸图像上传至后台与存储的数据对比,返回登录结果。(因为未找到具体的相关资料,此分析目前仅是一个移动开发者的分析,如有漏洞下次更新)

2、移动端的人脸识别
根据之前的分析,我们需要在本地分析采集到的图像是否有人脸信息。根据查找的资料,有如下实现方法:1.苹果原生CoreImage.framework框架。2.OpenVC框架,该框架是一个跨平台框架,专注于做图像技术的处理。(更多介绍百度即可)3.AVFoundation框架,这是在使用CoreImage走了弯路时发现的。

(1)CoreImage.framework
我们先用该框架实现人脸识别。首先创建一个工程,导入 CoreImage.framework 库:

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

创建一个UIImageView,给其一张图片,我们直接用storyboard拖拽界面、设置坐标,并关联属性到控制器(步骤简单略过):

%title插图%num
此时要注意,ImageView的图片适应模式设置为scaleAspectFit,如果要将图片拉伸展示到ImageView的话,面部位置并不在计算到的坐标框内。

插入识别代码:

func detectFace(withImage image: UIImage) {
// 将图像转为CIImage,使用Core Image需要使用CIImage
guard let personCIImg = CIImage(image: image) else {
return
}
// 设置识别精度
let opts: [String: Any] = [CIDetectorAccuracy: CIDetectorAccuracyHigh]
// 初始化识别器
let detector = CIDetector(ofType: CIDetectorTypeFace, context: nil, options: opts)

let result: [CIFaceFeature] = (detector?.features(in: personCIImg, options: opts) as? [CIFaceFeature])!

if result.count > 0 {
for face in result {
let faceBox = UIView(frame: face.bounds)

// 画一个红框画出面部位置
faceBox.layer.borderWidth = 3
faceBox.layer.borderColor = UIColor.red.cgColor
faceBox.backgroundColor = UIColor.clear
// 添加红框到图片上
imgView.addSubview(faceBox)
print(“面部坐标——> %d “, faceBox.frame)

}
}
}
好了,代码看似很简单的:

#3行:从imgView变量中取出image并转为CIImage,因为使用Core Image时需要用CIImage。

#9行:初始化一个识别器,并将识别精度以字典参数给它。

#11行:调用识别器的识别方法,并保存一个 [CIFaceFeature] 类型的结果。

#13——#25行:从返回的结果中取出数据。点开 CIFaceFeature 类我们可以看到的它的属性值,bounds就是我们要的识别到的面部区域。

#17——#22行:将识别到的区域用红框显示出来。
接下来调用测试一下代码结果:

imgView.contentMode = .scaleAspectFit
self.detectFace(withImage: imgView.image!)

%title插图%num

运行结果看到红框出界了,并没有出现在预期的范围内,这是因为UIKit框架中使用的坐标与Core Image 的坐标不同造成,为此我们还需要将坐标转换。

%title插图%num

将转换代码加入会,代码如下:

func detectFace(withImage image: UIImage) {
// 将图像转为CIImage,使用Core Image需要使用CIImage
guard let personCIImg = CIImage(image: image) else {
return
}
// 设置识别精度
let opts: [String: Any] = [CIDetectorAccuracy: CIDetectorAccuracyHigh]
// 初始化识别器
let detector = CIDetector(ofType: CIDetectorTypeFace, context: nil, options: opts)

let result: [CIFaceFeature] = (detector?.features(in: personCIImg, options: opts) as? [CIFaceFeature])!

let CIImgSize = personCIImg.extent.size
var transform = CGAffineTransform(scaleX: 1, y: -1)
transform = transform.translatedBy(x: 0, y: -CIImgSize.height)

if result.count > 0 {
for face in result {

// Apply the transform to convert the coordinates
var faceViewBounds = face.bounds.applying(transform)

// Calculate the actual position and size of the rectangle in the image view
let viewSize = imgView.bounds.size
let scale = min(viewSize.width / CIImgSize.width,
viewSize.height / CIImgSize.height)
let offsetX = (viewSize.width – CIImgSize.width * scale) / 2
let offsetY = (viewSize.height – CIImgSize.height * scale) / 2

faceViewBounds = faceViewBounds.applying(CGAffineTransform(scaleX: scale, y: scale))
faceViewBounds.origin.x += offsetX
faceViewBounds.origin.y += offsetY

let faceBox = UIView(frame: faceViewBounds)

// 画一个红框画出面部位置
faceBox.layer.borderWidth = 3
faceBox.layer.borderColor = UIColor.red.cgColor
faceBox.backgroundColor = UIColor.clear
// 添加红框到图片上
imgView.addSubview(faceBox)

print(“面部坐标——> %d “, faceBox.frame)

if face.rightEyeClosed {
print(“右眼闭着”)
}
if face.leftEyeClosed {
print(“左眼闭着”)
}
if face.hasSmile {
print(“在笑”)
}
}
}
}
#45行——#53行还可以识别图像的动作,具体的可以到类中查看。

运行效果:

%title插图%num
*************************************************************************************************
到这里,我们已经可以识别出人脸信息,但是在使用时我们不能拿着“这么大”的照片去用,裁剪后使用效率应该会更高。剔除人脸外无用的信息。但是进行的并不是很顺利,因为裁剪区域的坐标和界面显示的红框坐标并不相同,无奈被卡到现在还并未解决。

此处被卡时间太长,暂且搁置,后续研究

*************************************************************************************************
到这我们仅仅完成了静态人物的面部识别,而调用摄像头后动态面部信息的捕捉也是我们要使用的技术问题。前面所说的走弯路就在这了,看到了CoreImage.framework 可以识别图像,又可以自定义拍照界面,所以沿着这条路走了下去,结果并没有走通。首先说自定义界面只是简单的自定义,并不能按照自己的UI设计搭建拍照界面。其二,动态识别数据流信息(抓取人像信息,而不是拍摄后识别)貌似也不可以!!!

还好,在解这些问题的时候发现AVFoundation框架使我们需要的。

(2)AVFoundation.framework
正在研究中。。。
注:记得在plist文件中添加权限声明(调用相机,麦克风,媒体库等都要添加对应的权限),否则会崩的

直接上代码再注释吧,网上系统的资料比较少,基本都是一些简单的代码,也不能直接拿过来用!

var session: AVCaptureSession?

var device: AVCaptureDevice?

var input: AVCaptureDeviceInput?

var output: AVCaptureMetadataOutput?

var preview: AVCaptureVideoPreviewLayer?
// 初始化相机
func setupCamera() {
//session
session = AVCaptureSession()
session?.sessionPreset = AVCaptureSessionPresetPhoto
session?.sessionPreset = AVCaptureSessionPreset1280x720

// device
device = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo)
// 设置为前置摄像头
let devices = AVCaptureDeviceDiscoverySession(deviceTypes: [AVCaptureDeviceType.builtInWideAngleCamera], mediaType: AVMediaTypeVideo, position: AVCaptureDevicePosition.front)
for device in (devices?.devices)! {
self.device = device
}

// input
do {
try input = AVCaptureDeviceInput(device: device)
} catch let error as NSError {
print(“error: \(error.localizedDescription)”)
}
if (session?.canAddInput(input))! {
session?.addInput(input)
}

// output // 人脸识别
output = AVCaptureMetadataOutput()
output?.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
if (session?.canAddOutput(output))! {
session?.addOutput(output)
}
output?.metadataObjectTypes = [AVMetadataObjectTypeFace]
// preview
preview = AVCaptureVideoPreviewLayer(session: session)
preview?.videoGravity = AVLayerVideoGravityResizeAspectFill
preview?.frame = CGRect(x: (self.view.frame.width-200)/2.0, y: 150, width: 200, height: 200)
preview?.cornerRadius = 100
preview?.borderColor = UIColor.gray.cgColor
preview?.borderWidth = 3
// preview?.frame = self.view.bounds
self.view.layer.insertSublayer(preview!, at: 0)

session?.startRunning()
}
#3行,#17——#24行:硬件设备声明和初始化,调用前置摄像头
#5行:input,输入流

#7行:output,输出流

#9行:preview,预览界面,可以设置为想要的扫描效果界面。

#54行:初始化完成后一定要启动session

注:此处有一个巨大的坑,在设置output输出流,添加扫描识别类型时,一定要先添加input输入流,否则崩掉,然后网上也找不到相关资料,这是自己一步步试出来的!!!

上边的初始化完成后,需要实现一个协议方法,该方法在扫描到有人脸时会持续返回数据:

// MARK: – AVCaptureMetadataOutputObjectsDelegate
func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [Any]!, from connection: AVCaptureConnection!) {
for item in metadataObjects {
if (item as! AVMetadataObject).type == AVMetadataObjectTypeFace {
let transform: AVMetadataObject = (preview?.transformedMetadataObject(for: item as? AVMetadataObject))!
DispatchQueue.global().async {
DispatchQueue.main.async {
self.showFaceImage(withFrame: transform.bounds)
}
}
}
}
}
/// 显示人脸位置视图
func showFaceImage(withFrame rect: CGRect) {
if isStartFaceRecognition {
isStartFaceRecognition = false
faceBoxView.frame = rect
self.faceBoxView.transform = CGAffineTransform(scaleX: 1.5, y: 1.5);
UIView.animate(withDuration: 0.3, animations: {
[weak self] in
self?.faceBoxView.alpha = 1.0
self?.faceBoxView.transform = CGAffineTransform(scaleX: 1.0, y: 1.0);
}) { (finished: Bool) in
UIView.animate(withDuration: 0.2, animations: {
[weak self] in
self?.faceBoxView.alpha = 0.0
}, completion: { (finished: Bool) in
self.isStartFaceRecognition = true
})
}
}
}
返回的 AVMetadataObject 类中可以获取到面部位置坐标,根据坐标信息添加一个可视化界面展示给用户识别区域。

%title插图%num

以上就是我们这一阶段完成的效果展示

字母识词

字母识词
**题目:**请输入星期几的*个字母来判断一下是星期几,如果*个字母一样,则继续判断第二个字母。
1
**程序分析:**这里用字典的形式直接将对照关系存好。
1
weekT={‘h’:’thursday’,
       ‘u’:’tuesday’}
weekS={‘a’:’saturday’,
       ‘u’:’sunday’}
week={‘t’:weekT,
      ‘s’:weekS,
      ‘m’:’monday’,
      ‘w’:’wensday’,
      ‘f’:’friday’}
a=week[str(input(‘请输入*位字母:’)).lower()]
if a==weekT or a==weekS:
    print(a[str(input(‘请输入第二位字母:’)).lower()])
else:
    print(a)

调用函数

调用函数
**题目:**练习函数调用。
1
def hello():
    print(‘Hello World!’)
def helloAgain():
    for i in range(2):
        hello()
if __name__==’__main__’:
    helloAgain()

设置输出颜色

设置输出颜色
**题目:**文本颜色设置。
class bcolors:
    HEADER = ‘\033[95m’
    OKBLUE = ‘\033[94m’
    OKGREEN = ‘\033[92m’
    WARNING = ‘\033[93m’
    FAIL = ‘\033[91m’
    ENDC = ‘\033[0m’
    BOLD = ‘\033[1m’
    UNDERLINE = ‘\033[4m’
print(bcolors.WARNING + “警告的颜色字体?” + bcolors.ENDC)

算素数

算素数
**题目:**求100之内的素数。
1
**程序分析:**用else执行for循环的*励代码(如果for是正常完结,非break)。
1
lo=int(input(‘下限:’))
hi=int(input(‘上限:’))
for i in range(lo,hi+1):
    if i > 1:
        for j in range(2,i):
            if (i % j) == 0:
                break
        else:
            print(i)

iOS 代码重签名

代码重签名首先还是要了解iOS应用的签名机制。原理就是使用iOS免费的开发证书欺骗手机通过签名验证(告诉手机是我们自己的开发调试应用)。被重签名的应用是越狱 ipa 包或砸壳后的安装包。

1、手动重签名
1.1 查看xxx.app签名信息
解压安装包,Payload 文件夹下找到 xxx.app 文件,查看签名信息。

终端执行命令:
$ codesign -vv -d #.app路径#

%title插图%num
砸壳后的app是没有签名信息的,这样的app我们才能给其重签名,否则的话需要使用工具砸壳。

1.2 查看xxx.app 是否加密
查看安装包是否加密,进入 xxx.app 文件下

%title插图%num

终端执行命令:
$ otool -l WeChat | grep crypt

%title插图%num
1.3 查看本机所有证书文件
查找本机上进行真机调试的证书文件,并记录下与 Xcode 上进行真机调试时相同的证书。

终端执行命令:
$ security find-identity -v -p codesigning

1.4 删除xxx.app 包内影响签名的文件
删除插件PlugIns文件夹里面的内容!
删除Watch文件

%title插图%num

%title插图%num

1.5 重签名动态库
进入到 xxx.app/Frameworks 下,分别对其中包含的动态库进行重签名。所有证书是1.3中查找到的真机调试证书(必须与Xcode中使用的一致)。

执行重签名命令
$ codesign -fs #“证书”# #需要签名的文件#

%title插图%num
此处是四个动态库,不同应用安装包可能包含不同的framework动态库或不存在该文件。

1.6 给可执行文件执行权限
可执行文件就是 xxx.app 包内的 Mach-O 文件。一般与项目的 ipa 包同名。

添加可执行权限命令
$ chmod +x #文件路径#

%title插图%num
1.7 添加描述文件
新建一个iOS工程,真机编译后再Finder中打开 ipa 包,找到embedded.mobileprovision 文件,将其拷贝到重签名应用的 xxx.app 文件内。
将下图中的描述文件拷贝到重签名应用的 app 包内:

%title插图%num

1.8 修改 Bundle identifier
修改重签名应用 Info.plist 文件中 Bundle identifier 的值与新建工程的Bundle identifier 的值一致。

1.9 生成 plist 权限文件
新建一个 plist 文件(此处在Xcode中新建,命名为 tmp.plist)。
查看描述文件,将权限信息拷贝到新建的 tmp.plist 文件中。

%title插图%num

将 tmp.plist 文件拷贝到 xxx.app 的同级目录下(如下):

%title插图%num

1.10 签名整个APP
进入 xxx.app 所在目录,执行签名命令。

%title插图%num

执行命令:
$ codesign -fs #“证书”# –no-strict –entitlements=#plist文件# #xxx.app#

1.11 打包成 .ipa 包
可以使用终端命令打包,也可以压缩成 zip 包修改后缀名为 .ipa

%title插图%num

终端打包命令:
$ zip -ry WeChat.ipa Payload

%title插图%num

1.12 安装重签名应用
使用 Xcode 安装打包好的安装包。
菜单栏:Window ——> Devices and Simulators

%title插图%num

真机验证⬇️⬇️

%title插图%num

2、利用Xcode重签名

利用Xcode对安装包重签名的原理与手动签名一样,但有些步骤 Xcode 替我们完成,简化了手动签名的步骤。具体操作如下:
同样以微信为例,安装包文件名 WeChat.app

新建工程 new.project,真机编译;
Finder 打开app文件,WeChat.app替换原来的 new.app 文件;
修改WeChat.app 文件中 Info.plist —> Bundle identifier 的值;
重签名 WeChat.app 文件中 Frameworks 中的静态文件(参考 1.5);
设置 Mach-O 文件(WeChat)的可执行权限(参考 1.6);
*后编译运行至真机。

3、脚本自动重签名
脚本自动重签名,原理同上。将各步骤使用脚本文件代替执行。
shell 重签名脚本

3.1 直接添加脚本
shell 重签名脚本

新建工程 KYCodeSignature.project;
KYCodeSignature.project根目录下新建文件夹“APP”,将重签名的安装包 xxx.ipa 放到该文件夹夹下;

%title插图%num

在 TARGETS —> Build Phases —> Run Script 中添加脚本命令(如下图);

%title插图%num

编译运行到手机。
3.1 添加脚本文件路径
新建工程 new.project;
给脚本文件添加可执行权限 chmod +x XcodeApp.sh;
在 TARGETS —> Build Phases —> Run Script 中添加脚本文件路径;

%title插图%num

编译运行到手机。

IOS实现重签名实操

重签是把已发布/未发布的包重新签名为自己的证书和签名,关键就是替换ipa内的证书和描述文件。手动签名可以研读这篇文章—-IOS重签名原理

主要通过codesign命令完成。值得说明的是:我们要想对ipa进行重签名,那么这个ipa包一定是未被加密过的,如何查看是否被加密过?使用如下命令:

%title插图%num

因为重签名是替换原有的签名(不了解的可以研读这篇文章:https://blog.csdn.net/lwb102063/article/details/110661830),所以我么这里需要准备如下文件,来替换原来的签名:

1、 ipa文件(App Store下载的请自行”砸壳”)

2、 .mobileprovision文件

3、 .p12文件

4、 从iOS App Signer的 Github 仓库 上将其clone下来

使用iOS App Signer进行重签名还是比较方便的,具体参看文章iOS ipa重签名工具 – iOS App Signer,只要一步一步来就可以签名成功,签名后打包成ipa,我们可以使用iFunBox或者Apple Configuration 2进行安装,不清楚的可以看下这篇文章:https://blog.csdn.net/lwb102063/article/details/110739441

这里有一些注意点需要说明:
如果我们使用的是在Apple服务器购买的开发者账号,那么重签名选择的就是下载下来的mobileprovision文件,而且只需要把我们的bundleId改一致就可以了,这个没问题。但是如果我们并没有花钱买开发者账号,那么我们用的mobileprovision文件就是临时的,怎么获取这个呢?

我们只需要新建一个工程,编译后生成app,把里面的embedd.mobileprovision拿出来用就可以了(注意别过期),拿出来以后使用iOS App Signer进行签名,打包ipa进行安装。

如果不出意外,安装结束后会提示失败,经过研究,发现报以下错误:

‘xxx ‘ is authorized by a free provisioning profile, but apps validated by those are not allowed to be installed from this source.
原因如下:

xcode升级到7.3,iOS更新到9.3后,生成的ipa文件是不可通过iTunes安装的,我们只能选择通过xcode进行安装。

即:打开Xcode,连接真机设备,然后window/device,选择要安装的ipa点击安装即可!另外一种就是用Xcode打开wex5中生成的Xcode项目文件,然后连接真机设备,编译运行即可!