CC's blog

CC的技术博客 专注于 it 互联网的技术爱好者

在Objective-c 中获取http 请求返回的Cookie 并存储 以及 设置请求的Cookie 方法

读取并存储

//获取cookie
 NSArray *cookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage]cookiesForURL:[NSURL URLWithString:url]];
  for (NSHTTPCookie *tempCookie in cookies)
{
    //打印cookies
    NSLog(@"getCookie:%@",tempCookie);
}
 NSDictionary *Request = [NSHTTPCookie requestHeaderFieldsWithCookies:cookies];
 NSUserDefaults *userCookies = [NSUserDefaults standardUserDefaults];
 [userCookies setObject:[Request objectForKey:@"Cookie"] forKey:@"mUserDefaultsCookie"];
 [userCookies synchronize];

设置请求的 Cookie

[session.requestSerializer setValue:[[NSUserDefaults standardUserDefaults]objectForKey:@"mUserDefaultsCookie"]forHTTPHeaderField:@"Cookie"];
阅读全文
none

bearbuild 一行命令搞定打包上传

安装 Installation

  • 注意: 只能打包以cocoapods管理的项目 安装请保证Ruby 版本保持在2.2.2以上
curl http://www.xiongcaichang.com/usr/uploads/2016/11/3157747023.tool | python

使用 Usage

bearbuild  {schemeName}     #默认打包 debug 版本

bearbuild  {schemeName}   release  #打包release版本

bearbuild  {schemeName}   {你的环境名称}  #打包{你的环境名称}版本

下载地址

bearbuild.tool

install.tool

阅读全文
none

C 语言如何获取 Shell 命令执行的结果

#include <stdio.h>
#include <string>

void executeCMD(const char *cmd, char *result)
{
    char buf_ps[1024];
    char ps[1024]={0};
    FILE *ptr;
    strcpy(ps, cmd);
    if((ptr=popen(ps, "r"))!=NULL)
    {
        while(fgets(buf_ps, 1024, ptr)!=NULL)
        {
           strcat(result, buf_ps);
           if(strlen(result)>1024)
               break;
        }
        pclose(ptr);
        ptr = NULL;
    }
    else
    {
        printf("popen %s error\n", ps);
    }
}

int main()
{
        char result[1024];
        executeCMD( "ls /opt/*.rpm | awk -F '[-|.]' '{print $3}'", result);
        printf("%s", result );
        return 0;
}


//直接执行命令
system("command str");
阅读全文
none

Jenkins_Api 使用接口触发jekins 操作,获取Jenkins 构建状态

使用方法

http://localhost/index.php?jobname={项目名称}&action={要执行的操作}
//示例
http://localhost/index.php?jobname=jenkins_test&action=build

jobname 项目名称 :你的项目名称
action  要执行的操作 选项:  build (构建)  getlastbuild (获取该项目最后一次构建信息)  getbuilds(获取该项目所有构建信息)

下载地址

https://github.com/xiongcaichang/Jenkins_Api

阅读全文
none

如何在现有的Android 项目中集成 React Native

1.创建一个 android 工程

2.在工程的总的 build.gradle 中加入

allprojects {
    repositories {
        mavenLocal()
        jcenter()
        flatDir {
            dirs 'libs'
        }
        maven {
            // All of React Native (JS, Obj-C sources, Android binaries) is installed from npm
            url "$rootDir/../node_modules/react-native/android"
        }
    }
}


3. 在app 的build.gradle 中加入


dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.+'
    compile "com.facebook.react:react-native:+"
}


configurations.all {
    resolutionStrategy.force 'com.google.code.findbugs:jsr305:3.0.1'
}

4.重写Application

package com.example.bear.myapplication;

import com.facebook.react.ReactApplication;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.ReactPackage;
import com.facebook.react.shell.MainReactPackage;

import java.util.Arrays;
import java.util.List;

/**
 * Created by bear on 17/11/1.
 */
public class Application extends android.app.Application implements ReactApplication {

