前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >xcode自动签名_配置实用工具也不能移除

xcode自动签名_配置实用工具也不能移除

作者头像
全栈程序员站长
发布2022-11-10 13:21:20
3830
发布2022-11-10 13:21:20
举报
文章被收录于专栏:全栈程序员必看

大家好,又见面了,我是你们的朋友全栈君。

之前看到过一篇无证做真机测试的文章,很受用~

不过因为当时手贱,把默认的 “iPhone Developer” 签名 改成了自己的名字

直接导致后来的每一个 XCode 项目,我想在真机上面看效果都要重新设置签名配置。

当然,是可以按照那篇文章把这个名字再修改回来,不过我当时懒,就一直这么弄着了

如今经过了那么长的时间,我电脑里面存储的很多工程都沿用了这蛋疼的配置

所以一时半会儿要修改过来,也是一件很费神的事情。

而且,最近我们团队有通过 Versions 做项目管理进行协作开发~

好不容易解决了多人提交冲突的问题,但是还是存在一些令人不满意的地方,

那就是签名的问题,我的另一个伙计真机测试的话是用的是他自己合法的签名

导致我更新或者他更新了以后,各自的签名被弄坏得重复的做一些签名的设置~

还有祸不单行,XCode 修改签名的时候有时修改不动,要关了再打开才能改的动,是个 bug~

自从上次观察过 project.pbxproj 文件以后,我就发现签名的配置数据也是以明文的方式保存在这个里面的~

那么,完全有可能用 Java 写一个文本处理工具将签名配置那一段做文本替换,置换为我常用的签名配置。

开始我想的使用 Java 的正则表达式,但是一路都不成功。

主要还是因为我对正则表达式的适用范围了解地还不够深刻~

正则表达式擅长于做文本的行内处理,那种跨多行文本的情况用正则是不能取得很好效果的

主要还是因为 Java 正则表达式的通配符 “.” 只能匹配除 \n 以外的所有其他字符 所致~

后来我看到签名配置那段的开头和结尾都做了固定写法的注释,

这样的话我便抛弃了正则表达式的解决方案,直接用 String.indexOfString() 来做实现了

接下来基本上就是很简单的事情了,几行代码便解决了所有问题,下面上代码:

RepairWonderPipe.java

代码语言:javascript
复制
package org.bruce.xcproj.codesign.repair;
import java.io.File;
import java.io.InputStream;
/**
* @author Bruce Yang
* 仅限于处理 WonderPipe 工程(因为会将工程的某些设置抹掉)~
*/
public class RepairWonderPipe {
public static final String PROJECT_DIR = "/Users/user/SVN/WonderPipe";
/**
* 检查传入的文件目录是否为项目文件夹~
* @param dirProject
* @return
*/
public static boolean isProjectDir(String strProjectDir) {
File dirProject = new File(strProjectDir);
if(dirProject.exists() && dirProject.isDirectory()) {
for(File fileItem : dirProject.listFiles()) {
if(fileItem.getName().endsWith(".xcodeproj")) {
return true;
}
}
}
System.out.println("不是项目文件夹~");
return false;
}
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
// 1.检查是否为项目文件夹~
if(!isProjectDir(PROJECT_DIR)) {
System.err.println("不是 XCode 工程文件的根目录~");
return;
}
// 2.还是不确定能不能取到包下面的文件~
StringBuffer sbPath = new StringBuffer(PROJECT_DIR);
sbPath.append(File.separator).append("WonderPipe.xcodeproj");
sbPath.append(File.separator).append("project.pbxproj");
String strPath = sbPath.toString();
File f = new File(strPath);
if(!f.exists()) {
System.err.println("文件不存在: " + strPath);
return;
}
// 3.将文件内容读成字符串~
String fContents = StringFileBridge.file2String(f, "utf-8");
//		System.out.println(fContents);
// 4.处理~
String strBegin = "/* Begin XCBuildConfiguration section */";
int iBeginIndex = fContents.indexOf(strBegin);
String strEnd = "/* End XCBuildConfiguration section */";
int iEndIndex = fContents.indexOf(strEnd) + strEnd.length();
String strToBeReplaced = fContents.substring(iBeginIndex, iEndIndex);
//		System.err.println(strToBeReplaced);
String strResPath = "/org/bruce/xcproj/codesign/repair/XCBuildConfigurationBakup.txt";
InputStream is = RepairWonderPipe.class.getResourceAsStream(strResPath);
String strCfgTemplate = StringFileBridge.stream2String(is, "utf-8");
//		System.err.println(strCfgTemplate);
String strOutput = fContents.replace(strToBeReplaced, strCfgTemplate);
// 5.将处理完毕的文件写回原文件~
StringFileBridge.string2File(strOutput, f);
//		test0();
//		test1();
//		test2();
}
/**
* 特殊字符 * 的匹配,前面加双反斜杠~
*/
public static void test0() {
String str = "* sdfsdfsd *";
String reg = "\\* sdfsdfsd \\*";
if(str.matches(reg)) {
System.out.println("no!");
}
}
public static void test1() {
String str = "/哈哈/";
String reg = "/.*/";
if(str.matches(reg)) {
System.out.println("哈哈");
}
}
/**
* 结论:正则表达式不适合用于处理多行的文本~
*/
public static void test2() {
//		String str = "123123\n/* 嘻 */\n1231231";
String str = "\n/* 嘻 */\n";
String reg = "[.\n]*/\\* 嘻 \\*/[.\n]*";
if(str.matches(reg)) {
System.out.println("嘻");
}
}
}

