语言强制解包看 斯威夫特(Swift)(Swift) 的统筹

非知情我们发生无暴发发现,在一个 Objective-C 和 斯威夫特(Swift)(Swift) 混编的 App
中,当把一个 OC 中之参数转到 斯维夫特(Swift)(Swift) 时,斯威夫特(Swift)(Swift)会自动把此变量举行强制解包。举个例子,我于 OC 中定义这样一个变量:

 

 1 @property (nonatomic, copy) NSString *foo; 
  • 类型

它改变成为 Swift(Swift) 就改成了这么:

   
JavaScript提供了差不两个放数据类型。除了这几个,这卖文档还用介绍一些虚拟类型,例如选用器、伪类、事件出色。

var foo: String!

 

那样看起来合理。Swift 中出 String? 和 String! 三种样式,但 OC 中绝非
NSString? 和 NSString! ,当 Swift 不可能区分 OC 中的变量是匪是 nil
的早晚,一律强行转会为非空参数。这样设计显示了 Swift强安全性语言的特色。

  • String

可是此时问题来了。我们再次来到上文中的事例,如果 OC 中对 foo的以如下:

   
在JavaScript中字符串是一个不可变的靶子,它含有无、一个要五个字符。它的档次称之为“string”。

 1 @property (nonatomic, copy) NSString *foo;
 2 
 3 - (void)secretFunc {  
 4   // 一些诡异复杂的操作
 5   ...  
 6   self.foo = nil;
 7 }
 8 // 然后我们在 Swift 中这样调用:
 9 
10 func init() {
11   objectiveCObject.secretFunc()
12 }func calcLen() -> Int {  
13 
14   return objectiveCObject.foo.characters.count
15 
16 }
typeof"some string"; // "string"

方那段 斯维夫特(Swift)代码执行到calcLen()时会崩溃,原因是fooinit()遇就为如成了
nil,而foo在 Swift 中是 foo!。也就是说,因为 斯威夫特 对 OC
变量的强转,导致了次的倒台。这是一个充足轻忽略的题材,因为强转的下,Xcode
不会师被来另的警戒、报错或是提示。而我辈作为开发者,很爱忽视这样的错,导致
runtime 的时节一向倒。

    • 引号

对那种气象,我们来探讨下多少个问题。

   
一个字符串能够利用单引号或对引号来定义,你能够以双引号内或者周围嵌套使用单引号,假设一旦于双引号内使对引号(或者单引号内动单引号),必须嵌套使用反斜杠举办转义。

  • Q: 为何 斯威夫特(Swift)(Swift) 要以 OC 中之变量如foo转为foo!而不是foo?
"You make 'me' sad."
'That\'s "cranking" good fun!'
"<a href=\"home\">Home</a>"

就是一个爆发顶牛的话题。我个人觉得强制解包的章程会督促开发者考虑变量是否为
nil 的问题。在 OC 时代,声明变量一般不晤面设想是不是为空的题目;而以 斯维夫特(Swift)时代,因为那些是如出一辙家大安全性的言语,在变量定义时,必须确定变量是否为空。一般定义也非空有少栽以下格局:

    • 搭方法
1 // force unwrapping
2 var foo = "Hello"
3 // implicitly unwrapping
4 var foo: String!

   
在JavaScript中有有置方法好操作字符串。通常结果连续回到一个初的字符串,或回到一个array。

前端因最先值强制解包,定义 foo 为非空变量;后者则直表明 foo
为非空变量。

"hello".charAt( 0 ) // "h"
"hello".toUpperCase() // "HELLO"
"Hello".toLowerCase() // "hello"
"hello".replace( /e|o/g, "x" ) // "hxllx"
"1,2,3".split( "," ) // [ "1", "2", "3" ]

不管哪个种类情况,开发者会于平先河就是思考处理 nil
时之景观,并当继续开发中一向留心。所以从foo转化为foo!,你虽会面盘算 OC
中代码是否为只要处理
nil 的情形;而如转会为foo?,nil 也不在乎,而实际可能并无是这么,nil
的与众不同状况考虑会从来忽略,开发中的隐患一向是,同时也非合乎 Swift强安全性的规划思路。

    • Length属性
  • Q: 我便想吃 OC 中之变量从foo转化到 Swift 中变成foo?,有没爆发措施

   