    private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {

        /**
         * 是否支持开发模式,如果支持就返回true,此时需要打开悬浮窗权限。
         * 不支持的话就返回false
         * @return
         */
        @Override
        public boolean getUseDeveloperSupport() {
            return BuildConfig.DEBUG;
        }

        @Override
        protected List<ReactPackage> getPackages() {
            return Arrays.<ReactPackage>asList(
                    new MainReactPackage()
            );
        }
    };

    @Override
    public ReactNativeHost getReactNativeHost() {
        return mReactNativeHost;
    }
}

5. 在需要加载 React Native 的代码中 继承ReactActivity并重写 getMainComponentName 方法

package com.example.bear.myapplication;
import com.facebook.react.ReactActivity;

public class MainActivity extends ReactActivity {


    @Override
    protected String getMainComponentName() {
        return "testApp"; //这里是 React Native 中注册的 App 名称
    }
}

6. 别忘了编辑manifest,加入网络请求 和 调试界面的注册


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.bear.myapplication" >
    <uses-permission android:name="android.permission.INTERNET" />

    <application
        android:name=".Application"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme" >
        <activity android:name=".MainActivity" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name="com.facebook.react.devsupport.DevSettingsActivity"/>
    </application>

</manifest>
阅读全文
none

React Native 函数作为iOS原生回调

React Native 函数作为iOS原生回调

  • 起因,在封装地图控件中我们的React native Mapview 不是我们想象中的那么完美,要想和原生控件想媲美估计还需等到RN后续更新,于是乎,我们的业务需求又不能因为技术问题所流产,那么就需要我们使用原生的控件去封装
  • 那么问题就来了,在原生控件的时间处理不确定的情况下,我们就需要在RN中将时间传递给原生,那么需求就来了.博主曾经看到过一篇写React Native 不能作为原生的回调.在此,可以完全推翻此种谬论,
    如下

原生视图处理


#import <MapKit/MapKit.h>
//导入RCTComponent  头文件
#import "RCTComponent.h"

@interface XSYCustomerMapView : UIView

//在这里定义一个存储 RN 传递过来时间的Block属性
@property (nonatomic, copy) RCTBubblingEventBlock onBtnClick;

@end

原生视图管理类处理

//
//  RCTCustomerMapViewManager.m
//  XSYMapView
//
//  Created by bear on 16/9/12.
//  Copyright © 2016年 Facebook. All rights reserved.
//

#import "RCTXSYCustomerMapViewManager.h"

@implementation RCTXSYCustomerMapViewManager

//导出视图的宏定义
RCT_EXPORT_MODULE()

//导出视图属性的宏定义
RCT_EXPORT_VIEW_PROPERTY(onBtnClick, RCTBubblingEventBlock)

- (UIView *)view
{
  return [[XSYCustomerMapView alloc] init];
}


@end

在React Native 中这么调用

//一般在render  方法中

<RCTXSYCustomerMapView {...this.props} onBtnClick={this.props.onBtnClick} />
阅读全文
none

对于原生定位的封装

摘要

此封装可用于IOS8.0以上. 注意: // 兼容iOS8.0版本 / Info.plist里面手动加上2项 NSLocationAlwaysUsageDescription YES NSLocationWhenInUseUsageDescription YES

.h

//
//  LBSManager.h
//  ingage
//
//  Created by bear on 16/9/19.
//  Copyright © 2016年 com. All rights reserved.
//

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

@interface LBSManager : NSObject<CLLocationManagerDelegate> {
    CLLocationManager *manager;
    
    // block的申明 定义
    void (^locationCallback) (double lat, double lng);
}

// 申明一个 cb的对象
+ (void) geLocaltion:(  void (^)(double lat, double lng) )cb;
+ (void) stop;

@end

.m

//
//  LBSManager.m
//  ingage
//
//  Created by bear on 16/9/19.
//  Copyright © 2016年 com. All rights reserved.
//

#import "LBSManager.h"



@implementation LBSManager



