我的GitHub
0%

#1.第三方App跳转
这是很常见的问题,第三方app跳转到本app去做一些业务操作。
但是这时候会发现,你跳进来,是黑色的,没有界面,没想到吧23333
其实这在前面说过,RN的想法很独特,是一个ctrl上放了无数个view,不停的更改view来渲染,而rn的首页view,则是在appdelegate的初始化方法里去添加的。跳转进来的处理方法里如果你不写,就不会有view添加进来。
所以这时候有两种方法来完成这个view的添加操作:
####A.在第三方跳转进来的方法里做视图加载操作,但是这会遇到一个问题。假使你使用了RN的启动页,你会发现每次跳转进来都会开启启动页。这对用户的体验明显是很不好的。
####B.自己创建一个UIViewCtrl,并作为根视图放进window中,在这个UIViewCtrl中做视图加载操作。这样跳转进来加载根视图的时候就会把这个RN的View给加载上去。而且根据生命周期场景复现的原则,不会再有加载第二次第三次的情况。

如图

Appdelegate.m

RootViewCtrl.m

另外,如果要跳到某一页面做某一操作,又不想重复跳,可以采用以下方式移除

第三方跳转

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#pragma mark --第三方跳转进入这里(新)
-(BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
// NSLog(@"url ====%@",url);
thirdViewController *vc = [thirdViewController sharedthirdViewController];
vc.url = url;

UIViewController *topViewCtrl = self.nav.topViewController;
if ([topViewCtrl isKindOfClass:[thirdViewController class]]) { //判断是否在最顶层
[vc thirdSign];
}else{
[self.nav pushViewController:vc animated:YES];
[vc thirdSign];
}
return YES;
}

#2.应用升级苹果商店跳转
这个就很简单了啊,直接link:app在苹果商店的地址就行,至于怎么找app在苹果商店的地址,谷歌一下或百度一下都有。
#3.启动屏设置
采用了RN的启动页,你需要把原生的启动页稍作更改。把这个勾去掉

把这里改一下

#3.按钮点击封装防止二次点击
是不是有时候控件响应较慢,点击两次还以为没反应,结果却运行两次操作,感觉比较烦人。
这里贴出一个大佬给的方式,其实是采用定时器操作,只要有点击操作,做出事件处理,并开启定时器,在定时器时间内屏蔽其他的点击操作。

阅读全文 »

git:https://github.com/react-community/react-navigation/issues/1493
来,下猛药:
首先找到文件:src/views/ScenesReducer.js
然后用下面的代码:
  let k = null;
  let v = null;
  staleScenes.forEach(scene => {
  let {key} = scene;
  k = key;
  v = scene;
  });
  newStaleScenes = k && v ? new Map([[k, v]]) : new Map();
  newStaleScenes.forEach(mergeScene);
替换:staleScenes.forEach(mergeScene);
保存编译,就只有返回某页的动画了

转自http://www.cnblogs.com/lc901221/p/7543094.html
我就是那个贴了帖子看不懂答案的傻逼,。。

另外:
transitionConfig : () => ({
transitionSpec: {
duration: 0,
timing: Animated.timing,
easing: Easing.step0,
},
}),
去掉动画效果

2018-2-23 更新
以上解决方案适用于1.0.0beta版
升级到React-navigation 1.1.1版本后可直接通过key去回退指定版本。
至于怎么取key=>可以在跳转时缓存页面对应key值,通过页面名去获取缓存的key值跳转。
注意源码中当页面层级index为0时(首页)不会back。这一块应该是有想法的,但在特定情况下会有bug,因为我们项目就遇到了–但我暂时无法用语言总结出出现的场景。

无星的RN学习之旅(一)-环境安装以及新建项目
无星的RN学习之旅(二)-RN与原生的通信
无星的RN学习之旅(三)-bridge is not set.
无星的RN学习之旅(四)——通信、持久化存储、xcode打包
无星的RN学习之旅(六)-第三方App跳转,苹果商店跳转,loading框

