如何防止自定义init方法泄露Xcode中的绝对源路径?

klo*_*pps 4 xcode initialization build-settings ipa swift

对于一个新的Xcode项目,我以这种方式添加了一个带有自定义init方法的新类:

import Cocoa

class NewClass: NSControl {

    override init(frame: CGRect) {
        super.init(frame: frame)
    }

    required init(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,如果我构建并归档项目,则源文件的绝对路径将显示在二进制文件中:

/Users/my_username/my_path_to_xcode_projects/new_project/NewClass.swift
Run Code Online (Sandbox Code Playgroud)

我打算通过互联网分发我的最终项目.如何防止Xcode向其他人透露我的目录布局?我从类似问题的答案中了解到,在Xcode的"Build Settings"中,应该将"Deployment Prostprocessing"设置为Yes,以便从二进制文件中删除符号,但这似乎不适用于我的情况.

Sil*_*ger 6

如果仔细观察签名fatalError:

@noreturn public func fatalError(
    @autoclosure message: () -> String = default, 
    file: StaticString = #file, line: UInt = #line)
Run Code Online (Sandbox Code Playgroud)

您可以看到#file#line默认参数.这些在编译时进行评估,并解析为当前文件和行.

要不使用默认参数,您可以自己提供:

fatalError("Something went wrong", file: "", line: 0)
Run Code Online (Sandbox Code Playgroud)

在发布配置上编译时,路径不包含在二进制文件中.

如果#file在标准库中搜索,则可以找到其他4个实例,其中两个实例,assert并且assertionFailure不会包含在发布版本中.剩下的2个是preconditionpreconditionFailure.

解决方法

如果我们添加DEBUG/ RELEASE符号: 在此输入图像描述

我们可以对fatalError不使用#file发布版本上的预处理器语句的模拟等函数进行条件编译:

#if RELEASE
@inline(__always) @noreturn func fatalError(@autoclosure message: () -> String = "") {
    Swift.fatalError(message, file: "", line: 0)
}

@inline(__always) func preconditionAlt(@autoclosure condition: () -> Bool, @autoclosure _ message: () -> String = "") {
    Swift.precondition(condition, message, file: "", line: 0)
}

@inline(__always) @noreturn func preconditionFailureAlt(@autoclosure message: () -> String = "") {
    Swift.preconditionFailure(message, file: "", line: 0)
}
#else
@inline(__always) func preconditionAlt(@autoclosure condition: () -> Bool, @autoclosure _ message: () -> String = "", file: StaticString = #file, line: UInt = #line) {
    Swift.precondition(condition, message, file: file, line: line)
}

@inline(__always) @noreturn func preconditionFailureAlt(@autoclosure message: () -> String = "") {
    Swift.preconditionFailure(message, file: file, line: line)
}
#endif
Run Code Online (Sandbox Code Playgroud)

您调用任何这些函数的所有实例现在都使用自定义实现.这样,您在调试时仍然可以获取文件和行信息,但是防止它出现在产品中.你必须改变的每个实例precondition[Failure]precondition[Failure]Alt虽然斯威夫特不能明确地推断出功能,否则.您可以按Shift- Alt- Cmd- F在整个项目中搜索和替换

注意

如果第三方框架使用这些功能并在您的机器上进行编译,那么该路径显然将包含在框架产品中.要防止这种情况,您必须使用预编译版本或使用模拟自行编译.

如果任何其他自我声明或第三方功能使用#file,你显然也必须改变它,但它并不常见.

文件结构可能还有其他可能泄露的可能性,我不知道.