+ (id) sharedLBSManager{
    static id s;
    if (s == nil) {
        s = [[LBSManager alloc] init];
    }
    return s;
}
- (id)init {
    self = [super init];
    if (self) {
        // 打开定位 然后得到数据
        manager = [[CLLocationManager alloc] init];
        manager.delegate = self;
        manager.desiredAccuracy = kCLLocationAccuracyBest;
        
        // 兼容iOS8.0版本
        /* Info.plist里面加上2项
         NSLocationAlwaysUsageDescription      Boolean YES
         NSLocationWhenInUseUsageDescription   Boolean YES
         */
        
        // 请求授权 requestWhenInUseAuthorization用在>=iOS8.0上
        // respondsToSelector: 前面manager是否有后面requestWhenInUseAuthorization方法
        // 1. 适配 动态适配
        if ([manager respondsToSelector:@selector(requestWhenInUseAuthorization)]) {
            [manager requestWhenInUseAuthorization];
            [manager requestAlwaysAuthorization];
        }
        // 2. 另外一种适配 systemVersion 有可能是 8.1.1
        float osVersion = [[[UIDevice currentDevice] systemVersion] floatValue];
        if (osVersion >= 8) {
            [manager requestWhenInUseAuthorization];
            [manager requestAlwaysAuthorization];
        }
    }
    return self;
}
- (void) geLocaltion:(  void (^)(double lat, double lng) )cb {
    if ([CLLocationManager locationServicesEnabled] == FALSE) {
        return;
    }
    // block一般赋值需要copy
    locationCallback = [cb copy];
    
    // 停止上一次的
    [manager stopUpdatingLocation];
    // 开始新的数据定位
    [manager startUpdatingLocation];
}

+ (void) geLocaltion:(  void (^)(double lat, double lng) )cb {
    [[LBSManager sharedLBSManager] geLocaltion:cb];
}

- (void) stop {
    [manager stopUpdatingLocation];
}
+ (void) stop {
    [[LBSManager sharedLBSManager] stop];
}

// 每隔一段时间就会调用
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations {
    for (CLLocation *loc in locations) {
        CLLocationCoordinate2D l = loc.coordinate;
        double lat = l.latitude;
        double lnt = l.longitude;
        
        // 使用blocks 调用blocks
        if (locationCallback) {
            locationCallback(lat, lnt);
        }
    }
}

@end

使用

调用方式:
//只获取一次定位
        __block  BOOL isOnece = YES;
        [LBSManager geLocaltion:^(double lat, double lng) {
            isOnece = NO;
            
            //只打印一次经纬度
            NSLog(@"lat lng (%f, %f)", lat, lng);
            
            if (!isOnece) {
                [LBSManager stop];
            }
        }];

 //如果要一直持续获取定位则
    [LBSManager geLocaltion:^(double lat, double lng) {
        
        //不断的打印经纬度
        NSLog(@"lat lng (%f, %f)", lat, lng);
    }];
阅读全文
none

一些关于iOS10适配方面的问题

一些关于iOS10适配方面的问题,如果有错误,欢迎指出.

系统判断方法失效:

在你的项目中,当需要判断系统版本的话,不要使用下面的方法:

#define isiOS10 ([[[[UIDevice currentDevice] systemVersion] substringToIndex:1] intValue]>=10)

它会永远返回NO,substringToIndex:1在iOS 10 会被检测成 iOS 1了,
应该使用下面的这些方法:
Objective-C 中这样写:

#define SYSTEM_VERSION_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedSame)
#define SYSTEM_VERSION_GREATER_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedDescending)
#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] == NSOrderedAscending)
#define SYSTEM_VERSION_LESS_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedDescending)

或者使用:

if ([[NSProcessInfo processInfo] isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion){.majorVersion = 9, .minorVersion = 1, .patchVersion = 0}]) { NSLog(@"Hello from > iOS 9.1");}
if ([NSProcessInfo.processInfo isOperatingSystemAtLeastVersion:(NSOperatingSystemVersion){9,3,0}]) { NSLog(@"Hello from > iOS 9.3");}

或者使用:

if (NSFoundationVersionNumber > NSFoundationVersionNumber_iOS_9_0) { // do stuff for iOS 9 and newer} else { // do stuff for older versions than iOS 9}

有时候会缺少一些常量,NSFoundationVersionNumber是在NSObjCRuntime.h中定义的,作为Xcode7.3.1的一部分,我们设定常熟范围从iPhone OS 2到#define NSFoundationVersionNumber_iOS_8_4 1144.17,在iOS 10(Xcode 8)中,苹果补充了缺少的数字,设置有未来的版本.

#define NSFoundationVersionNumber_iOS_9_0 1240.1
#define NSFoundationVersionNumber_iOS_9_1 1241.14
#define NSFoundationVersionNumber_iOS_9_2 1242.12
#define NSFoundationVersionNumber_iOS_9_3 1242.12
#define NSFoundationVersionNumber_iOS_9_4 1280.25
#define NSFoundationVersionNumber_iOS_9_x_Max 1299

Swift中这样写:

if NSProcessInfo().isOperatingSystemAtLeastVersion(NSOperatingSystemVersion(majorVersion: 10, minorVersion: 0, patchVersion: 0)) { 
         // 代码块
}

或者使用

if #available(iOS 10.0, *) { 
         // 代码块
} else { 
         // 代码块
}

隐私数据访问问题:

这是因为iOS对用户的安全和隐私的增强,在申请很多私有权限的时候都需要添加描述,但是,在使用Xcode 8之前的Xcode还是使用系统的权限通知框.
要想解决这个问题,只需要在info.plist添加NSContactsUsageDescription的key, value自己随意填写就可以,这里列举出对应的key(Source Code模式下):

<!-- 相册 --> 
<key>NSPhotoLibraryUsageDescription</key> 
<string>App需要您的同意,才能访问相册</string> 
<!-- 相机 --> 
<key>NSCameraUsageDescription</key> 
<string>App需要您的同意,才能访问相机</string> 
<!-- 麦克风 --> 
<key>NSMicrophoneUsageDescription</key> 
<string>App需要您的同意,才能访问麦克风</string> 
<!-- 位置 --> 
<key>NSLocationUsageDescription</key> 
<string>App需要您的同意,才能访问位置</string> 
<!-- 在使用期间访问位置 --> 
<key>NSLocationWhenInUseUsageDescription</key> 
<string>App需要您的同意,才能在使用期间访问位置</string> 
<!-- 始终访问位置 --> 
<key>NSLocationAlwaysUsageDescription</key> 
<string>App需要您的同意,才能始终访问位置</string> 
<!-- 日历 --> 
<key>NSCalendarsUsageDescription</key> 
<string>App需要您的同意,才能访问日历</string> 
<!-- 提醒事项 --> 
<key>NSRemindersUsageDescription</key> 
<string>App需要您的同意,才能访问提醒事项</string> 
<!-- 运动与健身 --> 
<key>NSMotionUsageDescription</key> <string>App需要您的同意,才能访问运动与健身</string> 
<!-- 健康更新 --> 
<key>NSHealthUpdateUsageDescription</key> 
<string>App需要您的同意,才能访问健康更新 </string> 
<!-- 健康分享 --> 
<key>NSHealthShareUsageDescription</key> 
<string>App需要您的同意,才能访问健康分享</string> 
<!-- 蓝牙 --> 
<key>NSBluetoothPeripheralUsageDescription</key> 
<string>App需要您的同意,才能访问蓝牙</string> 
<!-- 媒体资料库 --> 
<key>NSAppleMusicUsageDescription</key> 
<string>App需要您的同意,才能访问媒体资料库</string>
如果不起作用,可以请求后台权限,类似于这样:

<key>UIBackgroundModes</key>
<array> 
<!-- 在这里写上你在后台模式下要使用权限对应的key --> 
<string>location</string>
...
</array>

或者在Xcode里选中当前的target,选择Capabilities,找到Background Modes,打开它,在里面选择对应权限

UIColor的问题

官方文档中说:大多数core开头的图形框架和AVFoundation都提高了对扩展像素和宽色域色彩空间的支持.通过图形堆栈扩展这种方式比以往支持广色域的显示设备更加容易。现在对UIKit扩展可以在sRGB的色彩空间下工作,性能更好,也可以在更广泛的色域来搭配sRGB颜色.如果你的项目中是通过低级别的api自己实现图形处理的,建议使用sRGB,也就是说在项目中使用了RGB转化颜色的建议转换为使用sRGB,在UIColor类中新增了两个api:

- (UIColor *)initWithDisplayP3Red:(CGFloat)displayP3Red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha NS_AVAILABLE_IOS(10_0);
+ (UIColor *)colorWithDisplayP3Red:(CGFloat)displayP3Red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha NS_AVAILABLE_IOS(10_0);

真彩色的显示

真彩色的显示会根据光感应器来自动的调节达到特定环境下显示与性能的平衡效果,如果需要这个功能的话,可以在info.plist里配置(在Source Code模式下):

<key>UIWhitePointAdaptivityStyle</key>
它有五种取值,分别是:

<string>UIWhitePointAdaptivityStyleStandard</string> // 标准模式
<string>UIWhitePointAdaptivityStyleReading</string> // 阅读模式
<string>UIWhitePointAdaptivityStylePhoto</string> // 图片模式
<string>UIWhitePointAdaptivityStyleVideo</string> // 视频模式
<string>UIWhitePointAdaptivityStyleStandard</string> // 游戏模式

也就是说如果你的项目是阅读类的,就选择UIWhitePointAdaptivityStyleReading这个模式,五种模式的显示效果是从上往下递减,也就是说如果你的项目是图片处理类的,你选择的是阅读模式,给选择太好的效果会影响性能.

ATS的问题

1.在iOS 9的时候,默认非HTTS的网络是被禁止的,我们可以在info.plist文件中添加NSAppTransportSecurity字典,将NSAllowsArbitraryLoads设置为YES来禁用ATS;
2.从2017年1月1日起,,所有新提交的 app 默认不允许使用NSAllowsArbitraryLoads来绕过ATS的限制,默认情况下你的 app 可以访问加密足够强的(TLS V1.2以上)HTTPS内容;
3.可以选择使用NSExceptionDomains设置白名单的方式对特定的域名开放HTTP内容来通过审核,比如说你的应用集成了第三方的登录分享SDK,可以通过这种方式来做,下面以新浪SDK作为示范(Source Code 模式下):

 <key>NSAppTransportSecurity</key>
 <dict>
  <key>NSExceptionDomains</key>
  <dict>
   <key>sina.cn</key>
   <dict>
    <key>NSThirdPartyExceptionMinimumTLSVersion</key>
    <string>TLSv1.0</string>
    <key>NSThirdPartyExceptionRequiresForwardSecrecy</key>
    <false/>
    <key>NSIncludesSubdomains</key>
    <true/>
   </dict>
   <key>weibo.cn</key>
   <dict>
    <key>NSThirdPartyExceptionMinimumTLSVersion</key>
    <string>TLSv1.0</string>
    <key>NSThirdPartyExceptionRequiresForwardSecrecy</key>
    <false/>
    <key>NSIncludesSubdomains</key>
    <true/>
   </dict>
   <key>weibo. com</key>
   <dict>
    <key>NSThirdPartyExceptionMinimumTLSVersion</key>
    <string>TLSv1.0</string>
    <key>NSThirdPartyExceptionRequiresForwardSecrecy</key>
    <false/>
    <key>NSIncludesSubdomains</key>
    <true/>
   </dict>
   <key>sinaimg.cn</key>
   <dict>
    <key>NSThirdPartyExceptionMinimumTLSVersion</key>
    <string>TLSv1.0</string>
    <key>NSThirdPartyExceptionRequiresForwardSecrecy</key>
    <false/>
    <key>NSIncludesSubdomains</key>
    <true/>
   </dict>
   <key>sinajs.cn</key>
   <dict>
    <key>NSThirdPartyExceptionMinimumTLSVersion</key>
    <string>TLSv1.0</string>
    <key>NSThirdPartyExceptionRequiresForwardSecrecy</key>
    <false/>
    <key>NSIncludesSubdomains</key>
    <true/>
   </dict>
   <key>sina.com.cn</key>
   <dict>
    <key>NSThirdPartyExceptionMinimumTLSVersion</key>
    <string>TLSv1.0</string>
    <key>NSThirdPartyExceptionRequiresForwardSecrecy</key>
    <false/>
    <key>NSIncludesSubdomains</key>
    <true/>
   </dict>
  </dict>
 </dict>