StringFileBridge.java

代码语言:javascript
复制
package org.bruce.xcproj.codesign.repair;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.io.Reader;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
/**
* 字符串与文件相互转换工具
* @author leizhimin 2009-7-14 15:54:18
*/
public class StringFileBridge {
/**
* 读取文件为一个内存字符串,保持文件原有的换行格式
* @param file 文件对象
* @param charset 文件字符集编码
* @return 文件内容的字符串
*/
public static String file2String(File file, String charset) {
StringBuffer sb = new StringBuffer();
try {
FileInputStream fis = new FileInputStream(file);
InputStreamReader isr = new InputStreamReader(fis, charset);
BufferedReader br = new BufferedReader(isr);
LineNumberReader reader = new LineNumberReader(br);
String line;
while ((line = reader.readLine()) != null) {
sb.append(line).append(System.getProperty("line.separator"));
}
reader.close();
} catch (Exception e) {
e.printStackTrace();
}
return sb.toString();
}
/**
* @author Bruce Yang
* 该方法用于配合上面的方法使用。
* @param unicodeStr
* @return
*/
public static String changeEncode(String unicodeStr, String charset) {
String utf8Str = null;
try {
utf8Str = new String(unicodeStr.getBytes(charset));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return utf8Str;
}
/**
* 将字符串存储为一个文件,当文件不存在时候,自动创建该文件,当文件已存在时候,重写文件的内容,特定情况下,还与操作系统的权限有关。
* @param text 字符串
* @param distFile 存储的目标文件
* @return 当存储正确无误时返回true,否则返回false
*/
public static boolean string2File(String text, File distFile) {
if (!distFile.getParentFile().exists()) {
distFile.getParentFile().mkdirs();
}
BufferedReader br = null;
BufferedWriter bw = null;
boolean flag = true;
try {
br = new BufferedReader(new StringReader(text));
bw = new BufferedWriter(new FileWriter(distFile));
char buf[] = new char[1024 * 64]; // 字符缓冲区
int len;
while ((len = br.read(buf)) != -1) {
bw.write(buf, 0, len);
}
bw.flush();
br.close();
bw.close();
} catch (IOException e) {
flag = false;
e.printStackTrace();
System.out.println("将字符串写入文件发生异常!");
}
return flag;
}
/**
* 文件转换为字符串
* @param in 		字节流
* @param charset 	文件的字符集
* @return 			文件内容
*/
public static String stream2String(InputStream in, String charset) {
StringBuffer sb = new StringBuffer();
try {
Reader reader = new InputStreamReader(in, charset);
int length = 0;
for (char[] c = new char[1024]; (length = reader.read(c)) != -1;) {
sb.append(c, 0, length);
}
reader.close();
} catch (Exception e) {
e.printStackTrace();
}
return sb.toString();
}
/**
* @param args
*/
public static void main(String[] args) {
String x = file2String(new File("/Users/user/Desktop/123.java"), "GBK");
System.out.println(x);
boolean b = string2File(x, new File("/Users/user/Desktop/1234.java"));
System.out.println(b);
}
}

XCBuildConfigurationBakup.txt (PS: 和前面的两个类放在同一个 package 下面~)

代码语言:javascript
复制
/* Begin XCBuildConfiguration section */
BAAEAE4815A89BC600FF66D7 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
CODE_SIGN_ENTITLEMENTS = "";
CODE_SIGN_IDENTITY = "";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
DEBUG,
"COCOS2D_DEBUG=1",
);
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
GCC_VERSION = com.apple.compilers.llvmgcc42;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 4.3;
"PROVISIONING_PROFILE[sdk=iphoneos*]" = "";
SDKROOT = iphoneos;
};
name = Debug;
};
BAAEAE4915A89BC600FF66D7 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
CODE_SIGN_ENTITLEMENTS = "";
CODE_SIGN_IDENTITY = "";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_PREPROCESSOR_DEFINITIONS = NDEBUG;
GCC_VERSION = com.apple.compilers.llvmgcc42;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 4.3;
OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1";
"PROVISIONING_PROFILE[sdk=iphoneos*]" = "";
SDKROOT = iphoneos;
};
name = Release;
};
BAAEAE4B15A89BC600FF66D7 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = YES;
CODE_SIGN_ENTITLEMENTS = Entitlements.plist;
CODE_SIGN_IDENTITY = yang3wei;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = yang3wei;
COPY_PHASE_STRIP = NO;
GCC_DYNAMIC_NO_PIC = NO;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = WonderPipe/Prefix.pch;
"GCC_THUMB_SUPPORT[arch=armv6]" = "";
GCC_VERSION = com.apple.compilers.llvmgcc42;
INFOPLIST_FILE = WonderPipe/Resources/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 4.3;
OTHER_LDFLAGS = "-lz";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE = "";
"PROVISIONING_PROFILE[sdk=iphoneos*]" = "";
TARGETED_DEVICE_FAMILY = "1,2";
USER_HEADER_SEARCH_PATHS = "\"WonderPipe/libs\"";
WRAPPER_EXTENSION = app;
};
name = Debug;
};
BAAEAE4C15A89BC600FF66D7 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = YES;
CODE_SIGN_ENTITLEMENTS = Entitlements.plist;
CODE_SIGN_IDENTITY = yang3wei;
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = yang3wei;
COPY_PHASE_STRIP = YES;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = WonderPipe/Prefix.pch;
"GCC_THUMB_SUPPORT[arch=armv6]" = "";
GCC_VERSION = com.apple.compilers.llvmgcc42;
INFOPLIST_FILE = WonderPipe/Resources/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 4.3;
OTHER_LDFLAGS = "-lz";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE = "";
"PROVISIONING_PROFILE[sdk=iphoneos*]" = "";
TARGETED_DEVICE_FAMILY = "1,2";
USER_HEADER_SEARCH_PATHS = "\"WonderPipe/libs\"";
VALIDATE_PRODUCT = YES;
WRAPPER_EXTENSION = app;
};
name = Release;
};
/* End XCBuildConfiguration section */

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/188973.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022年9月27日 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
项目管理
CODING 项目管理(CODING Project Management,CODING-PM)工具包含迭代管理、需求管理、任务管理、缺陷管理、文件/wiki 等功能,适用于研发团队进行项目管理或敏捷开发实践。结合敏捷研发理念,帮助您对产品进行迭代规划,让每个迭代中的需求、任务、缺陷无障碍沟通流转, 让项目开发过程风险可控,达到可持续性快速迭代。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档