Skip to content

Commit

Permalink
ios native modules: Expose "AppIdentifierPrefix" (Team ID plus a dot).
Browse files Browse the repository at this point in the history
Following discussion [1] about a SO answer (not currently the
accepted one) [2], we find it's not too hard, when we want the App
ID prefix (the Team ID plus a dot), to

1. Add a custom entry in ios/ZulipMobile/Info.plist that gets set to
   that string at build time, and

2. Write some minimal Objective-C to add a native module that calls
   an iOS API to grab that custom entry and exposes it to the
   JavaScript.

We followed a very clear React Native doc [3] on how to do this.

We also considered using a different doc [4] that would have helped
us package our code up very conveniently for distribution to NPM,
with a third-party tool called `create-react-native-module`. The
output of that tool seemed to have all the appropriate metadata that
we're used to seeing in modules in the React Native ecosystem, such
as a "podspec" file.

But our goal isn't to distribute this code for wide use. Still, it
would be possible to, e.g., host it on GitHub (or even locally) and
point to it from `dependencies` in our `package.json`. But this
seems like a lot more overhead than it'll ever be worth, and we
avoided doing something like that in 0b84717, an already-merged
part of issue zulip#4124, where we just wrote some Kotlin code and a few
lines in our `MainApplication.java` to import it.

We put the two new files in the same directory that has
`UtilManager.h` and `UtilManager.m`, which were also created for
Zulip-specific needs. This time, we follow the pattern of adding a
short, all-caps prefix, ZLP, as seen in

- Expo -> EX
- Unimodules -> UM
- React Native -> RCT

To link the new files, we used the Xcode UI:

1. Found the PBXGroup called "ZulipMobile" in the left sidebar. In
   Xcode 11.5, it has a folder icon. It includes the `Info.plist` as
   well as `UtilManager.h` and `UtilManager.m`.

2. Right-clicked it and selected `Add files to "ZulipMobile"...`,
   and chose those files.

3. Selected the ZulipMobile target in the project and targets list,
   and went to Build Phases -> Compile Sources to add the files
   there.

4. Saw that, surprisingly, they were already added there. So, job
   done.

Then, we tested with some in-app logging to see that we can indeed
access the App ID prefix. With NativeModules imported from
react-native, we see it at
`NativeModules.ZLPInfoProperties.appIdentifierPrefix`.

[1]: https://chat.zulip.org/#narrow/stream/243-mobile-team/topic/iOS.20native.20module/near/916750
[2]: https://stackoverflow.com/a/28714850/6792075
[3]: https://reactnative.dev/docs/0.60/native-modules-ios
[4]: https://reactnative.dev/docs/0.60/native-modules-setup
  • Loading branch information
chrisbobbe committed Jun 26, 2020
1 parent acd853a commit 4828ecf
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 0 deletions.
6 changes: 6 additions & 0 deletions ios/ZulipMobile.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; };
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
42689E9C23466FF7007540AA /* webview in Resources */ = {isa = PBXBuildFile; fileRef = 42689E9B23466FF7007540AA /* webview */; };
8BEA1EF024A6983D00674040 /* ZLPInfoProperties.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BEA1EEE24A6983D00674040 /* ZLPInfoProperties.m */; };
A148FEFC1E9D8CB900479280 /* zulip.mp3 in Resources */ = {isa = PBXBuildFile; fileRef = A148FEFB1E9D8CB900479280 /* zulip.mp3 */; };
C091D09FD11FDDB8E939257D /* libPods-ZulipMobile.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 74F3CD22CB932FA7EEE0BB66 /* libPods-ZulipMobile.a */; };
CFA67D201EC23BCB0070048E /* UtilManager.m in Sources */ = {isa = PBXBuildFile; fileRef = CFA67D1F1EC23BCB0070048E /* UtilManager.m */; };
Expand All @@ -32,6 +33,8 @@
42689E9B23466FF7007540AA /* webview */ = {isa = PBXFileReference; lastKnownFileType = folder; path = webview; sourceTree = "<group>"; };
66E34CC6219226D10091B852 /* ZulipMobile-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "ZulipMobile-Bridging-Header.h"; sourceTree = "<group>"; };
74F3CD22CB932FA7EEE0BB66 /* libPods-ZulipMobile.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-ZulipMobile.a"; sourceTree = BUILT_PRODUCTS_DIR; };
8BEA1EEE24A6983D00674040 /* ZLPInfoProperties.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ZLPInfoProperties.m; path = ZulipMobile/ZLPInfoProperties.m; sourceTree = "<group>"; };
8BEA1EEF24A6983D00674040 /* ZLPInfoProperties.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ZLPInfoProperties.h; path = ZulipMobile/ZLPInfoProperties.h; sourceTree = "<group>"; };
A148FEFB1E9D8CB900479280 /* zulip.mp3 */ = {isa = PBXFileReference; lastKnownFileType = audio.mp3; path = zulip.mp3; sourceTree = "<group>"; };
CF6CFE2C1E7DC55100F687C7 /* Build-Phases */ = {isa = PBXFileReference; lastKnownFileType = folder; path = "Build-Phases"; sourceTree = "<group>"; };
CFA67D1F1EC23BCB0070048E /* UtilManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = UtilManager.m; path = ZulipMobile/UtilManager.m; sourceTree = "<group>"; };
Expand All @@ -57,6 +60,8 @@
13B07FAE1A68108700A75B9A /* ZulipMobile */ = {
isa = PBXGroup;
children = (
8BEA1EEF24A6983D00674040 /* ZLPInfoProperties.h */,
8BEA1EEE24A6983D00674040 /* ZLPInfoProperties.m */,
3C4249EC1EF6E16500D245F1 /* ZulipMobile.entitlements */,
008F07F21AC5B25A0029DE68 /* main.jsbundle */,
13B07FAF1A68108700A75B9A /* AppDelegate.h */,
Expand Down Expand Up @@ -360,6 +365,7 @@
buildActionMask = 2147483647;
files = (
CFA67D201EC23BCB0070048E /* UtilManager.m in Sources */,
8BEA1EF024A6983D00674040 /* ZLPInfoProperties.m in Sources */,
13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */,
13B07FC11A68108700A75B9A /* main.m in Sources */,
);
Expand Down
2 changes: 2 additions & 0 deletions ios/ZulipMobile/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>AppIdentifierPrefix</key>
<string>$(AppIdentifierPrefix)</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleDisplayName</key>
Expand Down
5 changes: 5 additions & 0 deletions ios/ZulipMobile/ZLPInfoProperties.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#import <React/RCTBridgeModule.h>

@interface ZLPInfoProperties : NSObject <RCTBridgeModule>

@end
24 changes: 24 additions & 0 deletions ios/ZulipMobile/ZLPInfoProperties.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#import "ZLPInfoProperties.h"

@implementation ZLPInfoProperties

RCT_EXPORT_MODULE()

// For why we include this, see
// https://reactnative.dev/docs/0.60/native-modules-ios#implementing--requiresmainqueuesetup.
+ (BOOL)requiresMainQueueSetup
{
return NO; // Initialization may be done on any thread; we don't need access to UIKit.
}

- (NSDictionary *)constantsToExport
{
// Items from the Info.plist.
return @{
// We've added a custom entry that gives us the App ID
// Prefix (a.k.a. the Team ID plus a dot). Access it.
@"appIdentifierPrefix": [[NSBundle mainBundle] objectForInfoDictionaryKey:@"AppIdentifierPrefix"] ?: [NSNull null],
};
}

@end

0 comments on commit 4828ecf

Please sign in to comment.