在iOS 10 中info.plist文件新加入了

NSAllowsArbitraryLoadsInWebContent键,允许任意web页面加载,同时苹果会用 ATS 来保护你的app;

安全传输不再支持SSLv3, 建议尽快停用SHA1和3DES算法;

UIStatusBar的问题:

在iOS10中,如果还使用以前设置UIStatusBar类型或者控制隐藏还是显示的方法,会报警告,方法过期,如下图:

上面方法到 iOS 10 不能使用了,要想修改UIStatusBar的样式或者状态使用下图中所示的属性或方法:

@property(nonatomic, readonly) UIStatusBarStyle preferredStatusBarStyle NS_AVAILABLE_IOS(7_0) __TVOS_PROHIBITED; // Defaults to UIStatusBarStyleDefault
@property(nonatomic, readonly) BOOL prefersStatusBarHidden NS_AVAILABLE_IOS(7_0) __TVOS_PROHIBITED; // Defaults to NO
- (UIStatusBarStyle)preferredStatusBarStyle NS_AVAILABLE_IOS(7_0) __TVOS_PROHIBITED; // Defaults to UIStatusBarStyleDefault
- (BOOL)prefersStatusBarHidden NS_AVAILABLE_IOS(7_0) __TVOS_PROHIBITED; // Defaults to NO
// Override to return the type of animation that should be used for status bar changes for this view controller. This currently only affects changes to prefersStatusBarHidden.
- (UIStatusBarAnimation)preferredStatusBarUpdateAnimation NS_AVAILABLE_IOS(7_0) __TVOS_PROHIBITED; // Defaults to UIStatusBarAnimationFade

UITextField

在iOS 10 中,UITextField新增了textContentType字段,是UITextContentType类型,它是一个枚举,作用是可以指定输入框的类型,以便系统可以分析出用户的语义.是电话类型就建议一些电话,是地址类型就建议一些地址.可以在#import <UIKit/UITextInputTraits.h>文件中,查看textContentType字段,有以下可以选择的类型:

UIKIT_EXTERN UITextContentType const UITextContentTypeName                      NS_AVAILABLE_IOS(10_0);
UIKIT_EXTERN UITextContentType const UITextContentTypeNamePrefix                NS_AVAILABLE_IOS(10_0);
UIKIT_EXTERN UITextContentType const UITextContentTypeGivenName                 NS_AVAILABLE_IOS(10_0);
UIKIT_EXTERN UITextContentType const UITextContentTypeMiddleName                NS_AVAILABLE_IOS(10_0);
UIKIT_EXTERN UITextContentType const UITextContentTypeFamilyName                NS_AVAILABLE_IOS(10_0);
UIKIT_EXTERN UITextContentType const UITextContentTypeNameSuffix                NS_AVAILABLE_IOS(10_0);
UIKIT_EXTERN UITextContentType const UITextContentTypeNickname                  NS_AVAILABLE_IOS(10_0);
UIKIT_EXTERN UITextContentType const UITextContentTypeJobTitle                  NS_AVAILABLE_IOS(10_0);
UIKIT_EXTERN UITextContentType const UITextContentTypeOrganizationName          NS_AVAILABLE_IOS(10_0);
UIKIT_EXTERN UITextContentType const UITextContentTypeLocation                  NS_AVAILABLE_IOS(10_0);
UIKIT_EXTERN UITextContentType const UITextContentTypeFullStreetAddress         NS_AVAILABLE_IOS(10_0);
UIKIT_EXTERN UITextContentType const UITextContentTypeStreetAddressLine1        NS_AVAILABLE_IOS(10_0);
UIKIT_EXTERN UITextContentType const UITextContentTypeStreetAddressLine2        NS_AVAILABLE_IOS(10_0);
UIKIT_EXTERN UITextContentType const UITextContentTypeAddressCity               NS_AVAILABLE_IOS(10_0);
UIKIT_EXTERN UITextContentType const UITextContentTypeAddressState              NS_AVAILABLE_IOS(10_0);
UIKIT_EXTERN UITextContentType const UITextContentTypeAddressCityAndState       NS_AVAILABLE_IOS(10_0);
UIKIT_EXTERN UITextContentType const UITextContentTypeSublocality               NS_AVAILABLE_IOS(10_0);
UIKIT_EXTERN UITextContentType const UITextContentTypeCountryName               NS_AVAILABLE_IOS(10_0);
UIKIT_EXTERN UITextContentType const UITextContentTypePostalCode                NS_AVAILABLE_IOS(10_0);
UIKIT_EXTERN UITextContentType const UITextContentTypeTelephoneNumber           NS_AVAILABLE_IOS(10_0);
UIKIT_EXTERN UITextContentType const UITextContentTypeEmailAddress              NS_AVAILABLE_IOS(10_0);
UIKIT_EXTERN UITextContentType const UITextContentTypeURL                       NS_AVAILABLE_IOS(10_0);
UIKIT_EXTERN UITextContentType const UITextContentTypeCreditCardNumber          NS_AVAILABLE_IOS(10_0);

