0

Generally we created custom keyboard like https://developer.apple.com/documentation/uikit/keyboards_and_input/creating_a_custom_keyboard and we need to store data in async storage and fetch also. its works in android perfectly after adding .addPackage(new AsyncStoragePackage()) but not works in ios.

Module like :

index.js

AppRegistry.registerComponent(RNFirebaseBackgroundMessage, () => HeadlessCheck);

////Registering module for Custom Keyboard 
AppRegistry.registerComponent('RNKeyboard', () => Keyboard);

This is the native module directory structure for custom keyboard

created app module group in xcode like this

Expectation: Store data in async storage and access when keyboard load.

This is the file structure for extention:

https://user-images.githubusercontent.com/68462761/142420159-4dad8cce-dea9-49c3-9f50-a748f03cef1e.jpg

This is the KeyboardViewController.h file

#import "React/RCTAsyncLocalStorage.h"
#import "RNCAsyncStorage.h"

@interface KeyboardViewController : UIInputViewController

@end

KeyboardViewController.m file like this

#import "KeyboardViewController.h"

#import <React/RCTBridge.h>
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>

#import <React/RCTAsyncLocalStorage.h>
#import <React/RCTBridgeModule.h>
#import "RNCAsyncStorage.h"
#import <CodePush/CodePush.h>


@interface KeyboardViewController ()
  @property (nonatomic, strong) UIButton *nextKeyboardButton;
  @property (nonatomic) RCTRootView *rootView;
  @property (nonatomic) RCTBridge *bridge;
  @property (nonatomic) UIView *circleView;
@end

KeyboardViewController * keyboardViewController = nil;

@implementation KeyboardViewController

- (void)updateViewConstraints {
    [super updateViewConstraints];
    
  
    if (self.rootView) {
        NSLog(@"chaning root view dimensions");
        self.rootView.frame = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height);
    }
}

- (void)viewDidLoad {
    [super viewDidLoad];
  
    CGFloat _expandedHeight = 240;
    NSLayoutConstraint *_heightConstraint =
        [NSLayoutConstraint constraintWithItem: self.view
                                   attribute: NSLayoutAttributeHeight
                                   relatedBy: NSLayoutRelationEqual
                                      toItem: nil
                                   attribute: NSLayoutAttributeNotAnAttribute
                                  multiplier: 0.0
                                    constant: _expandedHeight];
    [self.view addConstraint: _heightConstraint];
    
    RNCAsyncStorage *asyncStorage = [_bridge moduleForClass:[RNCAsyncStorage class]];
    asyncStorage.delegate = self;

    NSLog(@"Added loading view");
    
    /* Custom RN View */
    self.bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:@{@"keyboardExtension": self}];
  
    NSDictionary *props = @{@"isKeyboard" : @true};
    self.rootView = [[RCTRootView alloc] initWithBridge:self.bridge
                                                     moduleName:@"RNKeyboard"
                                               initialProperties:props];
    [self.view addSubview:self.rootView];
    /* Custom RN View - end */
  
    
    [self updateViewConstraints];
    keyboardViewController = self;
}

- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
  #if DEBUG
    return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"nameKeyboard" fallbackResource:nil];
  #else
    return [CodePush bundleURL];
  #endif
}

- (void)viewWillLayoutSubviews
{
    self.nextKeyboardButton.hidden = !self.needsInputModeSwitchKey;
    [super viewWillLayoutSubviews];
}

- (void)textWillChange:(id<UITextInput>)textInput {
    // The app is about to change the document's contents. Perform any preparation here.
}

- (void)textDidChange:(id<UITextInput>)textInput {
    // The app has just changed the document's contents, the document context has been updated.
    
    UIColor *textColor = nil;
    if (self.textDocumentProxy.keyboardAppearance == UIKeyboardAppearanceDark) {
        textColor = [UIColor whiteColor];
    } else {textColor = [UIColor blackColor];}
    [self.nextKeyboardButton setTitleColor:textColor forState:UIControlStateNormal];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
}
@end

KeyboardExtension.m like this

https://user-images.githubusercontent.com/68462761/142418490-bc4a43f3-1799-4f49-bea7-b3f6b71d92cc.png

Main podfile like this:

require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules'
source 'https://github.com/CocoaPods/Specs.git'

platform :ios, '13.0'

target 'name' do
  config = use_native_modules!

  use_react_native!(:path => config["reactNativePath"])

  pod 'CodePush', :path => '../node_modules/react-native-code-push'
  pod 'RNDeviceInfo', :path => '../node_modules/react-native-device-info'
  # pod 'Firebase/Analytics'
  pod 'Permission-Camera', :path => "../node_modules/react-native-permissions/ios/Camera.podspec"
  pod 'DocumentScanner'
  pod 'DDPerspectiveTransform'
  pod 'RNCAsyncStorage', :path => '../node_modules/@react-native-community/async-storage'
  pod 'react-native-netinfo', :path => '../node_modules/@react-native-community/netinfo'

  # target 'nameTests' do
  #   inherit! :complete
  #   # Pods for testing
  # end

  # Enables Flipper.
  #
  # Note that if you have use_frameworks! enabled, Flipper will not work and
  # you should disable these next few lines.
  # use_flipper!
  # post_install do |installer|
  #   flipper_post_install(installer)
  # end

  # Add this below your pods. Where "YourAppShareExtension" is your Share Extension's target name
  target 'name Keyboard' do
    use_native_modules!
    inherit! :search_paths
    inherit! :complete
  end


  post_install do |installer|
    flipper_post_install(installer)
    installer.pods_project.targets.each do |target|

      target.build_configurations.each do |config|
        config.build_settings['APPLICATION_EXTENSION_API_ONLY'] = 'NO'
      end

      if target.name == "React"
        target.remove_from_project
      end
  
      # It removes React & Yoga from the Pods project, as it is already included in the main project.
      targets_to_ignore = %w(React yoga)
      if targets_to_ignore.include? target.name
        target.remove_from_project
      end
    end
  end
end

# target 'name-tvOS' do
#   # Pods for name-tvOS

#   target 'name-tvOSTests' do
#     inherit! :search_paths
#     # Pods for testing
#   end
# end
  • your question is very unclear about your project structure and the code you are using on the native and the RN side, but one thing is that an Extension has different SharedPreferences (and files) than the Main App. If you want to handle it across Extension and main app you need to creat App groups and use a group storage. – Christian Oct 25 '21 at 12:55
  • keyboad module is inside the project group (Targets) – Jaydip Sharma Oct 25 '21 at 13:14
  • Hello and welcome to StackOverflow. Please take some time to read the help page, especially the sections named [“What topics can I ask about here?”](http://stackoverflow.com/help/on-topic) and [“What types of questions should I avoid asking?”](http://stackoverflow.com/help/dont-ask). And more importantly, please read (the Stack Overflow question checklist)[http://meta.stackexchange.com/q/156810/204922]. You might also want to learn about [Minimal, Complete, and Verifiable Examples](http://stackoverflow.com/help/mcve). – Ajay Lingayat Oct 25 '21 at 13:29

0 Answers0