前言:贝塞尔曲线又称贝兹曲线,它的主要意义在于无论是直线或曲线都能在数学上予以描述。最初由保罗·德卡斯特里奥(Paul de Casteljau)于1959年运用德卡斯特里奥演算法开发(de Casteljau Algorithm),在1962,由法国工程师皮埃尔·贝塞尔(Pierre Bézier)所广泛发表。目前广泛应用于图形绘制领域来模拟光滑曲线,为计算机矢量图形学奠定了基础。在一些图形处理软件中都能见到贝塞尔曲线,比如CorelDraw中翻译成“贝赛尔工具”;而在Fireworks中叫“画笔”;Photoshop中叫“钢笔工具”。下图为Photoshop中用钢笔绘制的贝塞尔曲线,共绘制了三条贝塞尔曲线:数学表达术语:数据点、控制线、控制点、德卡斯特里奥算法、一阶,二阶,三阶,n阶…… 数据点:一条贝塞尔曲线的起始点和终结点都叫数据点。 控制线:在图中可以看到那条中心点为数据点的线段,每个数据点对应一条控制线 控制点:就是控制线的端点,通过控制线随着控制点的变化而变化;数据点和控制点决定一条贝塞尔曲线。 一阶贝塞尔曲线:其实是一条直线段,没有控制点。一阶贝塞尔曲线示意图一阶贝塞尔曲线公式二阶贝塞尔曲线:图中第二段为二阶贝塞尔曲线,只有一个控制点,即只有一个控制点和两个数据点来决定曲线形状。二阶贝塞尔曲线公式二阶公式推导:二阶贝塞尔曲线t=0.6示意图.gif根据控制点和数据点,对贝塞尔曲线进行约束,满足的条件为问题变为:已知P0(x0,y0), P1(x1,y1), P2(x2,y2),根据上式求P点坐标?先求出A、B点坐标,其坐标PA=P0+(P1-P0)·tPB=P1+(P2-P1)·t之后求P点坐标,其坐标P=PA+(PB-PA)·tP=(1-t)2P0+2t(1-t)P1+t2P2, t∈[0,1]三阶贝塞尔曲线:图中第三段为三阶贝塞尔曲线,有两个控制点和两个数据点决定的曲线,同样满足等比条件:三阶贝塞尔曲线三阶贝塞尔曲线公式德卡斯特里奥算法的思想:给定数据点和控制点P0、P1…Pn,首先将数据点和控制点连接形成一条折线,计算出每条折线上面的一点,使得初始数据点(初始控制点)到该点的距离与初始数据点(初始控制点)到终止数据点(终止控制点)的距离之比为t:1。将这些点连接起来形成新的折线(折线少了一段),用递归的算法继续计算,指导只有两个点,在这两个点形成的线段上去一点,满足以上的比例关系。随着t的从0到1的变化,该点的集合形成了贝塞尔曲线。n阶贝塞尔曲线公式如下。Android中的应用对android中如何获取贝塞尔曲线上的点,如何绘制贝塞尔曲线,以及结合贝塞尔曲线的知识做出的效果进行分析。1. 获取贝塞尔曲线上点的坐标在android中并没有直接获取的方法,因此需要利用上面的公式进行计算,以二阶贝塞尔曲线为例,获取51个点,主要是t从0开始到1间取51项的等差数列:public class MainActivity extends AppCompatActivity { private static final float mPointNum = 50f; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); init(); } private void init() { PointF mStartPoint = new PointF(0, 0); PointF mEndPoint = new PointF(0, 1200); PointF mControlPoint = new PointF(500, 600); List<PointF> mPointList = new ArrayList<>(); for (int i = 0; i <= mPointNum; i++) { mPointList.add(getBezierPoint(mStartPoint, mEndPoint, mControlPoint, i / mPointNum)); Log.d("Bezier", "X:" + mPointList.get(i).x + " Y:" + mPointList.get(i).y); } } private PointF getBezierPoint(PointF start, PointF end, PointF control, float t) { PointF bezierPoint = new PointF(); bezierPoint.x = (1 - t) * (1 - t) * start.x + 2 * t * (1 - t) * control.x + t * t * end.x; bezierPoint.y = (1 - t) * (1 - t) * start.y + 2 * t * (1 - t) * control.y + t * t * end.y; return bezierPoint; }}如果需要更高阶,可以使用递归函数来运算//用递归获取贝塞尔曲线点的x轴坐标private float getBezierPointX(int n, int position, float t) { if (n == 1) { return (1 - t) * mPointList.get(position).x + t * mPointList.get(position + 1).x; } return (1 - t) * getBezierPointX(n - 1, position, t) + t * getBezierPointX(n - 1, position + 1, t); }//用递归获取贝塞尔曲线点的x轴坐标private float getBezierPointX(int n, int position, float t) { if (n == 1) { return (1 - t) * mPointList.get(position).x + t * mPointList.get(position + 1).x; } return (1 - t) * getBezierPointX(n - 1, position, t) + t * getBezierPointX(n - 1, position + 1, t); }private ArrayList<PointF> buildBezierPoints() { ArrayList<PointF> points = new ArrayList<>(); int order = mPointList.size() - 1; float delta = 1.0f / POINT_NUM; for (float t = 0; t <= 1; t += delta) { // Bezier点集 points.add(new PointF(getBezierPointX(order, 0, t), getBezierPointY(order, 0, t))); } return points; }2. 绘制贝塞尔曲线Android 中的Path类可以直接绘制一阶到三阶的贝塞尔曲线,在onDraw(Canvas canvas) 方法中使用:绘制一阶贝塞尔曲线:canvas.drawLine(start.x,start.y,end.x,end.y);绘制二阶贝塞尔曲线:mPath.moveTo(startPoint.x, startPoint.y);//起点mPath.quadTo(controlPoint1.x, controlPoint1.y, endPoint.x, endPoint.y);canvas.drawPath(mPath, mPaint);绘制三阶贝塞尔曲线:mPath.moveTo(startPoint.x, startPoint.y);//起点mPath.cubicTo(controlPoint1.x, controlPoint1.y, controlPoint2.x, controlPoint2.y, endPoint.x, endPoint.y);canvas.drawPath(mPath, mPaint);绘制n阶贝塞尔曲线n阶贝塞尔曲线绘制,需要结合递归函数,设定一条曲线由多少个点组成,通过循环获取每个点的坐标进行绘制。7阶贝塞尔曲线8阶贝塞尔曲线3.Demo贝塞尔曲线在android中最常用的是做出一些动画特效,如QQ消息数拖拽形变效果,一些炫酷的下拉刷新控件,阅读软件的翻书效果,一些平滑的折线图的制作,某图片的运动轨迹等……3.1 形状变形只需要知道变形前和变形后图形的数据点和控制点即可,通过改变数据点和控制点使得形状发生改变。初始化 private float[] mData = new float[8]; // 顺时针记录绘制圆形的四个数据点 private float[] mCtrl = new float[16]; // 顺时针记录绘制圆形的八个控制点 private float mDuration = 1000; // 变化总时长 private float mCurrent = 0; // 当前已进行时长 private float mCount = 100; // 将时长总共划分多少份 private float mPiece = mDuration / mCount; // 每一份的时长在onDraw(Canvas canvas)方法中绘制 path.reset(); path.moveTo(mData[0], mData[1]); path.cubicTo(mCtrl[0], mCtrl[1], mCtrl[2], mCtrl[3], mData[2], mData[3]); path.cubicTo(mCtrl[4], mCtrl[5], mCtrl[6], mCtrl[7], mData[4], mData[5]); path.cubicTo(mCtrl[8], mCtrl[9], mCtrl[10], mCtrl[11], mData[6], mData[7]); path.cubicTo(mCtrl[12], mCtrl[13], mCtrl[14], mCtrl[15], mData[0], mData[1]); canvas.drawPath(path, mPaint); mCurrent += mPiece; if (mCurrent < mDuration) { mData[1] -= 120 / mCount; mCtrl[7] += 80 / mCount; mCtrl[9] += 80 / mCount; mCtrl[4] -= 20 / mCount; mCtrl[10] += 20 / mCount; postInvalidateDelayed((long) mPiece); }3.2 漂浮的爱心爱心的漂浮轨迹就是一条三阶贝塞尔曲线,结合属性动画中的估值器进行设置。首先定义一个属性动画的估值器public class BezierEvaluator implements TypeEvaluator<PointF> { private PointF mControlP1; private PointF mControlP2; public BezierEvaluator(PointF controlP1, PointF controlP2) { this.mControlP1 = controlP1; this.mControlP2 = controlP2; } @Override public PointF evaluate(float time, PointF start, PointF end) { float timeLeft = 1.0f - time; PointF point = new PointF(); point.x = timeLeft * timeLeft * timeLeft * (start.x) + 3 * timeLeft * timeLeft * time * (mControlP1.x) + 3 * timeLeft * time * time * (mControlP2.x) + time * time * time * (end.x); point.y = timeLeft * timeLeft * timeLeft * (start.y) + 3 * timeLeft * timeLeft * time * (mControlP1.y) + 3 * timeLeft * time * time * (mControlP2.y) + time * time * time * (end.y); return point; }}之后自定义一个view可以生成爱心,添加透明度,缩放等动画和根据贝塞尔曲线改变其位置的属性动画。初始化爱心图片和多个插值器等,到时随即选取 private void init() { // 初始化显示的图片 drawables = new Drawable[3]; drawables[0] = getResources().getDrawable(R.drawable.red); drawables[1] = getResources().getDrawable(R.drawable.yellow); drawables[2] = getResources().getDrawable(R.drawable.green); // 初始化插补器 mInterpolators = new Interpolator[4]; mInterpolators[0] = new LinearInterpolator();// 线性 mInterpolators[1] = new AccelerateInterpolator();// 加速 mInterpolators[2] = new DecelerateInterpolator();// 减速 mInterpolators[3] = new AccelerateDecelerateInterpolator();// 先加速后减速 // 底部 并且 水平居中 dWidth = drawables[0].getIntrinsicWidth(); dHeight = drawables[0].getIntrinsicHeight(); lp = new LayoutParams(dWidth, dHeight); lp.addRule(CENTER_HORIZONTAL, TRUE);// 这里的TRUE 要注意 不是true lp.addRule(ALIGN_PARENT_BOTTOM, TRUE); }入场动画private AnimatorSet getEnterAnimator(final View target) { ObjectAnimator alpha = ObjectAnimator.ofFloat(target, View.ALPHA, 0.2f, 1f); ObjectAnimator scaleX = ObjectAnimator.ofFloat(target, View.SCALE_X, 0.2f, 1f); ObjectAnimator scaleY = ObjectAnimator.ofFloat(target, View.SCALE_Y, 0.2f, 1f); AnimatorSet enter = new AnimatorSet(); enter.setTarget(target); enter.setInterpolator(new LinearInterpolator()); enter.setDuration(500).playTogether(alpha, scaleX, scaleY); return enter; }贝塞尔曲线动画 private ValueAnimator getBezierValueAnimator(final View target) { // 初始化贝塞尔估值器 BezierEvaluator evaluator = new BezierEvaluator(getPointF(2), getPointF(1)); // 起点在底部中心位置,终点在底部随机一个位置 ValueAnimator animator = ValueAnimator.ofObject(evaluator, new PointF((mWidth - dWidth) / 2, mHeight - dHeight), new PointF(random.nextInt(getWidth()), 0)); animator.setTarget(target); animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator valueAnimator) { // 这里获取到贝塞尔曲线计算出来的的x y值 赋值给view 这样就能让爱心随着曲线走啦 PointF pointF = (PointF) valueAnimator.getAnimatedValue(); target.setX(pointF.x); target.setY(pointF.y); // alpha动画 target.setAlpha(1 - valueAnimator.getAnimatedFraction()); } }); animator.setDuration(3000); return animator; }结合动画添加爱心public void addHeart() { final ImageView imageView = new ImageView(getContext()); // 随机选一个爱心 imageView.setImageDrawable(drawables[random.nextInt(3)]); imageView.setLayoutParams(lp); addView(imageView); AnimatorSet finalSet = new AnimatorSet(); AnimatorSet enterAnimatorSet = getEnterAnimator(imageView);//入场动画 ValueAnimator bezierValueAnimator = getBezierValueAnimator(imageView);//贝塞尔曲线路径动画 finalSet.playSequentially(enterAnimatorSet, bezierValueAnimator); finalSet.setInterpolator(mInterpolators[random.nextInt(4)]); finalSet.setTarget(imageView); finalSet.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { super.onAnimationEnd(animation); removeView((imageView));//删除爱心 } }); finalSet.start(); }3.3 贝塞尔曲线侧边索引条实例地址:FancyListIndexer_jb51.rar以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