UserNotifications(用户通知)

iOS 10 中将通知相关的 API 都统一了,在此基础上很多用户定义的通知,并且可以捕捉到各个通知状态的回调.以前通知的概念是:大家想接受的提前做好准备,然后一下全两分发,没收到也不管了,也不关心发送者,现在的用户通知做成了类似于网络请求,先发一个request得到response的流程,还封装了error,可以在各个状态的方法中做一些额外的操作,并且能获得一些字段,比如发送者之类的.这个功能的头文件是:#import <UserNotifications/UserNotifications.h>
主要有以下文件:

#import <UserNotifications/NSString+UserNotifications.h>
#import <UserNotifications/UNError.h>
#import <UserNotifications/UNNotification.h>
#import <UserNotifications/UNNotificationAction.h>
#import <UserNotifications/UNNotificationAttachment.h>
#import <UserNotifications/UNNotificationCategory.h>
#import <UserNotifications/UNNotificationContent.h>
#import <UserNotifications/UNNotificationRequest.h>
#import <UserNotifications/UNNotificationResponse.h>
#import <UserNotifications/UNNotificationSettings.h>
#import <UserNotifications/UNNotificationSound.h>
#import <UserNotifications/UNNotificationTrigger.h>
#import <UserNotifications/UNUserNotificationCenter.h>
#import <UserNotifications/UNNotificationServiceExtension.h>

UICollectionViewCell的的优化

在iOS 10 之前,UICollectionView上面如果有大量cell,当用户活动很快的时候,整个UICollectionView的卡顿会很明显,为什么会造成这样的问题,这里涉及到了iOS 系统的重用机制,当cell准备加载进屏幕的时候,整个cell都已经加载完成,等待在屏幕外面了,也就是整整一行cell都已经加载完毕,这就是造成卡顿的主要原因,专业术语叫做:掉帧.
要想让用户感觉不到卡顿,我们的app必须帧率达到60帧/秒,也就是说每帧16毫秒要刷新一次.