所有的字符串都发出一个length属性(长度属性)。

请这样于 OC 中定义变量:

"Hello".length // 5
"".length // 0
1 // foo -> foo?
2 @property (nullable, nonatomic, copy) NSString *foo;
3 // bar -> bar!
4 @property (nonnull, nonatomic, copy) NSString *bar;
5 // qux -> qux!
6 @property (nonatomic, copy) NSString *qux;
    • 默认布尔值

这种先表明是否也 null 的定义方法,是无是老大像 Swift 中的 optional
机制?不过 OC 时代我们几乎未相会失掉随便变量是否为 nullable
这宗事,因而我们得回味 OC 和 斯维夫特 在语言设计思路上之反差。

    一个空字符串默看false。

其实nullablenonnull大凡 Swift 出来之后才引入 OC 的。所以同样起初,OC
中的变量默认都是nullable,转变到 Swift中,应该就是?。不过这么转车代价但是死,我们富有变量都如在 斯威夫特(Swift)(Swift)中之所以if else或者guard来解包。所以为了写起方便,Swift干脆直接强转,故而现在之机制吗是一个史遗留问题。

!"" // true
!!"" // false
!"hello" // false
!"true" // false
!new Boolean( false ) // false
  • Q: 斯威夫特(Swift) 如此这般导致混编 App
    崩溃,没有提示的境况下程序员必须细细检查 nil 导致的
    bug,这样设计强制解包的代价是否暴发硌非凡?

 

是 bug 在混编 App
中杀轻并发,没有警示确实带动至极怪苦恼。实际上那一个题目都在苹果之开发者论坛上让提议,斯维夫特(Swift)组自己为开了单 ticket 要编,可惜最后不了了之。Github
上有人开出了第三正值的工具来解决这么些题材。

  • htmlString

本身个人觉得是题材苹果不重视的来头在 斯威夫特(Swift) 和 OC
混编只是一个临时的圈。斯威夫特(Swift)(Swift) 取代 OC
是一个时日问题,所以解决混编中之题材还显得没多可怜意义,在苹果中也直是低优先级。毕竟现在享有精力当在
斯威夫特 上,随着时光之延期和 OC 的脱离,这个问题吧以微不足道。

   
当一个字符串在JQuery文档中表示一个或多独DOM元素时,通常给成立与插到文档中常,这多少个字符串将被看作htmlString。当给看作一个JQuery()方法参数传递的时光,这些字符串将会给当是HTML。

 

   
当一个字符串作为参数传递给一个操作方法时,例如.append(),它总是让当当HTML,因为JQuery对斯字符串(CSS采取器)的此外一同解释不适用于其上下文。

    $.parseHTML()可以显式的分析一个html字符串。

// 追加<b>hello</b>:
$( "<b>hello</b>" ).appendTo( "body" );
// 追加<b>hello</b>:
$( "<b>hello</b>bye" ).appendTo( "body" );
// 语法错误, unrecognized expression: bye<b>hello</b>
$( "bye<b>hello</b>" ).appendTo( "body" );
// 追加bye<b>hello</b>:
$( $.parseHTML( "bye<b>hello</b>" ) ).appendTo( "body" );
// 追加<b>hello</b>wait<b>bye</b>:
$( "<b>hello</b>wait<b>bye</b>" ).appendTo( "body" );

 

  • Number

    在JavaScript中之Number是双料精度64员IEEE754格式化的值。仅仅作为字符串的时节,它们是不可变更的。对于Number类型的多寡有所的演算符都是因C语言的法展开演算的。

typeof 12 // "number"
typeof 3.543 // "number"
    • 默认布尔值

   
假若一个数字是0,那么它们默认为false。

!0 // true
!!0 // false
!1 // false
!-1 // false

   
由于是对精度运行,下边这些结果不到底一个谬误

0.1 + 0.2// 0.30000000000000004
    • Math

   
JavaScript提供了数学对象中之数字通用功效。

Math.PI // 3.141592653589793
Math.cos( Math.PI ) // -1
    • 数字分析

    parseInt和parseFloat可以用于解析字符串为数字,假使非指定两者是开隐式转换的。

