|
|
|
Protocol Buffers - Google's data interchange format
|
|
|
|
===================================================
|
|
|
|
|
|
|
|
Copyright 2008 Google Inc.
|
|
|
|
|
|
|
|
This directory contains the Objective C Protocol Buffers runtime library.
|
|
|
|
|
|
|
|
Requirements
|
|
|
|
------------
|
|
|
|
|
|
|
|
The Objective C implementation requires:
|
|
|
|
|
|
|
|
- Objective C 2.0 Runtime (32bit & 64bit iOS, 64bit OS X).
|
|
|
|
- Xcode 13.3.1 (or later).
|
|
|
|
- The library code does *not* use ARC (for performance reasons), but it all can
|
|
|
|
be called from ARC code.
|
|
|
|
|
|
|
|
Installation
|
|
|
|
------------
|
|
|
|
|
|
|
|
The distribution pulled from github includes the sources for both the
|
|
|
|
compiler (protoc) and the runtime (this directory). After cloning the distribution
|
|
|
|
and needed submodules ([see the src directory's README](../src/README.md)),
|
|
|
|
to build the compiler and run the runtime tests, you can use:
|
|
|
|
|
|
|
|
$ objectivec/DevTools/full_mac_build.sh
|
|
|
|
|
|
|
|
This will generate the `protoc` binary.
|
|
|
|
|
|
|
|
Building
|
|
|
|
--------
|
|
|
|
|
|
|
|
There are two ways to include the Runtime sources in your project:
|
|
|
|
|
|
|
|
Add `objectivec/*.h`, `objectivec/google/protobuf/*.pbobjc.h`, and
|
|
|
|
`objectivec/GPBProtocolBuffers.m` to your project.
|
|
|
|
|
|
|
|
*or*
|
|
|
|
|
|
|
|
Add `objectivec/*.h`, `objectivec/google/protobuf/*.pbobjc.h`,
|
|
|
|
`objectivec/google/protobuf/*.pbobjc.m`, and `objectivec/*.m` except for
|
|
|
|
`objectivec/GPBProtocolBuffers.m` to your project.
|
|
|
|
|
|
|
|
|
|
|
|
If the target is using ARC, remember to turn off ARC (`-fno-objc-arc`) for the
|
|
|
|
`.m` files.
|
|
|
|
|
|
|
|
The files generated by `protoc` for the `*.proto` files (`*.pbobjc.h` and
|
|
|
|
`*.pbobjc.m`) are then also added to the target.
|
|
|
|
|
|
|
|
Usage
|
|
|
|
-----
|
|
|
|
|
|
|
|
The objects generated for messages should work like any other Objective C
|
|
|
|
object. They are mutable objects, but if you don't change them, they are safe
|
|
|
|
to share between threads (similar to passing an NSMutableDictionary between
|
|
|
|
threads/queues; as long as no one mutates it, things are fine).
|
|
|
|
|
|
|
|
There are a few behaviors worth calling out:
|
|
|
|
|
|
|
|
A property that is type NSString\* will never return nil. If the value is
|
|
|
|
unset, it will return an empty string (@""). This is inpart to align things
|
|
|
|
with the Protocol Buffers spec which says the default for strings is an empty
|
|
|
|
string, but also so you can always safely pass them to isEqual:/compare:, etc.
|
|
|
|
and have deterministic results.
|
|
|
|
|
|
|
|
A property that is type NSData\* also won't return nil, it will return an empty
|
|
|
|
data ([NSData data]). The reasoning is the same as for NSString not returning
|
|
|
|
nil.
|
|
|
|
|
|
|
|
A property that is another GPBMessage class also will not return nil. If the
|
|
|
|
field wasn't already set, you will get a instance of the correct class. This
|
|
|
|
instance will be a temporary instance unless you mutate it, at which point it
|
|
|
|
will be attached to its parent object. We call this pattern *autocreators*.
|
|
|
|
Similar to NSString and NSData properties it makes things a little safer when
|
|
|
|
using them with isEqual:/etc.; but more importantly, this allows you to write
|
|
|
|
code that uses Objective C's property dot notation to walk into nested objects
|
|
|
|
and access and/or assign things without having to check that they are not nil
|
|
|
|
and create them each step along the way. You can write this:
|
|
|
|
|
|
|
|
```
|
|
|
|
- (void)updateRecord:(MyMessage *)msg {
|
|
|
|
...
|
|
|
|
// Note: You don't have to check subMessage and otherMessage for nil and
|
|
|
|
// alloc/init/assign them back along the way.
|
|
|
|
msg.subMessage.otherMessage.lastName = @"Smith";
|
|
|
|
...
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
If you want to check if a GPBMessage property is present, there is always as
|
|
|
|
`has\[NAME\]` property to go with the main property to check if it is set.
|
|
|
|
|
|
|
|
A property that is of an Array or Dictionary type also provides *autocreator*
|
|
|
|
behavior and will never return nil. This provides all the same benefits you
|
|
|
|
see for the message properties. Again, you can write:
|
|
|
|
|
|
|
|
```
|
|
|
|
- (void)updateRecord:(MyMessage *)msg {
|
|
|
|
...
|
|
|
|
// Note: Just like above, you don't have to check subMessage and otherMessage
|
|
|
|
// for nil and alloc/init/assign them back along the way. You also don't have
|
|
|
|
// to create the siblingsArray, you can safely just append to it.
|
|
|
|
[msg.subMessage.otherMessage.siblingsArray addObject:@"Pat"];
|
|
|
|
...
|
|
|
|
}
|
|
|
|
```
|
|
|
|
|
|
|
|
If you are inspecting a message you got from some other place (server, disk,
|
|
|
|
etc), you may want to check if the Array or Dictionary has entries without
|
|
|
|
causing it to be created for you. For this, there is always a `\[NAME\]_Count`
|
|
|
|
property also provided that can return zero or the real count, but won't trigger
|
|
|
|
the creation.
|
|
|
|
|
|
|
|
All message fields *always* have a value when accessed. For primitive type
|
|
|
|
fields (ints, floats, bools, enum) there the concept of *presence*, that allows
|
|
|
|
you to tell the difference between when the field is the *default* value because
|
|
|
|
it *was not* set and when it *was* set, but *explicitly* to the *default*
|
|
|
|
value for the field. For fields with that do support *presence*, you can test
|
|
|
|
if the value was *explicitly* set via the `has\[NAME\]` property. If the value
|
|
|
|
has been set, and you want to clear it, you can set the `has\[NAME\]` to `NO`.
|
|
|
|
|
|
|
|
The Objective C classes/enums can be used from Swift code.
|
|
|
|
|
|
|
|
Objective C Generator Proto File Options
|
|
|
|
----------------------------------------
|
|
|
|
|
|
|
|
**objc_class_prefix=\<prefix\>** (no default)
|
|
|
|
|
|
|
|
This options allow you to provide a custom prefix for all the symbols generated
|
|
|
|
from a proto file (classes (from message), enums, the Root for extension
|
|
|
|
support).
|
|
|
|
|
|
|
|
If not set, the generation options `package_to_prefix_mappings_path` and
|
|
|
|
`use_package_as_prefix` (documented below) controls what is used instead. Since
|
|
|
|
Objective C uses a global namespace for all of its classes, there can be collisions.
|
|
|
|
`use_package_as_prefix=yes` should avoid collisions since proto package are used to
|
|
|
|
scope/name things in other languages, but this option can be used to get shorter
|
|
|
|
names instead. Convention is to base the explicit prefix on the proto package.
|
|
|
|
|
|
|
|
Objective C Generator `protoc` Options
|
|
|
|
--------------------------------------
|
|
|
|
|
|
|
|
When generating Objective C code, `protoc` supports a `--objc_opt` argument; the
|
|
|
|
argument is comma-delimited name/value pairs (_key=value,key2=value2_). The
|
|
|
|
_keys_ are used to change the behavior during generation. The currently
|
|
|
|
supported keys are:
|
|
|
|
|
|
|
|
* `generate_for_named_framework`: The `value` used for this key will be used
|
|
|
|
when generating the `#import` statements in the generated code. Instead
|
|
|
|
of being plain `#import "some/path/file.pbobjc.h"` lines, they will be
|
|
|
|
framework based, i.e. - `#import <VALUE/file.pbobjc.h>`.
|
|
|
|
|
|
|
|
_NOTE:_ If this is used with `named_framework_to_proto_path_mappings_path`,
|
|
|
|
then this is effectively the _default_ to use for everything that wasn't
|
|
|
|
mapped by the other.
|
|
|
|
|
|
|
|
* `named_framework_to_proto_path_mappings_path`: The `value` used for this key
|
|
|
|
is a path to a file containing the listing of framework names and proto
|
|
|
|
files. The generator uses this to decide if another proto file referenced
|
|
|
|
should use a framework style import vs. a user level import
|
|
|
|
(`#import <FRAMEWORK/file.pbobjc.h>` vs `#import "dir/file.pbobjc.h"`).
|
|
|
|
|
|
|
|
The format of the file is:
|
|
|
|
* An entry is a line of `frameworkName: file.proto, dir/file2.proto`.
|
|
|
|
* Comments start with `#`.
|
|
|
|
* A comment can go on a line after an entry.
|
|
|
|
(i.e. - `frameworkName: file.proto # comment`)
|
|
|
|
|
|
|
|
Any number of files can be listed for a framework, just separate them with
|
|
|
|
commas.
|
|
|
|
|
|
|
|
There can be multiple lines listing the same frameworkName in case it has a
|
|
|
|
lot of proto files included in it; and having multiple lines makes things
|
|
|
|
easier to read.
|
|
|
|
|
|
|
|
* `runtime_import_prefix`: The `value` used for this key to be used as a
|
|
|
|
prefix on `#import`s of runtime provided headers in the generated files.
|
|
|
|
When integrating ObjC protos into a build system, this can be used to avoid
|
|
|
|
having to add the runtime directory to the header search path since the
|
|
|
|
generate `#import` will be more complete.
|
|
|
|
|
|
|
|
* `package_to_prefix_mappings_path`: The `value` used for this key is a
|
|
|
|
path to a file containing a list of proto packages and prefixes.
|
|
|
|
The generator will use this to locate which ObjC class prefix to use when
|
|
|
|
generating sources _unless_ the `objc_class_prefix` file option is set.
|
|
|
|
This option can be useful if multiple apps consume a common set of
|
|
|
|
proto files but wish to use a different prefix for the generated sources
|
|
|
|
between them. This option takes precedent over the `use_package_as_prefix`
|
|
|
|
option.
|
|
|
|
|
|
|
|
The format of the file is:
|
|
|
|
* An entry is a line of "package=prefix".
|
|
|
|
* Comments start with `#`.
|
|
|
|
* A comment can go on a line after a expected package/prefix pair.
|
|
|
|
(i.e. - "package=prefix # comment")
|
|
|
|
* For files that do NOT have a proto package (not recommended), an
|
|
|
|
entry can be made as "no_package:PATH=prefix", where PATH is the
|
|
|
|
path for the .proto file.
|
|
|
|
|
|
|
|
* `use_package_as_prefix`, `package_as_prefix_forced_prefix` and
|
|
|
|
`proto_package_prefix_exceptions_path`: The `value` for
|
|
|
|
`use_package_as_prefix` can be `yes` or `no`, and indicates if a prefix
|
|
|
|
should be derived from the proto package for all the symbols for files that
|
|
|
|
don't have the `objc_class_prefix` file option (mentioned above). This helps
|
|
|
|
ensure the symbols are more unique and means there is less chance of ObjC
|
|
|
|
class name collisions.
|
|
|
|
|
|
|
|
To help in migrating code to using this support,
|
|
|
|
`proto_package_prefix_exceptions_path` can be used to provide the path
|
|
|
|
to a file that contains proto package names (one per line, comments allowed
|
|
|
|
if prefixed with `#`). These package won't get the derived prefix, allowing
|
|
|
|
migrations to the behavior one proto package at a time across a code base.
|
|
|
|
|
|
|
|
`package_as_prefix_forced_prefix` can be used to provide a value that will
|
|
|
|
be used before all prefixes derived from the packages to help group all of
|
|
|
|
these types with a common prefix. Thus it only makes sense to use it when
|
|
|
|
`use_package_as_prefix` is also enabled. For example, setting this to
|
|
|
|
"XYZ\_" and generating a file with the package "something" defining
|
|
|
|
"MyMessage", would have Objective-C class be `XYZ_Something_MyMessage`.
|
|
|
|
|
|
|
|
`use_package_as_prefix` currently defaults to `no` (existing behavior), but
|
|
|
|
that could change in the future as it helps avoid collisions when more
|
|
|
|
protos get added to the build. Note that this would be a breaking change.
|
|
|
|
|
|
|
|
* `headers_use_forward_declarations`: The `value` for this can be `yes` or
|
|
|
|
`no`, and indicates if the generated headers use forward declarations for
|
|
|
|
Message and Enum types from other .proto files or if the files should be
|
|
|
|
imported into the generated header instead.
|
|
|
|
|
|
|
|
By using forward declarations, less code is likely to recompile when the
|
|
|
|
files do change, but Swift generally doesn't like forward declarations and
|
|
|
|
will fail to include properties when the concrete definition of the type is
|
|
|
|
known at import time. If your proto usages span modules, this can be a
|
|
|
|
problem.
|
|
|
|
|
|
|
|
`headers_use_forward_declarations` currently defaults to `yes` (existing
|
|
|
|
behavior), but in a future release, that default may change to provide
|
|
|
|
better Swift support by default.
|
|
|
|
|
|
|
|
Contributing
|
|
|
|
------------
|
|
|
|
|
|
|
|
Please make updates to the tests along with changes. If just changing the
|
|
|
|
runtime, the Xcode projects can be used to build and run tests. If your change
|
|
|
|
also requires changes to the generated code,
|
|
|
|
`objectivec/DevTools/full_mac_build.sh` can be used to easily rebuild and test
|
|
|
|
changes. Passing `-h` to the script will show the addition options that could
|
|
|
|
be useful.
|
|
|
|
|
|
|
|
Documentation
|
|
|
|
-------------
|
|
|
|
|
|
|
|
The complete documentation for Protocol Buffers is available via the
|
|
|
|
web at:
|
|
|
|
|
|
|
|
https://developers.google.com/protocol-buffers/
|