一、NSthread的初始化1.动态方法复制代码 代码如下:- (id)initWithTarget:(id)target selector:(SEL)selector object:(id)argument;  // 初始化线程  NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];  // 设置线程的优先级(0.0 - 1.0,1.0最高级)  thread.threadPriority = 1;  // 开启线程  [thread start];  参数解析:selector :线程执行的方法,这个selector最多只能接收一个参数target :selector消息发送的对象argument : 传给selector的唯一参数,也可以是nil2.静态方法复制代码 代码如下:+ (void)detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(id)argument;  [NSThread detachNewThreadSelector:@selector(run) toTarget:self withObject:nil];  // 调用完毕后,会马上创建并开启新线程  3.隐式创建线程的方法复制代码 代码如下:[self performSelectorInBackground:@selector(run) withObject:nil];  二、获取当前线程复制代码 代码如下:NSThread *current = [NSThread currentThread]; 三、获取主线程复制代码 代码如下:NSThread *main = [NSThread mainThread]; 四、暂停当前线程复制代码 代码如下:// 暂停2s  [NSThread sleepForTimeInterval:2];    // 或者  NSDate *date = [NSDate dateWithTimeInterval:2 sinceDate:[NSDate date]];  [NSThread sleepUntilDate:date];  五、线程间的通信1.在指定线程上执行操作复制代码 代码如下:[self performSelector:@selector(run) onThread:thread withObject:nil waitUntilDone:YES];  2.在主线程上执行操作复制代码 代码如下:[self performSelectorOnMainThread:@selector(run) withObject:nil waitUntilDone:YES];  3.在当前线程执行操作复制代码 代码如下:[self performSelector:@selector(run) withObject:nil];  六、优缺点1.优点:NSThread比其他两种多线程方案较轻量级,更直观地控制线程对象2.缺点:需要自己管理线程的生命周期,线程同步。线程同步对数据的加锁会有一定的系统开销七、下载图片的例子:新建singeView app新建项目,并在xib文件上放置一个imageView控件。按住control键拖到viewController.h文件中创建imageView IBOutlet ViewController.m中实现:复制代码 代码如下://  //  ViewController.m  //  NSThreadDemo  //  //  Created by rongfzh on 12-9-23.  //  Copyright (c) 2012年 rongfzh. All rights reserved.  //    #import "ViewController.h"  #define kURL @"http://avatar.csdn.net/2/C/D/1_totogo2010.jpg"  @interface ViewController ()    @end  复制代码 代码如下:  @implementation ViewController    -(void)downloadImage:(NSString *) url{      NSData *data = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:url]];      UIImage *image = [[UIImage alloc]initWithData:data];      if(image == nil){                }else{          [self performSelectorOnMainThread:@selector(updateUI:) withObject:image waitUntilDone:YES];      }  }    -(void)updateUI:(UIImage*) image{      self.imageView.image = image;  }      - (void)viewDidLoad  {      [super viewDidLoad];        //    [NSThread detachNewThreadSelector:@selector(downloadImage:) toTarget:self withObject:kURL];      NSThread *thread = [[NSThread alloc]initWithTarget:self selector:@selector(downloadImage:) object:kURL];      [thread start];  }    - (void)didReceiveMemoryWarning  {      [super didReceiveMemoryWarning];      // Dispose of any resources that can be recreated.  }    @end  线程间通讯线程下载完图片后怎么通知主线程更新界面呢?复制代码 代码如下:[self performSelectorOnMainThread:@selector(updateUI:) withObject:image waitUntilDone:YES];performSelectorOnMainThread是NSObject的方法,除了可以更新主线程的数据外,还可以更新其他线程的比如:用:复制代码 代码如下:performSelector:onThread:withObject:waitUntilDone: 运行下载图片:图片下载下来了。