阅读全文 »

废话不多说,直接上问题:
1.如何拼接请求头?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//申明返回的结果是json类型

manager.responseSerializer = [AFJSONResponseSerializer serializer];

//申明请求的数据是json类型

manager.requestSerializer=[AFJSONRequestSerializer serializer];

// /如果报接受类型不一致请替换一致text/html或别的

[manager.requestSerializer setValue:@"application/json" forHTTPHeaderField:@"Accept"];
[manager.requestSerializer setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[manager.requestSerializer setValue:value forHTTPHeaderField:key];
[manager.requestSerializer setValue: value forHTTPHeaderField:key];
[manager.requestSerializer setValue: value forHTTPHeaderField:key];


2.如何返回参数在调用的同一方法中?

block,参数带有block去实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
__block NSString *longitude; // __block,静态变量
[self.manager POST:URL parameters:params success:^(NSURLSessionDataTask * _Nonnull task, id _Nonnull responseObject) {

NSDictionary *locDictionary = [NSJSONSerialization JSONObjectWithData:responseObject options:NSJSONReadingMutableLeaves error:nil];
longitude = [locDictionary objectForKey:@"lon"]; // 纠正后经度

if (finishBlock)
{
finishBlock(longitude, nil);
}

} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSLog(@"%@", error);
if (finishBlock)
{
finishBlock(nil, error);
}
}];
阅读全文 »

说说最近项目的一些感想吧。

###一、RN的创意
RN其实我觉得是一个很有创意的想法。不知道各位写RN项目的时候,有没有打开Xcode看过app的层级关系,我发现RN的这个想法,真的很有创意。
作为一名原生的开发,一直都是一个控制器上放一个View,然后在这个底层的View上添加UI控件,当需要一个新的视图的时候,创建一个新的视图控制器,再放新的View。
###重点来了!RN并不是这么做的

根视图.png
RN是将App创建的时候生成的根视图控制器,也就是底层的视图控制器,作为根本,然后通过JS文件写的视图,也就是View,不停的增加在这个rootViewCtrl上,进行覆盖替换。
###二、Text的区别
或许有的兄弟还没遇到这个坑,假如使用图片或者其他背景色作为背景,往上添加Text标签的时候,安卓默认为透明背景色,但是苹果默认为灰白色。因此,在写App的时候,需要在Text的样式添加backgroundColor为transparent

1
backgroundColor:'transparent',

###三、原生与RN的通信
以前对原生与RN的通信不太了解。现在有了一些想法。
1.callback的通信方式,是会返回一个callback,这个callback是可以保存的,也就是说这个返回结果可以保存再用的。
2.promise,这个就比较有趣了,形象的说,这是个“通道”,RN的方法中,放一个promise的参数,在原生的module中,可以先定义几个promise的回调,在不同的地方用。
举个例子,我在RN中写几个方法。分别是:调用A方法,调用B方法,调用C方法,调用D方法。都是带Promise的。

promise.png
(lz是iOS开发,iOS中可以先声明几个变量)在iOS的module中,可以先声明几个promise的回调。比如先声明

1
2
3
4
5
6
7
8
9
 RCTPromiseResolveBlock resolveA
RCTPromiseResolveBlock resolveB
RCTPromiseResolveBlock resolveC
RCTPromiseResolveBlock resolveD

RCTPromiseRejectBlock rejectA
RCTPromiseRejectBlock rejectB
RCTPromiseRejectBlock rejectC
RCTPromiseRejectBlock rejectD

这四个回调的函数可以先声明,为什么会叫他通道,原因就是它其实可以这么理解,你将本来理解可能混乱的东西专一化,定义一个A方法成功的回调resolveA和一个A方法失败的回调rejectA,这两个回调只用于A方法。这么理解起来是不是清晰多了。因此可以理解为他是一个原生回调给RN的通信通道。
3.原生直接发消息,通过

1
[self sendEventWithName:@"EventReminder" body:@{@"name": eventName}];

