React Native学习之RN与iOS原生通信

iOS 平台开发语言分为:Objective-CSwift,目前 React Native 只能与Objective-C代码交互,与Swift代码交互必须先与Objective-C交互,再通过Objective-CSwift交互,由于Swift的某些先进特性,这种方式的混合开发完全是值得的,并不会有性能损失。

#import "RCTBridgeModule.h"  //导入这个头文件以现实RCTBridgeModule协议
#import "RCTBridge.h"  //导入这个头文件以实现向RN侧发送事件
#import "RCTEventDispatcher.h"  //导入这个头文件以实现向RN侧发送事件

ExampleInterface.h

#import <Foundation/Foundation.h>
#import "RCTBridgeModule.h" // 导入这个头文件以现实RCTBridgeModule协议
#import "RCTBridge.h"   // 导入这个头文件以实现向RN侧发送事件
#import "RCTEventDispatcher.h"  // 导入这个头文件以实现向RN侧发送事件

@interface ExampleInterface : NSObject<RCTBridgeModule>
@property (nonatomic, strong)NSString *contactName;  // 保存联系人名字
@property (nonatomic, strong)NSString *contactPhoneNumber;  // 保存联系人电话号码

@end

ExampleInterface.m

#import "ExampleInterface.h"
#import "CallAdressbookViewController.h"  //这是开发者使用Objective-C开发的类的头文件

@interface ExampleInterface()
@property (nonatomic, strong)NSDictionary *dic;

@end
@implementation ExampleInterface
- (instancetype) init{
    return self;
}
- (NSString *)contactName{
    if (!_contactName) {
        _contactName = @"";
    }
    return _contactName;
}

@synthesize bridge=_bridge;
// 除了现实RCTBridegModule协议外,类还需要包含RCT_EXPORT_MODELE()宏。这个宏可以添加一个参数用来指定在js中访问这个模块的名字
// 通常不指定名字,默认使用Objective-C类的名字
RCT_EXPORT_MODULE();

// 使用RCT_EXPORT_METHOD()宏声明需要提供给RN组件调用的方法
RCT_EXPORT_METHOD(sendMessage: (NSString *)msg)
{
    // 在调试窗口中打印React Native调用此函数时携带的参数
    NSLog(@"收到的来自React Native的消息:%@", msg);

    // 检测收到的消息是否为json格式
    NSData *data = [msg dataUsingEncoding:NSUTF8StringEncoding];
    NSError *error;
    NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:&error];

    if (error != nil) {
        NSLog(@"解析错误:%@", error);
    } else {
        // 没有错误则通知React Native,发送消息给React Native
        [self.bridge.eventDispatcher sendAppEventWithName:@"NativeModuleMsg" body:@{@"message":@"发送消息通知React Native - 没有解析错误"}];
    }

    // 检测消息的msgType是否为pickContact,如果是则初始化挑选联系人界面
    NSString *login = [dic objectForKey:@"msgType"];

    if ([login isEqualToString:@"pickContact"]) [self callAddress];
}

- (void)callAddress {
    UIViewController *controller = (UIViewController*)[[[UIApplication sharedApplication]keyWindow] rootViewController];

    CallAdressbookViewController *addressbookViewController = [[CallAdressbookViewController alloc] init];
    [controller presentViewController:addressbookViewController animated:YES completion:nil];

    self.contactName = addressbookViewController.contactName;

    self.contactPhoneNumber = addressbookViewController.contactPhoneNumber;

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(calendarEventReminderReceived:) name:@"Num" object:nil];
}

- (dispatch_queue_t)methodQueue
{
    return dispatch_get_main_queue();
}

- (void)calendarEventReminderReceived:(NSNotification *)notification{
    self.contactPhoneNumber = notification.object;
    self.contactName = notification.userInfo[@"name"];
    // 去除获取到的电话号码中的特殊字符
    self.contactPhoneNumber=[self.contactPhoneNumber stringByReplacingOccurrencesOfString:@"-" withString:@""];
    self.contactPhoneNumber = [self.contactPhoneNumber stringByReplacingOccurrencesOfString:@"(" withString:@""];
    self.contactPhoneNumber = [self.contactPhoneNumber stringByReplacingOccurrencesOfString:@")" withString:@""];
    self.contactPhoneNumber = [self.contactPhoneNumber stringByReplacingOccurrencesOfString:@" " withString:@""];

    NSMutableDictionary *dic=[[NSMutableDictionary alloc] init];

    [dic setObject:@"pickContactResult" forKey:@"msgType"];

    if(self.contactPhoneNumber==nil){
        self.contactPhoneNumber=@"";
    }

    [dic setObject:self.contactPhoneNumber forKey:@"peerNumber"];

    if(self.contactName == nil){
        self.contactName = @"";
    }

    // 组装发送给rn侧的消息

    [dic setObject:self.contactName forKey:@"displayName"];
    self.dic = [dic copy];
    NSError *error = [[NSError alloc] init];
    NSData *data = [NSJSONSerialization dataWithJSONObject:self.dic options:0 error:&error];
    NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

    // 向React Native发送消息
    [self.bridge.eventDispatcher sendAppEventWithName:@"NativeModuleMsg" body:@{@"message":str}];
}