parseInt( "123" ) = 123 // (隐式十进制)
parseInt( "010" ) = 8 // (隐式八进制)
parseInt( "0xCAFE" ) = 51966 // (隐式十六进制)
parseInt( "010", 10 ) = 10 // (显示十进制)
parseInt( "11", 2 ) = 3 // (显示二进制)
parseFloat( "10.10" ) = 10.1
    • Numbers与Strings

   
当数字加一个字符串时,结果一直是一个字符串,而运算符格局是千篇一律的,这是要注意的,假若你想先举办数字运算再附加到一个字符串,那么数字运算需要用括号包裹起来。

"" + 1 + 2; // "12"
"" + ( 1 + 2 ); // "3"
"" + 0.0000001; // "1e-7"
parseInt( 0.0000001 ); // 1 (!)

   
或者你若拔取JavaScript提供的String类,可以分析一个数字呢字符串。

String( 1 ) + String( 2 ); // "12"
String( 1 + 2 ); // "3"
    • NaN和Infinity

   
解析一个免是数字的事物平常结果是NaN,isNaN方法好拉您判定结果是否是NaN。

parseInt( "hello", 10 ) // NaN
isNaN( parseInt("hello", 10) ) // true

 
  除散装之结果是Infinity。

1 / 0// Infinity

 
  NaN和Infinity都是Number类型的。

typeof NaN // "number"
typeof Infinity // "number"

   
需要注意的是NaN的同种出乎意料的较,它与它们自己比是见仁见智之。

NaN == NaN// false (!)

    可是Infinity的比是不同之。

Infinity == Infinity// true
    • Integer

   
整数是一个家常的数字型,但每当明确指明的时段,表示数字是一个非浮点数。

    • Float

       
    浮点数也是一个熟视无睹的数字型,但每当明确指明的当儿,就代表数字是一个浮点数。

 

  • Boolean

   
在JavaScript中Boolean代表的是true或者false。

if ( true ) console.log( "always!" );
if ( false ) console.log( "never!" );

 

  • Object

       
    在JavaScript中一切都是对象。最简易的创设对象的法门是目的文字。

var x = {};
var y = {
name: "Pete",
age: 15
};

    对象的色是Object。

typeof {} // "object"
    • 点符号

       
    你可以使用点符号读取和写入对象的习性。

y.name // "Pete"
y.age // 15
x.name = y.name + " Pan" // "Pete Pan"
x.age = y.age + 1 // 16
    • 数组符号

       
    或许你念写对象的性是因而数组符号,它同意你动态的选用对象的性质。

var operations = {
increase: "++",
decrease: "--"
};
var operation = "increase";
operations[ operation ] // "++"
operations[ "multiply" ] = "*"; // "*"
    • 迭代

       
    通过for-in-loop就得概括的兑现目标的迭代。

var obj = {
name: "Pete",
age: 15
};
for( key in obj ) {
alert( "key is " + [ key ] + ", value is " + obj[ key ] );
}

   
需要专注的是for-in-loop可能会师在延伸使用到Object.prototype的上起问题,例如Object.prototype被人改了。

   
JQuery提供了通用的each方法去遍历对象的性与要素数组。

jQuery.each( obj, function( key, value ) {
console.log( "key", key, "value", value );
});

   
缺点是回调被调用在迭代值的前后文中,因而若错过了初对象的上下文。

    • 默认布尔值

       
    一个对象,无论它是不是暴发性,默认值永远不会师呢false。

!{} // false
!!{} // true
    • 原型

       
    所有的靶子还发生原型(prototype)属性,每当把它们当属性之时光,假若当靶上找不交此特性它仍会于对象的原型上展开反省,JQuery广泛的利用原型将艺术上加至JQuery实例上。JQuery使用jQuery.fn作为jQuery.prototype的别名,你得应用中的任意一个

var form = $("#myform");
console.log( form.clearForm ); // undefined
// jQuery.fn == jQuery.prototype
jQuery.fn.clearForm = function() {
return this.find( ":input" ).each(function() {
this.value = "";
}).end();
};
// 所有的JQuery对象实例都可以运行,因为新的方法已经被添加到原型上了
console.log( form.clearForm );
form.clearForm();

 

  • Array

       
    在JavaScript中数组是可是其余,并且有一些停放方法可行使。

var x = [];
var y = [ 1, 2, 3 ];
typeof []; // "object"
typeof [ 1, 2, 3 ]; // "object"
x[ 0 ] = 1;
y[ 2 ] // 3
    • 迭代

       
    在三番五遍组的迭代中length属性是不行管用的。

