Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions .eslintrc.js

This file was deleted.

6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,9 @@ yarn-error.log

# Expo
.expo/*

# Swift Package Manager
#
.build/
.swiftpm/
Package.resolved
67 changes: 67 additions & 0 deletions Package.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// swift-tools-version:5.9
//
// This Package.swift is forward-compatibility scaffolding for the React Native
// SPM migration outlined in RFC 0994:
// https://github.com/react-native-community/discussions-and-proposals/pull/994
//
// The RN CLI's SPM autolinking (and Expo's `et prebuild` pipeline that consumes
// `spm.config.json`) is the supported install path. The expo-modules-core
// dependency below points at the standard React Native / Expo `node_modules`
// layout (`../expo-modules-core` relative to this package). That matches the
// shape RFC 0994's autolinking generates and works whenever this package is
// resolved as a local SPM package alongside a node_modules tree.
//
// As a consequence, this manifest does NOT resolve standalone via Xcode's
// "Add Package Dependencies…" flow today — `../expo-modules-core` only
// exists when the package is checked out beside an installed `node_modules/`.
// That changes once Expo / RN ship a published `ExpoModulesCore` SPM product.
//
// Platform floor is iOS 14: that is when `NWBrowser` / local network
// permission first exist. Bumping it would be an unnecessary breaking change
// for downstream apps still on the CocoaPods path.

import PackageDescription

let package = Package(
name: "ReactNativeLocalNetworkPermission",
platforms: [
.iOS(.v14)
],
products: [
.library(
name: "ReactNativeLocalNetworkPermission",
targets: ["ReactNativeLocalNetworkPermission"]
)
],
dependencies: [
// ⚠️ This relative path assumes a non-hoisted `node_modules/` layout where
// this package lives one level deep (e.g. `node_modules/<pkg>/Package.swift`)
// and `expo-modules-core` is a sibling. Hoisted monorepo layouts (Yarn
// workspaces, pnpm) where `expo-modules-core` resolves elsewhere will fail
// to resolve this dependency. The supported install path is RN/Expo's SPM
// autolinking, not standalone `swift package` resolution.
.package(name: "expo-modules-core", path: "../expo-modules-core")
Comment thread
benjaminkomen marked this conversation as resolved.
],
targets: [
.target(
name: "ReactNativeLocalNetworkPermission",
dependencies: [
.product(name: "ExpoModulesCore", package: "expo-modules-core")
],
path: "ios",
exclude: [
"ReactNativeLocalNetworkPermission.podspec"
],
sources: [
"ReactNativeLocalNetworkPermissionModule.swift",
"LocalNetworkAuthorization.swift"
],
resources: [
.copy("PrivacyInfo.xcprivacy")
],
linkerSettings: [
.linkedFramework("Network")
]
)
]
)
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,15 @@ Add this library to your project:

`yarn add @generac/react-native-local-network-permission`

### Swift Package Manager support

CocoaPods (via the bundled `.podspec`) is still the primary install path and works for every React Native and Expo app today.

This module also ships SPM scaffolding for the migration described in [React Native RFC 0994](https://github.com/react-native-community/discussions-and-proposals/pull/994) (CocoaPods deprecation, December 2026):

- `spm.config.json` — consumed by Expo's `et prebuild` pipeline (`EXPO_USE_PRECOMPILED_MODULES=1`) to generate XCFrameworks. Picked up automatically by Expo's autolinking; no extra setup.
- `Package.swift` — a forward-compatible manifest. The library target declares its dependency on `ExpoModulesCore` by name; the consumer's autolinking pipeline (RN CLI's SPM autolinking once it lands, or a hand-written brownfield manifest) is responsible for providing `.package(path: ".../node_modules/expo-modules-core")`. As a result, this `Package.swift` does not resolve standalone via "Add Package Dependencies…" in Xcode today — that workflow becomes available once the React Native SPM autolinking proposal lands.

### iOS manual configuration

#### NSLocalNetworkUsageDescription
Expand Down
10 changes: 10 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// @generated by expo-module-scripts
const { defineConfig } = require('eslint/config');
const baseConfig = require('expo-module-scripts/eslint.config.base');

module.exports = defineConfig([
baseConfig,
{
ignores: ['build/**', 'example/**'],
},
]);
7 changes: 6 additions & 1 deletion example/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,19 @@
"orientation": "portrait",
"icon": "./assets/icon.png",
"userInterfaceStyle": "light",
"newArchEnabled": true,
"splash": {
"image": "./assets/splash.png",
"resizeMode": "contain",
"backgroundColor": "#ffffff"
},
"ios": {
"supportsTablet": true,
"bundleIdentifier": "expo.modules.localnetworkpermission.example"
"bundleIdentifier": "expo.modules.localnetworkpermission.example",
"deploymentTarget": "16.4",
"infoPlist": {
"NSLocalNetworkUsageDescription": "This example app demonstrates requesting local network permission."
}
}
}
}
59 changes: 33 additions & 26 deletions example/ios/Podfile
Original file line number Diff line number Diff line change
@@ -1,21 +1,47 @@
# Generated by `expo prebuild` — Expo SDK 56. Do not hand-edit; regenerate via prebuild.
require File.join(File.dirname(`node --print "require.resolve('expo/package.json')"`), "scripts/autolinking")
require File.join(File.dirname(`node --print "require.resolve('react-native/package.json')"`), "scripts/react_native_pods")

require 'json'
podfile_properties = JSON.parse(File.read(File.join(__dir__, 'Podfile.properties.json'))) rescue {}

ENV['RCT_NEW_ARCH_ENABLED'] = podfile_properties['newArchEnabled'] == 'true' ? '1' : '0'
ENV['EX_DEV_CLIENT_NETWORK_INSPECTOR'] = podfile_properties['EX_DEV_CLIENT_NETWORK_INSPECTOR']
def ccache_enabled?(podfile_properties)
Comment thread
benjaminkomen marked this conversation as resolved.
# Environment variable takes precedence
return ENV['USE_CCACHE'] == '1' if ENV['USE_CCACHE']

platform :ios, podfile_properties['ios.deploymentTarget'] || '13.4'
install! 'cocoapods',
:deterministic_uuids => false
# Fall back to Podfile properties
podfile_properties['apple.ccacheEnabled'] == 'true'
end

ENV['EX_DEV_CLIENT_NETWORK_INSPECTOR'] ||= podfile_properties['EX_DEV_CLIENT_NETWORK_INSPECTOR']
ENV['RCT_USE_RN_DEP'] ||= podfile_properties['ios.buildReactNativeFromSource'] == 'true' ? '0' : '1'
ENV['RCT_USE_PREBUILT_RNCORE'] ||= podfile_properties['ios.buildReactNativeFromSource'] == 'true' ? '0' : '1'
ENV['RCT_HERMES_V1_ENABLED'] ||= '1' if podfile_properties['expo.useHermesV1'] == 'true'
ENV['EXPO_USE_PRECOMPILED_MODULES'] ||= '1' if podfile_properties['EXPO_USE_PRECOMPILED_MODULES'] != 'false'
platform :ios, podfile_properties['ios.deploymentTarget'] || '16.4'

prepare_react_native_project!

target 'reactnativelocalnetworkpermissionexample' do
use_expo_modules!
config = use_native_modules!

if ENV['EXPO_USE_COMMUNITY_AUTOLINKING'] == '1'
config_command = ['node', '-e', "process.argv=['', '', 'config'];require('@react-native-community/cli').run()"];
else
config_command = [
'node',
'--no-warnings',
'--eval',
'require(\'expo/bin/autolinking\')',
'expo-modules-autolinking',
'react-native-config',
'--json',
'--platform',
'ios'
]
end

config = use_native_modules!(config_command)

use_frameworks! :linkage => podfile_properties['ios.useFrameworks'].to_sym if podfile_properties['ios.useFrameworks']
use_frameworks! :linkage => ENV['USE_FRAMEWORKS'].to_sym if ENV['USE_FRAMEWORKS']
Expand All @@ -33,26 +59,7 @@ target 'reactnativelocalnetworkpermissionexample' do
installer,
config[:reactNativePath],
:mac_catalyst_enabled => false,
:ccache_enabled => podfile_properties['apple.ccacheEnabled'] == 'true',
:ccache_enabled => ccache_enabled?(podfile_properties),
)

# This is necessary for Xcode 14, because it signs resource bundles by default
# when building for devices.
installer.target_installation_results.pod_target_installation_results
.each do |pod_name, target_installation_result|
target_installation_result.resource_bundle_targets.each do |resource_bundle_target|
resource_bundle_target.build_configurations.each do |config|
config.build_settings['CODE_SIGNING_ALLOWED'] = 'NO'
end
end
end
end

post_integrate do |installer|
begin
expo_patch_react_imports!(installer)
rescue => e
Pod::UI.warn e
end
end
end
Loading