这种方式注意了,请使用单例。

阅读全文 »

报错信息:bridge is not set. This is probably because you’ve “
“explicitly synthesized the bridge in %@, even though it’s inherited “
“from RCTEventEmitter.

踩坑了。。。
我相信肯定有兄弟需要从原生的OC向RN主动发起事件。而且这种场景也很多,比如集成第三方的服务,通过代理回调获取结果发送给RN等等等等。。。
我将我遇到的坑总结一下吧。
先看下官网怎么写的

官网介绍1

官网介绍2.png
1.你是不是像官网一样,先写一个继承自RCTEventEmitter的对象,什么都不写,看看能不能运行?
答案是:并不能运行=。=你必须写实现,也就是以下这个方法

1
2
3
4
5
//.m文件
- (NSArray<NSString *> *)supportedEvents
{
return @[@"EventReminder"];
}

2.你在使用发送文件,也就是

1
[self sendEventWithName:@"消息名" body:参数];

运行这个方法的时候有没有崩溃啊=。=
崩溃的提示是不是

1
2
3
bridge is not set. This is probably because you've "
"explicitly synthesized the bridge in %@, even though it's inherited "
"from RCTEventEmitter.

其实就是bridage为空。
这个时候你查这个报错提示是不是发现有人说在Appdelegate.m里把rootView的bridage赋给这个你创建的对象,然后你试了一下确实发出去了开始哈皮=。=

阅读全文 »

有时候用AFNetworking发送数据的时候会产生这种错误:

1
Request failed: unacceptable content-type: text/html

3259244-7ef2c6bad256fe3a.png.jpeg

这是因为text/html这个方式AF中没有。。这种时候有两种方式解决
1.直接修改AF的文件:
AFURLResponseSerialization.m文件中大约226行处,将

1
self.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript", nil];

修改为:

1
self.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript", @"text/html",nil];

2.jpg
此时便可以正常发送消息了。
不过不是很建议直接修改,比如你要封装sdk总不能直接把别人写的第三方封进来吧,一方面别人集成容易产生冲突,第二你的sdk体积会大很多。这时候可以采用第二种方式
2.在你发送的时候每次都添加

3.jpg

1
2
3
4

manager.requestSerializer = [AFHTTPRequestSerializer serializer];
manager.responseSerializer = [AFJSONResponseSerializer serializer];
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript",@"text/html",@"text/plain", nil];
阅读全文 »

接上一篇无星的RN学习之旅(一)最后我给出了一个基础项目地址进行学习。
PS:我使用的是VSCode编译器和Xcode编译器
一、RN如何调用原生方法
1.在新建的项目中打开ios目录下的工程文件,同时使用VSCode打开项目目录。
新建NSObjec对象,名字任意,我这里叫RNruniOS

.h文件添加RCTBridgeModule.h头文件,RCTBridgeModule协议

1
2
3
4
5
6
//RNruniOS.h文件
#import <Foundation/Foundation.h>
#import "React/RCTBridgeModule.h"
@interface RNruniOS : NSObject<RCTBridgeModule>

@end

.m文件添加RCTConvert.h头文件,并添加相应宏

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//RNruniOS.m文件
#import "RNruniOS.h"
//RCTConvert提供了一系列辅助函数,用来接收一个JSON值并转换到原生Objective-C类型或类。
#import "React/RCTConvert.h"
@implementation RNruniOS

//为了实现RCTBridgeModule协议,需要包含RCT_EXPORT_MODULE()宏。
//这个宏也可以添加一个参数用来指定在Javascript中访问这个模块的名字。
//如果不指定,默认就会使用这个Objective-C类的名字。
RCT_EXPORT_MODULE()

//通过RCT_EXPORT_METHOD()宏声明要给Javascript导出的方法,否则React Native不会导出任何方法。
RCT_EXPORT_METHOD(RNiOSLog:(NSString*)msg)
{
NSLog(@"RN调用iOS打印方法信息是%@",msg);
}