for ( var i = 0; i < a.length; i++ ) {
// a[i]
}

   
当性能是重中之重的时节,只念博一浅length属性可以扶持运行速度的升级。

for ( var i = 0, j = a.length; i < j; i++ ) {
// a[i]
}

   
另外还有平等种植情状是在迭代告知句被定义变量来囤数组当前迭代底要素,在循环体中不再选拔数组元素而是以此变量。

for ( var i = 0, item; item = a[i]; i++ ) {
// 使用item变量
}

   
JQuery提供了each方法好迭代数组的每个元素,那一个办法对迭代目标的性也是适用的。

var x = [ 1, 2, 3 ];
jQuery.each( x, function( index, value ) {
console.log( "index", index, "value", value );
});

    length属性可以为此来作序号将元素参与到数组的最后。

var x = [];
x.push( 1 );
x[ x.length ] = 2;
x // [ 1, 2 ]

    数组还有不少的松开方法。

var x = [ 0, 3, 1, 2 ];
x.reverse() // [ 2, 1, 3, 0 ]
x.join(" – ") // "2 - 1 - 3 - 0"
x.pop() // [ 2, 1, 3 ]
x.unshift( -1 ) // [ -1, 2, 1, 3 ]
x.shift() // [ 2, 1, 3 ]
x.sort() // [ 1, 2, 3 ]
x.splice( 1, 2 ) // [ 2, 3 ]
    • 默认布尔值

       
    一个往往组,无论它发出没起素,也永远不谋面默认为false。

![] // false
!![] // true
    • Array<Type> 符号

       
    在JQuery的API中,通常可以发现有Array<Type>符号。这样可以指定数组元素的预期类型,类似于.NET中的泛型。

dragPrevention    Array<String>

 

  • PlainObject

 
  PlainObject是一个JavaScript对象,包含了0个或多少个键值对。

var a = [];
var d = document;
var o = {};
typeof a; // object
typeof d; // object
typeof o; // object
jQuery.isPlainObject( a ); // false
jQuery.isPlainObject( d ); // false
jQuery.isPlainObject( o ); // true

 

  • Function

   
一个函数(方法)在JavaScript中好是命名的或是匿名的。任何一个函数都足以分配受一个变量,或传递给一个函数,可是经过传递成员函数这样的方得以使她们于别一个靶的上下文调用。函数的品类是“function”。

function named() {}
var handler = function() {}

   
JQuery代码中之匿名函数是大量凸现的。

$( document ).ready(function() {});
$( "a" ).click(function() {});
$.ajax({
url: "someurl.php",
success: function() {}
});
    • 语言,参数

   
在函数中生出同样种植特殊的变量,这虽然是参数,它是一模一样栽伪数组格局的元素。

function log( x ) {
console.log( typeof x, arguments.length );
}
log(); // "undefined", 0
log( 1 ); // "number", 1
log( "1", "2", "3" ); // "string", 3

   
参数对象还出一个callee属性,它对的是实例之中的函数。

var awesome = function() { return arguments.callee; }
awesome() == awesome // true
    • 上下文

   
在JavaScript中,this总是指为当前齐下文,默认状况下this指向的是window对象,在一个函数内this的上下文就汇合起变动,这种变更在函数是怎么吃调用的。

$( document ).ready(function() {
// this指向window.document
});
$( "a" ).click(function() {
// this指向DOM中的a标签元素
});

   
你可指定一个函数的光景文来使用函数的放方法call或者apply。两者的区别在咋样传递参数,call将有所的参数作为一个arguments传递给函数,而apply接收一个arguments数组作为参数。

function scope() {
console.log( this, arguments.length );
}
scope() // window, 0
scope.call( "foobar", [ 1, 2 ] ); // "foobar", 1
scope.apply( "foobar", [ 1, 2 ] ); // "foobar", 2
    • 作用域

   
在JavaScript中,所有函数内部定义之变量都唯有在该函数的企图域内是可行之。

    在大局范围外定义的变量和函数内部定义之变量名称一致时,两者是休谋面生出争持之。