获取本机IP地址public String getLocalIpAddress() { WifiManager wifiManager = (WifiManager) getSystemService(android.content.Context.WIFI_SERVICE);WifiInfo wifiInfo = wifiManager.getConnectionInfo();int ipAddress = wifiInfo.getIpAddress();try {return InetAddress.getByName(String.format("%d.%d.%d.%d",(ipAddress & 0xff), (ipAddress >> 8 & 0xff),(ipAddress >> 16 & 0xff), (ipAddress >> 24 & 0xff))).toString();} catch (UnknownHostException e) {// TODO Auto-generated catch blocke.printStackTrace();}return null;}获取本机的物理地址public String getLocalMacAddress() {WifiManager wifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);WifiInfo info = wifi.getConnectionInfo();return info.getMacAddress();}以上就是Android 获取手机 IP和MAC地址的方法,希望能帮助到读者,谢谢大家对本站的支持!

前言最近因为工作的需要,要自定义展示Wifi信号强弱的需要,就通过利用系统广播的方式实现了一个自定义View——WifiStateView,下面话不多说了,感兴趣的朋友们一起来看看详细的介绍吧。实现的效果图如下所示:用不同的图片来表示Wifi信号的强弱,可以自定义Wifi信号等级图标简陋了点,根据需要来替换即可/** * 作者: 叶应是叶 * 时间: 2017/8/22 18:25 * 描述: */public class WifiStateView extends AppCompatImageView { private WifiManager wifiManager; private WifiHandler wifiHandler; //没有开启Wifi或开启了Wifi但没有连接 private static final int LEVEL_NONE = 0; //Wifi信号等级(最弱) private static final int LEVEL_1 = 1; //Wifi信号等级 private static final int LEVEL_2 = 2; //Wifi信号等级 private static final int LEVEL_3 = 3; //Wifi信号等级(最强) private static final int LEVEL_4 = 4; private final String TAG = "WifiStateView"; private static class WifiHandler extends Handler { //虚引用 private WeakReference<WifiStateView> stateViewWeakReference; WifiHandler(WifiStateView wifiStateView) { stateViewWeakReference = new WeakReference<>(wifiStateView); } @Override public void handleMessage(Message msg) { WifiStateView wifiStateView = stateViewWeakReference.get(); if (wifiStateView == null) { return; } switch (msg.what) { case LEVEL_1: wifiStateView.setImageResource(R.drawable.wifi_1); break; case LEVEL_2: wifiStateView.setImageResource(R.drawable.wifi_2); break; case LEVEL_3: wifiStateView.setImageResource(R.drawable.wifi_3); break; case LEVEL_4: wifiStateView.setImageResource(R.drawable.wifi_4); break; case LEVEL_NONE: default: wifiStateView.setImageResource(R.drawable.wifi_none); break; } } } private BroadcastReceiver wifiStateReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { Log.e(TAG, "action " + intent.getAction()); switch (intent.getAction()) { case WifiManager.WIFI_STATE_CHANGED_ACTION: if (wifiManager.getWifiState() == WifiManager.WIFI_STATE_DISABLING) { wifiHandler.sendEmptyMessage(LEVEL_NONE); } break; case WifiManager.RSSI_CHANGED_ACTION: if (wifiManager.getWifiState() == WifiManager.WIFI_STATE_DISABLED) { wifiHandler.sendEmptyMessage(LEVEL_NONE); return; } WifiInfo wifiInfo = wifiManager.getConnectionInfo(); int level = WifiManager.calculateSignalLevel(wifiInfo.getRssi(), 5); Log.e(TAG, "level:" + level); wifiHandler.sendEmptyMessage(level); break; } } }; public WifiStateView(Context context) { this(context, null); } public WifiStateView(Context context, @Nullable AttributeSet attrs) { this(context, attrs, 0); } public WifiStateView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); wifiManager = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE); wifiHandler = new WifiHandler(this); } @Override protected void onAttachedToWindow() { super.onAttachedToWindow(); IntentFilter intentFilter = new IntentFilter(); //Wifi连接状态变化 intentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); //Wifi信号强度变化 intentFilter.addAction(WifiManager.RSSI_CHANGED_ACTION); getContext().registerReceiver(wifiStateReceiver, intentFilter); } @Override protected void onDetachedFromWindow() { super.onDetachedFromWindow(); wifiHandler.removeCallbacksAndMessages(null); getContext().unregisterReceiver(wifiStateReceiver); }}这里提供代码下载:github地址:https://github.com/leavesC/WifiStateView本地下载:http://xiazai.jb51.net/201708/yuanma/WifiStateView(jb51.net).rar总结以上就是这篇文章的全部内容了,希望本文的内容对各位Android开发者们的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对脚本之家的支持。

本文主要是一些对iOS新功能的探索,之前发现博客里关于iOS新功能的分析大多是过于概括,每个功能几句话,无法了解到具体的功能。所以本次的探索是基于Api层面,着重看一些具体用法所做的笔记,本来想分别画个类图来着,后来还是觉得太耗时而放弃。如果不想把苹果iOSSDK里的.h文件都摆出来详细读,那看这篇笔记应该是个不错的选择。 本文以文档的目录为基础,提到的功能模块有: Proactive Suggestions Integrating with the Messages App User Notifications Speech Recognition Wide Color Adapting to the True Tone Display App Search Enhancements Widget Enhancements Security and Privacy Enhancements还没有详细探索的模块是SiriKit CallKit (工作职能和这里联系不多,还不care这里)Apple Pay Enhancements (工作职能和这里联系不多,还不care这里)SiriKit   SiriKit的功能非常强大,支持音频、视频、消息发送接收、搜索照片、预订行程、管理锻炼等等。在用到此服务时,siri会发送Intent对象,里面包括用户的请求和各种数据,可以对这个intent处理选择适当的响应。 这个功能主要是看这两个头文件(#import <Intents/Intents.h>、#import <IntentsUI/IntentsUI.h>)所涵盖到的类太多,前期先略过了,之后等iOS10可以推送更新了再做进一步调研。 Proactive Suggestions 系统预先建议 背景就是iOS9的时候系统给予的主动建议会通过:Spolight搜索,Safari搜索,Handoff,或者siri建议。 在iOS10之后新增了,键盘QuickType建议,地图,车载娱乐,应用切换,siri交互,锁屏播放。 比如你正在一个应用里看一个酒店,可以使用mapitem属性保存正在查看的这个酒店的位置,然后你切换旅行或地图App时这个位置可以自动提供使用。  如果你需要这样利用系统来共享一个位置,那你需要指定这个位置的经纬度,地名,电话等属性 来便于siri的直接调起。 文档中还列出了几种场景 1.在输入框(UITextFiled)输入时,可以指定一下这个输入框的类型,以便系统可以分析出用户的语义。 是电话类型就建议一些电话,是地址类型就建议一些地址。看下头文件(#import <UIKit/UITextInputTraits.h>)可指定的类型 就是这个新增的textContentType字段,里面有很多种类型可选。 UIKIT_EXTERN NSString *const UITextContentTypeName NS_AVAILABLE_IOS(10_0);UIKIT_EXTERN NSString *const UITextContentTypeNamePrefix NS_AVAILABLE_IOS(10_0);UIKIT_EXTERN NSString *const UITextContentTypeGivenName NS_AVAILABLE_IOS(10_0);UIKIT_EXTERN NSString *const UITextContentTypeMiddleName NS_AVAILABLE_IOS(10_0);UIKIT_EXTERN NSString *const UITextContentTypeFamilyName NS_AVAILABLE_IOS(10_0);UIKIT_EXTERN NSString *const UITextContentTypeNameSuffix NS_AVAILABLE_IOS(10_0);UIKIT_EXTERN NSString *const UITextContentTypeNickname NS_AVAILABLE_IOS(10_0);UIKIT_EXTERN NSString *const UITextContentTypeJobTitle NS_AVAILABLE_IOS(10_0);UIKIT_EXTERN NSString *const UITextContentTypeOrganizationName NS_AVAILABLE_IOS(10_0);UIKIT_EXTERN NSString *const UITextContentTypeLocation NS_AVAILABLE_IOS(10_0);UIKIT_EXTERN NSString *const UITextContentTypeFullStreetAddress NS_AVAILABLE_IOS(10_0);UIKIT_EXTERN NSString *const UITextContentTypeStreetAddressLine1 NS_AVAILABLE_IOS(10_0);UIKIT_EXTERN NSString *const UITextContentTypeStreetAddressLine2 NS_AVAILABLE_IOS(10_0);UIKIT_EXTERN NSString *const UITextContentTypeAddressCity NS_AVAILABLE_IOS(10_0);UIKIT_EXTERN NSString *const UITextContentTypeAddressState NS_AVAILABLE_IOS(10_0);UIKIT_EXTERN NSString *const UITextContentTypeAddressCityAndState NS_AVAILABLE_IOS(10_0);UIKIT_EXTERN NSString *const UITextContentTypeSublocality NS_AVAILABLE_IOS(10_0);UIKIT_EXTERN NSString *const UITextContentTypeCountryName NS_AVAILABLE_IOS(10_0);UIKIT_EXTERN NSString *const UITextContentTypePostalCode NS_AVAILABLE_IOS(10_0);UIKIT_EXTERN NSString *const UITextContentTypeTelephoneNumber NS_AVAILABLE_IOS(10_0);UIKIT_EXTERN NSString *const UITextContentTypeEmailAddress NS_AVAILABLE_IOS(10_0);UIKIT_EXTERN NSString *const UITextContentTypeURL NS_AVAILABLE_IOS(10_0);UIKIT_EXTERN NSString *const UITextContentTypeCreditCardNumber NS_AVAILABLE_IOS(10_0);2.如果是视频类App可以使用MPPlayableContentManager (#import <MediaPlayer/MPPlayableContentManager.h>)看了下,新增了一个属性nowPlayingIdentifiers,苹果的意思应该是只要你以前是用这个多媒体类播放音乐的我就可以让你在锁屏页面交互,需要配置在这个数组里。   3.如果是出行类app可以使用MKDirectionsRequest。 (#import <MapKit/MKDirectionsRequest.h>  )这个类里几乎没有新增api,iOS10就新增了一个枚举,而且看上去就是个默认值。如果要使用此功能,需要配置在info.plist文件里 新增key - value ,MKDirectionsApplicationSupportedModes - MKDirectionsModeRideShare。User Notifications 用户通知 总体的意思就是支持了很多用户定义的通知,并且可以捕捉到各个通知状态的回调。以往通知的概念是:大家想接收的都提前做好准备,然后一下全量分发,没收到也不管了,也不关心发送者。现在用户通知做成了和网络请求有点像 一个先发request再得到response的流程,甚至封装了error,可以在各个状态的方法中做一些额外操作,并且也能取到一些字段,如发送者等。 此功能的头文件入口在#import <UserNotifications/UserNotifications.h>1.NSString+UserNotifications.h 有一个方法 localizedUserNotificationStringForKey: arguments: (提供该通知被呈现时的本地化字符串),猜测下面的类有很多initWithIdentifier的,他们的indentifier就是这个。2.UNError.h 有一个属性UNErrorDomain 和一个枚举 UNErrorCode,顾名思义。 3.UNNotification.h 里面有两个属性,date日期 和 request,这个request是上面“8”的类型UNNotificationRequest,点进去看了下比较清晰,有identifier标识,content内容,trigger触发条件, 和带上这三个东西的初始化方法。 其中内容 和 触发条件这两个属性,分别是上面“7” 和 “12”的类型,这个下面再谈。 4.UNNotificationAction.h 这个类突出的是一个通知的动作,有identifier,title,options(枚举,就是通知当前的权限,允许?拒绝?前台时允许?)属性。然后就是带上这三个东西的初始化方法。 然后比较费解的就是下面有一个子类UNTextInputNotificationAction ,这个子类有两个额外属性, 按钮title,和文本框placeholder, 为什么会是这两个属性? 莫非是点击通知后下拉出的快速回复,有一个输入框和一个按钮。 5.UNNotificationAttachment.h 这个里面就是URL(资源url属性),type(附件类型)。 然后是带上这两个属性的初始化方法。 下面声明了几个字符串常量,暂时还不知道具体用在哪里,typeHint,hiddenKey,clippingRectKey,TimeKey。 6.UNNotificationCategory.h 有indentifier属性,actions(里面是数组),minimalActions(最重要的数组,就是只能给你两个位置显示你显示哪两个,这么个意思),intentIdentifiers属性(应该是和上面的动作数组关联的吧),options(权限相关,无?允许自定义关闭?允许车载系统交互?)。最后就是把这些都带上的init方法。  猜测这个类之所以取名叫category应该是,在某个地方展示通知的时候会把所有通知一一分类, 然后每个类别的通知可能最多只能让你展示几个,如果不做限制应该会展示全部通知,如果权限设置的是允许自定义关闭那可能就是支持类似一键清除的操作。 7.UNNotificationContent.h 消息的内容,一看就能知道应该是一个类似于Entity的东西,里面装有大量的属性:attachments(可选的附件集合),badge(小红点数量),body,categoryIndentifier,launchImageName(从消息里点开的应用程序应该能看到启动图对吧),subtitle,threadIdentifier(与request关联),title,userInfo,sound这个是“11”的类型,应该是同时来时的声音,点开“11”看一下 ,就俩方法,defaultSound,soundNamed: 自定义声音,都在~/Library/Sounds 目录下。 恩再回到刚才那个content类里面有个子类UNMutableNotificationContent,属性和父类相同,只不过是子类的属性都可以修改了,父类的那些属性都是readonly的。 8.UNNotificationRequest.h 上面第3条说过了 9.UNNotificationResponse.h  有action,也有request,那也就有response,这里面有两个属性,notification,actionIdentifier  响应里就这俩破玩意。 然后有个子类UNTextInputNotificationResponse, 这里面就一个属性userText ,看命名很好猜,应该就是前面说的那个有输入框里输入的内容。 10.UNNotificationSettings.h 这个类里就是一些设置了,有一个枚举说的是有没有权限,一个枚举说的是不支持?禁用?启用?。 然后下面一大波属性,小红点设置,声音设置,弹窗设置等等 都是这个枚举类型, 最后还有个alertStyle属性(枚举,None?Banner?alert?)。 11.sound前面第7条说过了 12.UNNotificationTrigger.h 有一个属性 repeats(是否重复发通知)。 下面有四个子类,push通知触发, 时间通知触发,日历通知触发,地区通知触发, 时间的有timeInterval属性, 日历的有dateComponents属性。 然后时间和日历的子类都有nextTriggerDate 方法。 13.UNUserNotificationCenter.h 这里面东西多到吐了,同学你记得NSNotificationCenter么? 需要提一点的就是以前的通知中心有个方法[NSNotificationCenter defaultCenter], 这里是[UNUserNotificationCenter currentNotificationCenter], 提醒一下到时候别说敲不出来。 方法大多是一些remove,add,get等操作, 还有2个代理方法:通知将要发出去时调用,收到通知的response后调用。 14.UNNotificationServiceExtension.h 里面有两个方法,收到通知的请求后调用, 系统将要销毁时调用。通知里面有UI相关的类 #import <UserNotificationsUI/UserNotificationsUI.h> 这个类里面就一个文件, 而且方法比较单一,就是收到通知调用,和收到通知的响应调用。 其他方法也就是mediaPlay 和 mediaPause 。和一些多媒体播放的按钮frame,color等, 这里面的作用难道仅仅就是通知来了后播放的音乐暂时暂停下,响一声通知,再播放? 具体WWDC2016上说的锁屏页面的通知样式处理的api是在下面的部件增强章节中。Integrating with the Messages App 与系统短信 app交互 对消息额支持很大,可以模拟发消息收消息,发邮件等,提供了UI界面。 也提供了一些额外扩展的api,如表情包区域。WWDC2016上说的各种消息内的新操作在头文件中都能找到Api。 此功能的头文件入口在#import <Messages/Messages.h> 1.MSMessagesAppViewController.h 这个类应该就是苹果自己的消息界面,你可以继承他写你自己自定义的界面。 属性有:activeConversation 指的是当前的会话对象,是上面“2”这个类型,具体详细可以看下面的第“2”点、还有个是presentationStyle(外观样式,枚举类型,紧缩?扩张?)。 接下来就是方法了:requestPresentationStyle(请求消息过渡到指定的样式),dismiss消除方法。 然后就是一波生命周期方法了,每一类都有will和did,会话信息将要(已经)活跃时,将要(已经)解除活跃,将要(已经)选择信息,将要(已经)收到信息,将要(已经)开始发送,将要(已经)取消发送,将要(已经)开始过渡。 2.MSConversation.h 属性有localParticipantIdentifier(当前会话参与者生成的标识,他说只有删了App才会变 姑且理解成id是不会变的),remoteParticipantIdentifiers(远端的标识符数组),selectedMessage(选中的信息),以及4个对象方法 插入一条信息,插入一个标签,插入一段文本,插入一个附件。 这四个方法都有成功的回调。 3.MSSession.h 这个类里面是空的,解释说是用session来处理消息序列间的关系。可能就是占个位,以后估计会添加东西。 这个MSSession是后面很多参数的类型,应该就是区分消息类似于标识符的作用。  4.MSMessage.h 初始化方法是initWithSession ,没错就是上面那个MSSession。 除了初始化方法剩下的就全是属性了:session,senderParticipantIdentifier(发送者的标识符),layout布局这个是“5”这个类型,URL,shouldExpire(选yes会自动消失,用户手动选择为这条消息续命),accessibilityLabel(残疾人模式支持),error。 5.MSMessageLayout.h 这个是抽象类,里面是空的,就是个布局文件,继承自NSObject。 6.MSMessageTemplateLayout.h 继承上面那个类,看名字是模板布局后面应该会用的挺多的,里面的属性有,标题,子标题,尾部标题,尾部子标题,图片,多媒体URL,图片标题,图片子标题。  7.MSSticker.h 应该是消息上的表情包。 里面就有两个属性imageFileURL ,localizedDescription 图片和局部描述。然后是带上这两个属性的初始化方法 initWithContentsOfFileURL: localizedDescription: 。 8.MSStickerView.h 这个类就是一个view,里面包着一个sticker,也就是包裹着上面那个装饰品的view。 提供了带上sticker的初始化方法,一个常规属性animationDuration,和三个方法startAnimating,stopAnimating,isAnimating。 9.MSStickerBrowserViewDataSource.h 细思极恐,这个类不就是wwdc2016上说的那个可以在消息下面添加自定义表情的地方么。 符合datasource的风格,里面就两个方法,numberOfStickersInStickerBrowserView: (返回一个总数),stickerBrowserView:stickerAtIndex:(返回这个索引下的内容)。 10.MSStickerBrowserView.h 上面那个是datasource,那这个就是用了上面数据源的view呗。 除了初始化方法,有两个属性 stickerSize(枚举,小,中,大),dataSource(就是上面的“9”),还有个人reloadData方法。 11.MSStickerBrowserViewController.h 上面是个view, 这个就是承载上面那个view的viewcontroller。肯定得有这个属性stickerBrowserView 和初始化方法。 这个message模块还有UI相关的api   #import <MessageUI/MessageUI.h> 就是两个VC ,MFMailComposeViewController,MFMessageComposeViewController。 这两个都是继承自UINavigationController.   觉得这两个就是发邮件的编辑页面,和发消息的编辑页面。  发邮件的页面里有 canSendMail (Bool方法),set主题,set发件人,set收件人,set内容,set附件。 然后有一个代理,和代理方法,猜也能猜到 就是成功失败回调。mailComposeController:didFinishWithResult: error:  。 那另一个消息和这差不多了就不说了。Speech Recognition 语音识别转文字 这个类里面的Api和方法调用都非常清晰,感觉使用起来会非常方便。真的为科大讯飞捏把汗了,科大讯飞的app(录音宝)我看过,都还没有说一段语音能直接转文字的功能,他们是直接把声音文件上传,然后24小时候再发给你转换后的结果...而且一上来就要收费。苹果的这个功能已经做到了系统原生支持,真的厉害。 此功能的头文件入口在#import <Speech/Speech.h> 1.SFSpeechRecognitionResult.h这个类里有三个属性:bestTranscription 就是最优的转化结果咯,是上面的“7”这个类型的。然后再看下这个SFTranscription.h ,果然不出所料 有两个属性 一个是字符串类型formattedString 一个是数组类型的segments ,恩 前者就是转化后的字符串,后者是分割后的一个个小结果集合。 然后这个分割的一个个小结果呢又是上面“6”这个类型。那再看一下“6” 里面的属性就是 substring, 时间戳,duration,准确性,备选答案数组,这些很清晰的东西了。 2.SFSpeechRecognitionRequest.h 这个类里东西有点多,属性taskHint,是上面“4”这个类型,点开一看就是一个枚举,用来区分你这个语音识别的请求是哪一类的 查找?确认?听写?无法识别?。 接下来是两个BOOL类型的,shouldReportPartialResults(是否语音局部的一块一块也要处理?默认选false就是一句话全说完了再上传吧),detectMultipleUtterances(假如你说了10秒钟,只有后5秒匹配到了结果,那你前面删了还是保留?默认不删),然后是分析到的关键字数组,和标识符什么的。 然后这个request有两个子类,一个是从本地URL读取 一个声音文件去识别, 一个是默认做法用话筒和AVFoundation库接收到声音去识别,然后有几个拼接声音的API。 3.SFSpeechRecognitionTask.h 从名字就能看出来这是语音识别最重要的一个类了,里面的属性有:state这是一个枚举,说明当前状态是进行中?已完成?被取消?等等。 接下来是三个常见的 isFinishing ,isCancelled ,error 。 接下来是 isPowerAvailable (是否开启说话声音大小的监测?),peakPower(最大声音),averagePower(平均声音)。 属性就这些了,接下来就是一个协议和一波代理方法:刚刚识别出话语调用,猜测话语时调用,话说完了调用,取消时调用,等等等,你能想到的回调方法苹果应该都有的。 4.上面第2条里面说过了 5.SFSpeechRecognizer.h 和系统的那些相机权限,通讯录权限有点像, 就是现在的状态是什么?同意?拒绝?还是未选择过? 然后提供了方法让用户去选择。 然后有些属性:NSSet类型的supportedLocales(支持地区方言的集合), available是否可用,locale当前地区 ,defaultTaskHint默认类别,request(就是上面说的请求),队列,代理。 然后有个协议和代理方法:发现用户给与的权限发生改变时调用。 6和7. 上面第1条里说过了  Wide Color 宽域颜色 文档的原话说:大多数的 core字打头的图形框架 还有AVFoundation 都大大提高了对扩展像素和宽色域色彩空间的支持。通过图形堆栈扩展这种方式比以往支持广色域的显示设备更加容易。现在对UIKit扩展可以在sRGB的色彩空间下工作,性能更好,也可以在更广泛的色域来搭配sRGB颜色。 然后说了几个场景说建议你用sRGB吧,比如依赖于UIkit的clamp component values的应用程序,或是使用较低级别api执行自己图像处理的 都建议用sRGB吧。 然后看了下UIColor类里 到底什么是sRGB? 发现多了两个iOS10新增的api。 复制代码 代码如下:+ (UIColor *)colorWithDisplayP3Red:(CGFloat)displayP3Red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha NS_AVAILABLE_IOS(10_0);  //董铂然 博客园- (UIColor *)initWithDisplayP3Red:(CGFloat)displayP3Red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha NS_AVAILABLE_IOS(10_0); //董铂然 博客园细节都是一样的就是一个类方法一个实例方法, 我理解下,就是说建议你们以前改用colorwithRGB的地方 现在都换成这个方法叭。可能大多数公司都抽成了 RGB(a,g,b,a)这种宏吧,那就在宏定义那改一下就好了。 Adapting to the True Tone Display 真彩色显示 真彩色的显示会根据光感应器来进行自动的调节来达到特定环境下的显示与性能平衡效果。 如果需要这个功能的话需要再info.plist里配置 UIWhitePointAdaptivityStyle 共有五种选择: 1.UIWhitePointAdaptivityStyleStandard 标准 2.UIWhitePointAdaptivityStyleReading 阅读 3.UIWhitePointAdaptivityStylePhoto 图片 4.UIWhitePointAdaptivityStyleVideo 视频 5.UIWhitePointAdaptivityStyleGame 游戏 然后他说的很清楚,如果你是图片处理类的app,那就直接配stylePhoto吧,如果你是阅读类的那就直接配styleReading吧。 这五个形式的显示效果从上往下递减,我理解是说在阅读时给你最好的效果,但如果在游戏时也给那么好的效果会影响性能,就给你一个相对次一点的显示效果让性能更流畅。App Search Enhancements 应用搜索增强 iOS10的搜索功能做了一定增强:应用程序内搜索,搜索传递,考虑私人差异,结果可视化。 使用CSSearchQuery类,调用Core Spotlight的api,可以让你不必自己维护自己的搜索索引,关于对搜索关键字的处理,还有考虑到不同类别差异导致搜索结果的排序都是苹果帮你处理。 并且搜索结果可以继续往下传递,假设你用Core Spotlight搜索火车站,提示的是地图类app搜索火车站的结果,你点进去后,这个地图类app会接收到“火车站”这个字段在应用内也完成搜索。支持此功能也是需要配置plist文件:key-value  CoreSpotlightContinuation-YES,然后设置CSQueryContinuationActionType(#import<CoreSpotlight/CSSearchableItem.h>)。最后传递的搜索字符串用continueUserActivity:restorationHandler:方法接收。 然后现在看一下#import <CoreSpotlight/CSSearchQuery.h>头文件里面的结构。 看上去这个CSSearchQuery像是一个查询语句操作,有创建,查询成功和错误等。初始化方法是initWithQueryString: attributes:。 有isCanceled属性 和 cancel 和 start方法。 还有foundItemCount属性,看上去是能够得到搜索的结果个数。protectionClasses(数组),看上去像是隐私相关受保护的文件。 还有两个block,一个是搜索结束后回调,参数是NSError;一个是查询到结果时回调,参数是items数组。这个items数组都是CSSearchableItem类型,这里面有个attributeSet属性,里面可以传入以下类型 Widget Enhancements 锁屏部件增强 现在锁屏界面有了新的设计,建议我们废弃以前的notificationCenterVibrancyEffect 改用widgetPrimaryVibrancyEffect或者widgetSecondaryVibrancyEffect,并且窗口的小部件可以让你描述有多少东西可用,支持紧凑和扩展两种形态。这些新旧的Effect效果在这个类下,可能是之前锁屏玩不出什么花样所以大家没怎么关注这里。 #import <NotificationCenter/NotificationCenter.h> 里面有三个头文件 1.NCWidgetProviding.h 先来两个方法  复制代码 代码如下:- (void)widgetPerformUpdateWithCompletionHandler:(void (^)(NCUpdateResult result))completionHandler;这个方法如果实现了,系统将在适当的时候召唤部件更新形态,无论是在通知中心还是后台。 需要启用后台更新功能,部件会在异步工作主线程更新,调用参数块的工作完成后会得到相应的结果。 复制代码 代码如下:- (void)widgetActiveDisplayModeDidChange:(NCWidgetDisplayMode)activeDisplayMode withMaximumSize:(CGSize)maxSize;这个方法应该是部件变化时调用,参数是最大有多大。这里声明了一个分类UIVibrancyEffect (NCWidgetAdditions),里面就是本章节说的iOS10新增API + (UIVibrancyEffect *)widgetPrimaryVibrancyEffect NS_AVAILABLE_IOS(10_0);+ (UIVibrancyEffect *)widgetSecondaryVibrancyEffect NS_AVAILABLE_IOS(10_0);这两个方法名字上是老大和老二,有什么区别? 都是用在选择的文字或图形上,默认用上面,如果开启了further diminution(应该是类似于上面压缩模式)就用下面的。 下面又声明了一个分类NSExtensionContext (NCWidgetAdditions),里面也是iOS10的新增API 里面有两个属性 widgetLargestAvailableDisplayMode ,widgetActiveDisplayMode 。 是两种显示模式是NCWidgetDisplayMode枚举类型,有紧缩和扩张两种。 ,估计假如是新闻通知一个是一般大小,一个是点开详情的大小。 然后就是一个方法widgetMaximumSizeForDisplayMode ,返回值是CGSize取到播放模式的最大尺寸。 2.NCWidgetController.h里面除了个初始化方法,还有一个方法复制代码 代码如下:- (void)setHasContent:(BOOL)flag forWidgetWithBundleIdentifier:(NSString *)bundleID;第一个参数默认为yes,就是该展示时就展示,这个方法可以跨小组件间通讯,以及和providing app交互。 3.NCWidgetTypes.h 里面就一个枚举类型NCWidgetDisplayMode ,前面第1点说过了。 Security and Privacy Enhancements 安全和保密性增强 安全方面在iOS10中引入了更多修改和补充,具体有以下几点: 1.在info.plist文件新增了一个key,NSAllowsArbitraryLoadsInWebContent,允许任意web页面加载,同时苹果会用ATS保护你的app。 2.使用改进后的SecKey API 而不是过时的 CDSA API。 3.安全传输API中不再支持SSLv3, 建议你们尽快停用SHA1和3DES加密算法。 4.剪贴板的扩展,因为wwdc2016演示了可以跨设备复制粘贴啊,那肯定要做一些限制可见(#import <UIKit/UIPasteboard.h>) 5.这点最重要的,建议尽快适配, 所有和用户权限相关的地方必须在info.plist里配置里面包括 NSBluetoothPeripheralUsageDescriptionNSCalendarsUsageDescriptionNSCameraUsageDescriptionNSContactsUsageDescriptionNSHealthShareUsageDescriptionNSHealthUpdateUsageDescriptionNSHomeKitUsageDescriptionNSLocationAlwaysUsageDescriptionNSLocationWhenInUseUsageDescriptionNSMicrophoneUsageDescriptionNSMotionUsageDescriptionNSPhotoLibraryUsageDescriptionNSRemindersUsageDescriptionNSSiriUsageDescriptionNSSpeechRecognitionUsageDescriptionNSVideoSubscriberAccountUsageDescriptionNSVoIPUsageDescription虽然现在还没有iOS10系统的手机,但是我用模拟器试了下,亲测如果我想唤起通讯录但是没有配置NSContactsUsageDescription,刚启动时不会崩溃,但是在唤起操作发生时会直接崩溃。 在info.plist设置之后就可以正常使用了。本文是用笔者认为比较清晰的结构整理的,希望读者也能有所帮助。 当然里面也有一些地方是我自己的猜测和理解,不能保证100%正确,有不同而理解欢迎一起讨论。以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

分类:腾博会手机版下载

时间:2016-02-19 08:02:16