总结iOS Protobuf 应用在项目中(批量执行protoc命令)

本文介绍了如何在iOS项目中使用Protobuf,并提供了一个shell脚本`protocol.sh`,该脚本批量执行protoc命令,将protobuf协议文件转换为Objective-C代码,并自动管理Xcode项目中的文件。通过这个过程,可以方便地整合和更新protobuf定义到项目中。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • 项目目录:

公司项目目录

  • protocol_def、userPreference_def 是protobuf协议文件
  • start可执行文件源码:

#!/bin/sh
#
# An example hook script to prepare a packed repository for use over
# dumb transports.
#
# To enable this hook, rename this file to "post-update".

protoPPath=`dirname $0`
echo ${protoPPath}
cd ${protoPPath}
ruby protocol.rb
 

  • protocol.rb 源码:

require 'xcodeproj'
system 'echo $(pwd)'
project_path = File.join(File.dirname(__FILE__), "../KLProtobufs.xcodeproj")
project = Xcodeproj::Project.open(project_path)
target = project.targets.first
group = project.main_group.find_subpath(File.join('KLProtobufs', 'protoBufs'), true)
group.set_source_tree('<group>')
group.set_path('protoBufs')

def removeBuildPhaseFilesRecursively(aTarget, aGroup)
    aGroup.files.each do |file|
        if file.real_path.to_s.end_with?(".m", ".mm", ".cpp") then
            aTarget.source_build_phase.remove_file_reference(file)
        elsif file.real_path.to_s.end_with?(".plist") then
            aTarget.resources_build_phase.remove_file_reference(file)
        end
    end
    
    aGroup.groups.each do |group|
        removeBuildPhaseFilesRecursively(aTarget, group)
    end
end

if !group.empty? then
    removeBuildPhaseFilesRecursively(target, group)
    group.clear()
    group.remove_from_project
end

group = project.main_group.find_subpath(File.join('KLProtobufs', 'protoBufs'), true)
group.set_source_tree('<group>')
group.set_path('protoBufs')

def createProtoFile(project)
    system 'sh protocol.sh'
end

createProtoFile(project)

def addFilesToGroup(project, aTarget, aGroup)
    Dir.foreach(aGroup.real_path) do |entry|
        filePath = File.join(aGroup.real_path, entry)
        # 过滤目录和.DS_Store文件
        if !File.directory?(filePath) && entry != ".DS_Store" && entry != ".md" && filePath.to_s.end_with?(".m", ".mm", ".h") then
            # 特殊逻辑
            # 向group中增加文件引用
            fileReference = aGroup.new_reference(filePath)
            # 如果不是头文件则继续增加到Build Phase中,PB文件需要加编译标志
            if filePath.to_s.end_with?("pbobjc.m", "pbobjc.mm") then
                aTarget.source_build_phase.add_file_reference(fileReference, true)
            elsif filePath.to_s.end_with?(".m", ".mm", ".cpp") then
                aTarget.source_build_phase.add_file_reference(fileReference, true)
            elsif filePath.to_s.end_with?(".plist") then
                aTarget.resources_build_phase.add_file_reference(fileReference, true)
            end
            # 目录情况下, 递归添加
        elsif File.directory?(filePath) && entry != '.' && entry != '..' then
            hierarchy_path = aGroup.hierarchy_path[1, aGroup.hierarchy_path.length]
            subGroup = project.main_group.find_subpath(hierarchy_path + '/' + entry, true)
            subGroup.set_source_tree(aGroup.source_tree)
            subGroup.set_path(aGroup.real_path + entry)
            addFilesToGroup(project, aTarget, subGroup)
        end
    end
end

addFilesToGroup(project, target, group)

project.save
 

  • protocol.sh 源码: 

#!/bin/sh
protoFPath="$(pwd)/protoBufs"
rm -rf protoBufs
mkdir protoBufs

cd protocol_def/
protoc *.proto protocols/shared/*.proto --proto_path="." --objc_out="../protoBufs"
function scandir() {
    local cur_dir parent_dir workdir
    workdir=$1
    cd ${workdir}
    if [ ${workdir} = "/" ]
    then
        cur_dir=""
    else
        cur_dir=$(pwd)
    fi
    for dirlist in $(ls ${cur_dir})
    do
        if test -d ${dirlist};then
            cd ${dirlist}
            sed -i '' -e 's/protocols\/shared\///g' *
            mv ${cur_dir}/${dirlist}/*.m *.h ${protoFPath}
            scandir ${cur_dir}/${dirlist}
            cd ..
        elif test -f ${dirlist}; then
            sed -i '' -e 's/protocols\/shared\///g' ${dirlist}
        fi
    done
}
for dirlist in ${protoFPath}; do
    if test -d ${dirlist};then
        scandir ${dirlist}
    fi
done

cd ../userPreference_def/
protoc *.proto share/*.proto --proto_path="." --objc_out="../protoBufs"
function scandir1() {
    local cur_dir parent_dir workdir
    workdir=$1
    cd ${workdir}
    if [ ${workdir} = "/" ]
    then
        cur_dir=""
    else
        cur_dir=$(pwd)
    fi
    for dirlist in $(ls ${cur_dir})
    do
        if test -d ${dirlist};then
            cd ${dirlist}
            sed -i '' -e 's/share\///g' *
            mv ${cur_dir}/${dirlist}/*.m *.h ${protoFPath}
            scandir1 ${cur_dir}/${dirlist}
            cd ..
        elif test -f ${dirlist}; then
            sed -i '' -e 's/share\///g' ${dirlist}
        fi
    done
}
for dirlist in ${protoFPath}; do
    if test -d ${dirlist};then
        scandir1 ${dirlist}
    fi
done

protoBufs目录就是执行start之后生成的,里面存着变异好的oc文件(就是在项目中可以实际用到的) 

好了代码都贴出来了,及时看不懂的复制粘贴也应该知道有些地方是需要替换成自己项目中的目录和路径的吧~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值