@end

CallAdressbookViewController.h

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

@interface CallAdressbookViewController : UIViewController

@property (nonatomic, strong)NSString *contactName;
@property (nonatomic, strong)NSString *contactPhoneNumber;

@end

CallAdressbookViewController.m

#import "CallAdressbookViewController.h"
#import <AddressBookUI/AddressBookUI.h>
#import <AddressBook/AddressBook.h>
#import "AppDelegate.h"

@class CallAdressbookViewController;

@interface CallAdressbookViewController()<ABPeoplePickerNavigationControllerDelegate>

@end

@implementation CallAdressbookViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor whiteColor];

    ABPeoplePickerNavigationController *peoplePicker = [[ABPeoplePickerNavigationController alloc] init];
    peoplePicker.peoplePickerDelegate = self;

    [self presentViewController:peoplePicker animated:YES completion:nil];
    [self authoriy];
}

// 授权注册
- (void)authoriy {
    // 检查是否是iOS6
    if (&ABAddressBookRequestAccessWithCompletion != NULL) {
        // iOS6版本中
        ABAddressBookRef abRef = ABAddressBookCreateWithOptions(NULL, NULL);
        if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined) {
            // 如果从未申请过权限,申请权限
            ABAddressBookRequestAccessWithCompletion(abRef, ^(bool granted, CFErrorRef error) {
                // 根据granted参数判断用户是否同意授予权限、
                if (granted) {
                    // 查询所有,即显示通讯录所有联系人
                    [self getContacts];
                }
            });
        } else if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusAuthorized) {
            // 如果权限已经被授予,查询所有,即显示通讯录所有联系人
            [self getContacts];
        } else {
            // 如果权限被收回,提醒用户去系统设置菜单中打开
            UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"温馨提示" message:@"请您设置允许APP访问您的通讯录\n设置>通用>访问权限" delegate:self cancelButtonTitle:@"" otherButtonTitles:nil, nil];
            [alert show];
            return;
        }
        if (abRef) {
            CFRelease(abRef);
        }
    }
}

// 获取全部通讯录单元信息
- (void)getContacts {
    ABAddressBookRef addressBook = ABAddressBookCreateWithOptions(NULL, NULL);
    // 1.取全部联系人
    CFArrayRef allPerson = ABAddressBookCopyArrayOfAllPeople(addressBook);
    CFIndex number = ABAddressBookGetPersonCount(addressBook);
    // 进行遍历
    for (NSInteger i = 0; i < number; i ++) {
        ABRecordRef people = CFArrayGetValueAtIndex(allPerson, i);
        // 2.获取联系人的姓名
        NSString *firstName = (__bridge NSString *)(ABRecordCopyValue(people, kABPersonFirstNameProperty));
        NSString *middleName = (__bridge NSString *)(ABRecordCopyValue(people, kABPersonMiddleNameProperty));
        NSString *lastName = (__bridge NSString *)(ABRecordCopyValue(people, kABPersonLastNameProperty));
        NSString *nameString  = nil;
        if (firstName.length != 0) nameString = firstName;
        if (middleName.length != 0) nameString = [nameString stringByAppendingString:middleName];
        if (lastName.length != 0) nameString = [nameString stringByAppendingString:lastName];
        // if (firstName.length == 0 || lastName.length == 0) nameString = firstName ? [NSString stringWithFormat:@"%@%@" , firstName(lastName ? lastName : @"") ] : @"";
        // nameString = middleName.length ?  [NSString stringWithFormat:@"%@%@%@", lastName, middleName, firstName] : [NSString stringWithFormat:@"%@%@", lastName, firstName];
        NSLog(@"姓名:%@", nameString);

        // 3.获取联系人的头像图片
        // NSData *userImageData = (__bridge NSData *)(ABPersonCopyImageData(people));
        // UIImage *userImage = [UIImage imageWithData:userImageData];
        // NSData *data = UIImageJPEGRepresentation(userImage, 1.0);
        // NSString *userImageString= [data base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
        // NSURL *userImageURL  = [NSURL URLWithString:userImageString];
        // NSLog(@"头像:%@", userImageURL);

        // 4.获取联系人电话
        ABMutableMultiValueRef phoneMutil = ABRecordCopyValue(people, kABPersonPhoneProperty);
        NSMutableArray *phones = [[NSMutableArray alloc] init];
        for (int  i = 0; i < ABMultiValueGetCount(phoneMutil); i ++) {
            // NSString *phone = (__bridge NSString *)(ABMultiValueCopyValueAtIndex(phoneMutil, i));
            NSString *phoneLabel = (__bridge NSString *)(ABMultiValueCopyLabelAtIndex(phoneMutil, i));
            // if (phone.length  <  11) {
                // break;
            // }
            if ([phoneLabel isEqualToString:@"_$!<Mobile>!$_"]) {
                [phones addObject:(__bridge id _Nonnull)(ABMultiValueCopyValueAtIndex(phoneMutil, i))];
            } else {
                [phones addObject:(__bridge id _Nonnull)(ABMultiValueCopyValueAtIndex(phoneMutil, i))];
            }
        }
        for (int  i = 0; i < phones.count; i ++) {
            NSLog(@"电话%d:%@", i+1, phones[i]);
        }
    }
}

