addPlistKey method

OperationResult addPlistKey(
  1. String key,
  2. String value, {
  3. PlistValueType valueType = PlistValueType.string,
})

Adds a key-value pair to the iOS Info.plist file.

This method safely parses the plist, checks for duplicates, and inserts the key-value pair in the appropriate location within the dictionary.

Parameters

  • key: The plist key name (e.g., NSCameraUsageDescription).
  • value: The value for that key.
  • valueType: The plist value type (defaults to PlistValueType.string).

Supported Value Types

Returns

  • Success if the key was added or already exists
  • Failure if the plist could not be found or parsed

Example

final manager = IosManager('/path/to/project');

// Add a string value
manager.addPlistKey('NSCameraUsageDescription', 'Camera access needed');

// Add a boolean value
manager.addPlistKey(
  'UIRequiresFullScreen',
  'true',
  valueType: PlistValueType.boolean,
);

// Add an integer value
manager.addPlistKey(
  'MinimumOSVersion',
  '12',
  valueType: PlistValueType.integer,
);

Implementation

OperationResult addPlistKey(
  String key,
  String value, {
  PlistValueType valueType = PlistValueType.string,
}) {
  final plistFile = File(_infoPlistPath);

  if (!plistFile.existsSync()) {
    return const Failure(
      'Could not find Info.plist. '
      'Are you in a Flutter project root directory?',
    );
  }

  try {
    String content = plistFile.readAsStringSync();

    // Check if key already exists (prevent duplicates)
    final keyPattern = RegExp(
      '<key>${RegExp.escape(key)}</key>',
      multiLine: true,
    );

    if (keyPattern.hasMatch(content)) {
      return Success('Key "$key" already exists in Info.plist.');
    }

    // Find the main <dict> element to insert into
    final dictClosePattern = RegExp(r'</dict>\s*</plist>\s*$');
    final match = dictClosePattern.firstMatch(content);

    if (match == null) {
      return const Failure(
        'Invalid Info.plist format: could not find closing </dict> tag.',
      );
    }

    // Build the value element based on the specified type
    final valueElement = switch (valueType) {
      PlistValueType.string => '<string>$value</string>',
      PlistValueType.boolean => value.toLowerCase() == 'true'
          ? '<true/>'
          : '<false/>',
      PlistValueType.integer => '<integer>$value</integer>',
      PlistValueType.array => '<array>\n\t\t<string>$value</string>\n\t</array>',
    };

    // Insert the new key-value pair before </dict>
    final insertion = '\t<key>$key</key>\n\t$valueElement\n';
    content = content.replaceFirst(
      dictClosePattern,
      '$insertion</dict>\n</plist>\n',
    );

    plistFile.writeAsStringSync(content);
    return Success('Successfully added "$key" to Info.plist.');
  } on FileSystemException catch (e) {
    return Failure('Failed to update Info.plist: ${e.message}');
  }
}