@end

2.在rn项目中的index.ios.js文件进行调用

1
2
//RN调用iOS原生方法,定义一个变量
var RNruniOS = NativeModules.RNruniOS;
1
2
//RN调用原生方法
RNruniOS.RNiOSLog('RN调用iOS打印方法成功。');

通过xcode进行项目编译,点击相应按钮触发事件即可看见控制台打印输出log信息。
该小练习github地址:https://github.com/XingXiaoWu/RNruniOS

二、回调函数CallBack的使用
无星的RN学习之旅(一)-环境安装以及新建项目
无星的RN学习之旅(三)
无星的RN学习之旅(四)——通信、持久化存储、xcode打包
无星的RN学习之旅(五)-关于react-navigation多层级页面返回时,去掉逐层推出动画
无星的RN学习之旅(六)-第三方App跳转,苹果商店跳转,loading框

阅读全文 »

iOS菜鸟,本周开始了react native的学习。
(一)环境安装
官网写的很详细,我觉得就没必要重新再啰嗦了。
官网地址:
http://reactnative.cn/docs/0.46/getting-started.html
(二)新建第一个项目
1.打开“终端”输入

1
react-native init MyApp --version 0.44.3

注意:init命令默认会创建最新的版本,而目前最新的0.45及以上版本需要下载boost库编译。此库体积庞大,在国内即便翻墙也很难下载成功,导致很多人无法正常运行iOS项目,推荐暂时使用0.44.3的版本。
2.创建成功后cd到项目路径下

1
cd MyApp

3.运行该项目

1
react-native run-ios

P.S 我是运行iOS,如果运行安卓就输入

1
react-native run-android

我创建了一个练习文件,可供练习,这五个练习完成应该就能初步知道怎么交互了。包括我的学习路线怎么完成也会慢慢更新~

界面图
地址是:https://github.com/XingXiaoWu/React-Native-First
不如随手点个star让楼主也开心一整天~

阅读全文 »

这个是一些小坑,大牛们忽略。

1.有些时候,后台传输一些json数据会是Unicode码,如果存在在数组里,就更尴尬了,无法转成数组,那么这时候怎么办呢。

例如.png

这时候,一定要把\U转换成\u,转换成功即可正常使用。
2.如何判断属于什么类型。
数据属于什么类型,使用iskindofclass来进行判断

再例如.png

3.如何将json串转换成dic或array
如果json数据正常,直接使用如图方法,如json数据为单引号,则进行转义。

转换.png

1
2
3
4
5
6
7
8
9
10
11
12
13
    NSString *arrString = [jsonDic valueForKey:@"XXX"];

if ([arrString isKindOfClass:[NSString class]]) {
NSLog(@"NSString类");
}else if([arrString isKindOfClass:[NSArray class]]){
NSLog(@"NSArray类");
}

//如果是单引号加上这句
NSString *str3 = [arrString stringByReplacingOccurrencesOfString:@"'" withString:@"\""];

NSData *arrData = [str3 dataUsingEncoding:NSUTF8StringEncoding];//也可以试试NSASCIIStringEncoding
NSArray *array = [self toArrayOrNSDictionary:arrData];
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#pragma mark -- 将JSON串转化为NSDictionary或NSArray
- (id)toArrayOrNSDictionary:(NSData *)jsonData{
NSError *error = nil;
id jsonObject = [NSJSONSerialization JSONObjectWithData:jsonData
options:NSJSONReadingAllowFragments
error:&error];

if (jsonObject != nil && error == nil){
return jsonObject;
}else{
// 解析错误
return nil;
}
}
阅读全文 »

img

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
HashMapreMap =newHashMap();

try{

JSONObject jsonobject=newJSONObject(response);

Iterator i=jsonobject.keys();

while(i.hasNext()){

String key = (String) i.next();

String values=jsonobject.getString(key);

reMap.put(key,values);

}

}catch(JSONException e) {

e.printStackTrace();

}

阅读全文 »