#pragma mark - ABPeoplePickerNavigationControllerDelegate
- (void)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker didSelectPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier {
    ABMultiValueRef valuesRef = ABRecordCopyValue(person, kABPersonPhoneProperty);
    CFIndex index = ABMultiValueGetIndexForIdentifier(valuesRef, identifier);
    CFStringRef value = ABMultiValueCopyValueAtIndex(valuesRef, index);

    // 获取联系人姓名
    // ABRecordRef people = CFArrayGetValueAtIndex(valuesRef, index);
    // NSString *firstName = (__bridge NSString *)(ABRecordCopyValue(people, kABPersonFirstNameProperty));
    // NSString *middleName = (__bridge NSString *)(ABRecordCopyValue(people, kABPersonMiddleNameProperty));
    // NSString *lastName = (__bridge NSString *)(ABRecordCopyValue(people, kABPersonLastNameProperty));
    // NSString *nameString  = nil;
    // if (firstName.length != 0) nameString = firstName;
    // if (middleName.length != 0) nameString = [nameString stringByAppendingString:middleName];
    // if (lastName.length != 0) nameString = [nameString stringByAppendingString:lastName];
    // if (firstName.length == 0 || lastName.length == 0) nameString = firstName ? [NSString stringWithFormat:@"%@%@" , firstName(lastName ? lastName : @"") ] : @"";
    // nameString = middleName.length ?  [NSString stringWithFormat:@"%@%@%@", lastName, middleName, firstName] : [NSString stringWithFormat:@"%@%@", lastName, firstName];

    CFStringRef anFullName = ABRecordCopyCompositeName(person);

    [peoplePicker dismissViewControllerAnimated:YES completion:^{
        [self dismissViewControllerAnimated:YES completion:^{
            self.contactPhoneNumber =  (__bridge NSString *)(value);
            self.contactName = (__bridge NSString *)(anFullName);

            [[NSNotificationCenter defaultCenter] postNotificationName:@"Num" object:self.contactPhoneNumber userInfo: @{@"name" : self.contactName}];

            NSLog(@"%@ %@", self.contactPhoneNumber, self.contactName);
        }];
    }];
}

- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person {
    [peoplePicker dismissViewControllerAnimated:YES completion:^ {
        // 获取联系人姓名
        // NSString *firstName = (__bridge NSString *)(ABRecordCopyValue(person, kABPersonFirstNameProperty));
        // NSString *middleName = (__bridge NSString *)(ABRecordCopyValue(person, kABPersonMiddleNameProperty));
        // NSString *lastName = (__bridge NSString *)(ABRecordCopyValue(person, kABPersonLastNameProperty));
        // NSString *nameString  = nil;
        // if (firstName.length != 0) nameString = firstName;
        // if (middleName.length != 0) nameString = [nameString stringByAppendingString:middleName];
        // if (lastName.length != 0) nameString = [nameString stringByAppendingString:lastName];
        // if (firstName.length == 0 || lastName.length == 0) nameString = firstName ? [NSString stringWithFormat:@"%@%@" , firstName(lastName ? lastName : @"") ] : @"";
        // nameString = middleName.length ?  [NSString stringWithFormat:@"%@%@%@", lastName, middleName, firstName] : [NSString stringWithFormat:@"%@%@", lastName, firstName];

        CFStringRef anFullName = ABRecordCopyCompositeName(person);

        [self dismissViewControllerAnimated:YES completion:^{
            ABMultiValueRef phones = ABRecordCopyValue(person,kABPersonPhoneProperty);
            NSString *phone  = nil;
            for (int i = 0; i < ABMultiValueGetCount(phones); i++) {
                phone = (__bridge NSString *)(ABMultiValueCopyValueAtIndex(phones, i));
                NSLog(@"telephone = %@",phone);
            }
            self.contactPhoneNumber = phone;
            self.contactName = (__bridge NSString *)(anFullName);

            [[NSNotificationCenter defaultCenter] postNotificationName:@"Num" object:self.contactPhoneNumber userInfo: @{@"name" : self.contactName}];

            NSLog(@"%@ %@", self.contactPhoneNumber, self.contactName);
        }];
    }];
    return YES;
}

- (void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController *)peoplePicker{
    [self dismissViewControllerAnimated:YES completion:^{
        [self dismissViewControllerAnimated:YES completion:nil];
    }];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

版权声明:
作者:Joe.Ye
链接:https://www.appblog.cn/index.php/2023/02/25/react-native-learning-for-rn-and-ios-native-communication/
来源:APP全栈技术分享
文章版权归作者所有,未经允许请勿转载。

THE END
分享
二维码
打赏
海报
React Native学习之RN与iOS原生通信
iOS 平台开发语言分为:Objective-C和Swift,目前 React Native 只能与Objective-C代码交互,与Swift代码交互必须先与Objective-C交互,再通过Objective-C与Sw……
<<上一篇
下一篇>>
文章目录
关闭
目 录