var x = 0;
(function() {
var x = 1;
console.log( x ); // 1
})();
console.log( x ); // 0
    • 闭包

    闭包是针对功用域范围之扩大,闭包让函数可以于外部看该函数被创立的功用域内之变量。这种形式允许你创制对象后通过措施来操作对象中的变量,那些变量是外部不可见的,那吗多亏面向对象编程的根底。

function create() {
var counter = 0;
return {
increment: function() {
counter++;
},
print: function() {
console.log( counter );
}
}
}
var c = create();
c.increment();
c.print(); // 1
    • 代办情势

   
在JavaScript中起一致种植代理形式,为外对象提供平等种代理以控制对这些目的的看,可以兑现中央的面向方面编程(AOP)。

  • 回调

   
回调就是当一个函数中传送一些函数作为该参数。JQuery的事件系就是是使用函数回调来贯彻之。

$( "body" ).click(function( event ) {
console.log( "clicked: " + event.target );
});

   
回调的重返值是可选的,例如提防表单提交,我们得以经过波来进展处理。

$( "#myform" ).submit(function() {
return false;
});

 

  • Selector

   
在JQuery中一个selector是于用来挑选DOM文档中的元素,这文档一般是以浏览器被,除此之外通过AJAX接收的XML文档也是适用的。

   
如若selector被指定为参数类型,那么它将承受任何JQuery构造函数接受的,例如:字符串、元素与要素列表等。

 

  • Event

       
    JQuery事件系统是基于W3C标准规格事件目的的,事件目的是给保险传递让事件处理器的。

    DOM中之标准事件是:blur, focus,
 load, resize, scroll, unload, beforeunload, click, dblclick, mousedown,
mouseup, mousemove, mouseover, mouseout, mouseenter, mouseleave, change,
select, submit, keydown, keypress, 和
keyup。DOM事件之称是为片要素预定义的,JQuery事件模型可以因而元素上之部分称呼指向一个事件。

 

  • Element

       
    在DOM中之一个素得以发性能、文本及子节点。它提供了法可遍历父节点和子节点,并收获其的性质。JQuery提供了帮手元素与DOM交互的不二法门。

   
每当使用JQuery中的each方法,函数回调的上下文将吃装为一个DOM元素,事件处理器为是类似之。

$( ":text" ).blur(function() {
if( !this.value ) {
alert( "Please enter some text!" );
}
});

 

  • jQuery

       
    JQuery对象涵盖一个DOM元素的汇聚。JQuery平日利用CSS样式中之选用器来配合文档中的元素,设置JQuery对象吃之素通常让誉为设置“匹配元素”或者“已选元素”。

   
JQuery对象类似于数组,可是需要注意的凡它不是当真的数组对象,即使她有length属性,可是任何一些数组内置方法是休可以用的。

   
很多JQuery方法再次来到的呢是JQuery对象,所以于这么的境况下得以链式调用的道来调用函数。

$( "p" ).css( "color", "red" ).find( ".special" ).css( "color", "green" );

   
每当你使用JQuery的链式调用函数时,即便您想回到当前因素此前的酷元素,那么您可以使用.end()方法。

   
JQuery对象好是空的,不含DOM中之要素,你得经$()成立一个空JQuery对象。如果采用器没有选任何因素或链式方法吃淋了富有的因素,那么JQuery对象啊空而非是error,并且在空的JQuery对象上调用方法是没用的。

 

  • XMLHttpRequest

     
      一些jQuery的AJAX函数重返的凡当地的XMLHttpRequest(XHR)对象,而XMLHttpRequest正是AJAX的核心目的,其重点效能是暨服务端举办数据交互。

 

  • XML Document

    XML文档对象是透过浏览器的XML
DOM解析器创立的,XML文档与HTML文档有着不同的语义,但大部分之遍历与JQuery方法对互相是同选用及运作的。

 

  • 种检查

   
jQuery提供了一部分基本的实用方法来规定一个特定值的花色。

var myValue = [ 1, 2, 3 ];
// 使用JavaScript的typeof来测试类型
typeof myValue === "string"; // false
typeof myValue === "number"; // false
typeof myValue === "undefined"; // false
typeof myValue === "boolean"; // false
// 使用全等于运算符判断是否为null
myValue === null; // false
// 使用Jquery的方法检查类型
jQuery.isFunction( myValue ); // false
jQuery.isPlainObject( myValue ); // false
jQuery.isArray( myValue ); // true

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图