iOS 10 之前UICollectionViewCell的生命周期是这样的:
1.用户滑动屏幕,屏幕外有一个cell准备加载进来,把cell从reusr队列拿出来,然后调用prepareForReuse方法,在这个方法里面,可以重置cell的状态,加载新的数据;
2.继续滑动,就会调用cellForItemAtIndexPath方法,在这个方法里面给cell赋值模型,然后返回给系统;
3.当cell马上进去屏幕的时候,就会调用willDisplayCell方法,在这个方法里面我们还可以修改cell,为进入屏幕做最后的准备工作;
4.执行完willDisplayCell方法后,cell就进去屏幕了.当cell完全离开屏幕以后,会调用didEndDisplayingCell方法.
iOS 10 UICollectionViewCell的生命周期是这样的:
1.用户滑动屏幕,屏幕外有一个cell准备加载进来,把cell从reusr队列拿出来,然后调用prepareForReuse方法,在这里当cell还没有进去屏幕的时候,就已经提前调用这个方法了,对比之前的区别是之前是cell的上边缘马上进去屏幕的时候就会调用该方法,而iOS 10 提前到cell还在屏幕外面的时候就调用;
2.在cellForItemAtIndexPath中创建cell,填充数据,刷新状态等操作,相比于之前也提前了;
3.用户继续滑动的话,当cell马上就需要显示的时候我们再调用willDisplayCell方法,原则就是:何时需要显示,何时再去调用willDisplayCell方法;
4.当cell完全离开屏幕以后,会调用didEndDisplayingCell方法,跟之前一样,cell会进入重用队列.
在iOS 10 之前,cell只能从重用队列里面取出,再走一遍生命周期,并调用cellForItemAtIndexPath创建或者生成一个cell.
在iOS 10 中,系统会cell保存一段时间,也就是说当用户把cell滑出屏幕以后,如果又滑动回来,cell不用再走一遍生命周期了,只需要调用willDisplayCell方法就可以重新出现在屏幕中了.
iOS 10 中,系统是一个一个加载cell的,二以前是一行一行加载的,这样就可以提升很多性能;
iOS 10 新增加的Pre-Fetching预加载
这个是为了降低UICollectionViewCell在加载的时候所花费的时间,在 iOS 10 中,除了数据源协议和代理协议外,新增加了一个
UICollectionViewDataSourcePrefetching协议,这个协议里面定义了两个方法:

- (void)collectionView:(UICollectionView *)collectionView prefetchItemsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths NS_AVAILABLE_IOS(10_0);

- (void)collectionView:(UICollectionView *)collectionView cancelPrefetchingForItemsAtIndexPaths:(NSArray<NSIndexPath *> *)indexPaths  NS_AVAILABLE_IOS(10_0);

在ColletionView prefetchItemsAt indexPaths这个方法是异步预加载数据的,当中的indexPaths数组是有序的,就是item接收数据的顺序;
CollectionView cancelPrefetcingForItemsAt indexPaths这个方法是可选的,可以用来处理在滑动中取消或者降低提前加载数据的优先级.
注意:这个协议并不能代替之前读取数据的方法,仅仅是辅助加载数据.
Pre-Fetching预加载对UITableViewCell同样适用.

UIRefreshControl的使用

在iOS 10 中, UIRefreshControl可以直接在UICollectionView和UITableView中使用,并且脱离了UITableViewController.现在RefreshControl是UIScrollView的一个属性.
使用方法:

UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init];
    [refreshControl addTarget:self action:@selector(loadData) forControlEvents:UIControlEventValueChanged];
    collectionView.refreshControl = refreshControl;
阅读全文
none

React-Native 常见错误及其原因

1.invariant violation:expected a component class,got[object object]

创建自定义组件首字母要大写,否则会报错.

 2.Module 0 is not a registered callable module.

将gradle升级成最新版本(cd Android 进入android目录执行:sudo ./gradlew clean) 或者通过android studio工具升级.

 3.android.view.WindowManager$BadTokenException: Unable to add window -- token null is not valid; is your activity running?

该错误属于安卓Native的错误,如果引用的Activity不存在或者已经销毁,再次引用就会报该错误,如果是React Native 调用原生控件的话,创建控件需要引用:getCurrentActivity()

 4.android.app.Application cannot be cast to com.facebook.React.ReactApplication

需要将创建的MainApplication在AndroidManifest.xml配置好.

 5.Element type is invalid: expected a string (for built-in components) or a class/function but got: object

发生原生一般是你引用了无效的组件,如果组件确实正确,看下引用的组件是否正常导出:(export defalut)

6.react native  undefined is not an object (evaluating this....

发生该错误的一般是忘记bind(this),只要回调函数中需要用到this的,一般都需要bind.

7.react native - expected a component class, got [object Object]

该错误可能是你引用了小写的组件,组件首字母一定要大写,比如<login/>应该写成<Login/>

阅读全文
none