Swift 2

Swift系列文章由CocoaChina翻译小组翻译自苹果的官方文档: The Swift Programming Language。本篇译者:葛布林大帝( 博客)和 @numbbbbb( 博客),校对: ChildhoodAndy

通常来说,编程语言教程中的第一个程序应该在屏幕上打印“Hello,world”。在 Swift 中,可以用一行代码实现:
  1. println("hello,world")
如果你写过 C 或者 Objective-C 代码,那你应该很熟悉这种形式——在 Swift 中,这行代码就是一个完整的程序。你不需要为了输入输出或者字符串处理导入一个单独的库。全局作用域中的代码会被自动当做程序的入口点,所以你也不需要main函数。你同样不需要在每个语句结尾写上分号。
这个教程会通过一系列编程例子来让你对 Swift 有初步了解,如果你有什么不理解的地方也不用担心——任何本章介绍的内容都会在后面的章节中详细讲解。
注意:为了获得最好的体验,在 Xcode 当中使用代码预览功能。代码预览功能可以让你编辑代码并实时看到运行结果。
简单值
使用let来声明常量,使用var来声明变量。一个常量的值在编译时并不需要获取,但是你只能为它赋值一次。也就是说你可以用常量来表示这样一个值:你只需要决定一次,但是需要使用很多次。
  1. varmyVariable=42
  2. myVariable=50
  3. letmyConstant=42
常量或者变量的类型必须和你赋给它们的值一样。然而,声明时类型是可选的,声明的同时赋值的话,编译器会自动推断类型。在上面的例子中,编译器推断出myVariable是一个整数(integer)因为它的初始值是整数。
如果初始值没有提供足够的信息(或者没有初始值),那你需要在变量后面声明类型,用冒号分割。
  1. letimplicitInteger=70
  2. letimplicitDouble=70.0
  3. letexplicitDouble:Double=70
练习:创建一个常量,显式指定类型为Float并指定初始值为4。
值永远不会被隐式转换为其他类型。如果你需要把一个值转换成其他类型,请显式转换。
  1. letlabel="Thewidthis"
  2. letwidth=94
  3. letwidthLabel=label+String(width)
练习:删除最后一行中的String,错误提示是什么?
有一种更简单的把值转换成字符串的方法:把值写到括号中,并且在括号之前写一个反斜杠。例如:
  1. letapples=3
  2. letoranges=5
  3. letappleSummary="Ihave\(apples)apples."
  4. letfruitSummary="Ihave\(apples+oranges)piecesoffruit."
练习:使用\()来把一个浮点计算转换成字符串,并加上某人的名字,和他打个招呼。
使用方括号[]来创建数组和字典,并使用下标或者键(key)来访问元素。
  1. varshoppingList=["catfish","water","tulips","bluepaint"]
  2. shoppingList[1]="bottleofwater"
  3. varoccupations=[
  4. "Malcolm":"Captain",
  5. "Kaylee":"Mechanic",
  6. ]
  7. occupations["Jayne"]="PublicRelations"
要创建一个空数组或者字典,使用初始化语法。
  1. letemptyArray=String[]()
  2. letemptyDictionary=Dictionary<String,Float>()
如果类型信息可以被推断出来,你可以用[]和[:]来创建空数组和空字典——就像你声明变量或者给函数传参数的时候一样。
  1. shoppingList=[]//去逛街并买点东西
控制流
使用if和switch来进行条件操作,使用for-in、for、while和do-while来进行循环。包裹条件和循环变量括号可以省略,但是语句体的大括号是必须的。
  1. letindividualScores=[75,43,103,87,12]
  2. varteamScore=0
  3. forscoreinindividualScores{
  4. ifscore>50{
  5. teamScore+=3
  6. }else{
  7. teamScore+=1
  8. }
  9. }
  10. teamScore
在if语句中,条件必须是一个布尔表达式——像if score { ... }这样的代码是错误的。
你可以一起使用if和let来处理值缺失的情况。有些变量的值是可选的。一个可选的值可能是一个具体的值或者是nil,表示值缺失。在类型后面加一个问号来标记这个变量的值是可选的。
  1. varoptionalString:String?="Hello"
  2. optionalString==nil
  3. varoptionalName:String?="JohnAppleseed"
  4. vargreeting="Hello!"
  5. ifletname=optionalName{
  6. greeting="Hello,\(name)"
  7. }
练习:把optionalName改成nil,greeting会是什么?添加一个else语句,当optionalName是nil时给greeting赋一个不同的值。
如果变量的可选值是nil,条件会判断为false,大括号中的代码会被跳过。如果不是nil,会将值赋给let后面的常量,这样代码块中就可以使用这个值了。
switch支持任意类型的数据以及各种比较操作——不仅仅是整数以及测试相等。
  1. letvegetable="redpepper"
  2. switchvegetable{
  3. case"celery":
  4. letvegetableComment="Addsomeraisinsandmakeantsonalog."
  5. case"cucumber","watercress":
  6. letvegetableComment="Thatwouldmakeagoodteasandwich."
  7. caseletxwherex.hasSuffix("pepper"):
  8. letvegetableComment="Isitaspicy\(x)?"
  9. default:
  10. letvegetableComment="Everythingtastesgoodinsoup."
  11. }
练习删除default语句,看看会有什么错误?
运行switch中匹配到的子句之后,程序会退出switch语句,并不会继续向下运行,所以不需要在每个子句结尾写break。
你可以使用for-in来遍历字典,需要两个变量来表示每个键值对。
  1. letinterestingNumbers=[
  2. "Prime":[2,3,5,7,11,13],
  3. "Fibonacci":[1,1,2,8],
  4. "Square":[1,4,9,16,25],
  5. ]
  6. varlargest=0
  7. for(kind,numbers)ininterestingNumbers{
  8. fornumberinnumbers{
  9. ifnumber>largest{
  10. largest=number
  11. }
  12. }
  13. }
  14. largest
练习:添加另一个变量来记录哪种类型的数字是最大的。
使用while来重复运行一段代码直到不满足条件。循环条件可以在开头也可以在结尾。
  1. varn=2
  2. whilen<100{
  3. n=n*2
  4. }
  5. n
  6. varm=2
  7. do{
  8. m=m*2
  9. }whilem<100
  10. m
你可以在循环中使用..来表示范围,也可以使用传统的写法,两者是等价的:
  1. varfirstForLoop=0
  2. foriin0..3{
  3. firstForLoop+=i
  4. }
  5. firstForLoop
  6. varsecondForLoop=0
  7. forvari=0;i<3;++i{
  8. secondForLoop+=1
  9. }
  10. secondForLoop
使用..创建的范围不包含上界,如果想包含的话需要使用...。
函数和闭包
使用func来声明一个函数,使用名字和参数来调用函数。使用->来指定函数返回值。
  1. funcgreet(name:String,day:String)->String{
  2. return"Hello\(name),todayis\(day)."
  3. }
  4. greet("Bob","Tuesday")
练习:删除day参数,添加一个参数来表示今天吃了什么午饭。
使用一个元组来返回多个值。
  1. funcgetGasPrices()->(Double,Double,Double){
  2. return(3.59,3.69,3.79)
  3. }
  4. getGasPrices()
函数的参数数量是可变的,用一个数组来获取它们:
  1. funcsumOf(numbers:Int...)->Int{
  2. varsum=0
  3. fornumberinnumbers{
  4. sum+=number
  5. }
  6. returnsum
  7. }
  8. sumOf()
  9. sumOf(42,597,12)
练习:写一个计算参数平均值的函数。
函数可以嵌套。被嵌套的函数可以访问外侧函数的变量,你可以使用嵌套函数来重构一个太长或者太复杂的函数。
  1. funcreturnFifteen()->Int{
  2. vary=10
  3. funcadd(){
  4. y+=5
  5. }
  6. add()
  7. returny
  8. }
  9. returnFifteen()
函数是一等公民,这意味着函数可以作为另一个函数的返回值。
  1. funcmakeIncrementer()->(Int->Int){
  2. funcaddOne(number:Int)->Int{
  3. return1+number
  4. }
  5. returnaddOne
  6. }
  7. varincrement=makeIncrementer()
  8. increment(7)
函数也可以当做参数传入另一个函数。
  1. funchasAnyMatches(list:Int[],condition:Int->Bool)->Bool{
  2. foriteminlist{
  3. ifcondition(item){
  4. returntrue
  5. }
  6. }
  7. returnfalse
  8. }
  9. funclessThanTen(number:Int)->Bool{
  10. returnnumber<10
  11. }
  12. varnumbers=[20,19,12]
  13. hasAnyMatches(numbers,lessThanTen)
函数实际上是一种特殊的闭包,你可以使用{}来创建一个匿名闭包。使用in来分割参数并返回类型。
  1. numbers.map({
  2. (number:Int)->Intin
  3. letresult=3*number
  4. returnresult
  5. })
练习:重写闭包,对所有奇数返回0。
有很多种创建闭包的方法。如果一个闭包的类型已知,比如作为一个回调函数,你可以忽略参数的类型和返回值。单个语句闭包会把它语句的值当做结果返回。
你可以通过参数位置而不是参数名字来引用参数——这个方法在非常短的闭包中非常有用。当一个闭包作为最后一个参数传给一个函数的时候,它可以直接跟在括号后面。
  1. sort([1,12,2]){$0>$1}
对象和类
使用class和类名来创建一个类。类中属性的声明和常量、变量声明一样,唯一的区别就是它们的上下文是类。同样,方法和函数声明也一样。
  1. classShape{
  2. varnumberOfSides=0
  3. funcsimpleDescription()->String{
  4. return"Ashapewith\(numberOfSides)sides."
  5. }
  6. }
练习:使用let添加一个常量属性,再添加一个接收一个参数的方法。
要创建一个类的实例,在类名后面加上括号。使用点语法来访问实例的属性和方法。
  1. varshape=Shape()
  2. shape.numberOfSides=7
  3. varshapeDescription=shape.simpleDescription()
这个版本的Shape类缺少了一些重要的东西:一个构造函数来初始化类实例。使用init来创建一个构造器。
  1. classNamedShape{
  2. varnumberOfSides:Int=0
  3. varname:String
  4. init(name:String){
  5. self.name=name
  6. }
  7. funcsimpleDescription()->String{
  8. return"Ashapewith\(numberOfSides)sides."
  9. }
  10. }
注意:self被用来区别实例变量。当你创建实例的时候,像传入函数参数一样给类传入构造器的参数。每个属性都需要赋值——无论是通过声明(就像numberOfSides)还是通过构造器(就像name)。
如果你需要在删除对象之前进行一些清理工作,使用deinit创建一个析构函数。
子类的定义方法是在它们的类名后面加上父类的名字,用冒号分割。创建类的时候并不需要一个标准的根类,所以你可以忽略父类。
子类如果要重写父类的方法的话,需要用override标记——如果没有添加override就重写父类方法的话编译器会报错。编译器同样会检测override标记的方法是否确实在父类中。
  1. classSquare:NamedShape{
  2. varsideLength:Double
  3. init(sideLength:Double,name:String){
  4. self.sideLength=sideLength
  5. super.init(name:name)
  6. numberOfSides=4
  7. }
  8. funcarea()->Double{
  9. returnsideLength*sideLength
  10. }
  11. overridefuncsimpleDescription()->String{
  12. return"Asquarewithsidesoflength\(sideLength)."
  13. }
  14. }
  15. lettest=Square(sideLength:5.2,name:"mytestsquare")
  16. test.area()
  17. test.simpleDescription()
练习:创建NamedShape的另一个子类Circle,构造器接收两个参数,一个是半径一个是名称,实现area和describe方法。
属性可以有 getter 和 setter 。
  1. classEquilateralTriangle:NamedShape{
  2. varsideLength:Double=0.0
  3. init(sideLength:Double,name:String){
  4. self.sideLength=sideLength
  5. super.init(name:name)
  6. numberOfSides=3
  7. }
  8. varperimeter:Double{
  9. get{
  10. return3.0*sideLength
  11. }
  12. set{
  13. sideLength=newValue/3.0
  14. }
  15. }
  16. overridefuncsimpleDescription()->String{
  17. return"Anequilateraltriaglewithsidesoflength\(sideLength)."
  18. }
  19. }
  20. vartriangle=EquilateralTriangle(sideLength:3.1,name:"atriangle")
  21. triangle.perimeter
  22. triangle.perimeter=9.9
  23. triangle.sideLength
在perimeter的 setter 中,新值的名字是newValue。你可以在set之后显示的设置一个名字。
注意EquilateralTriangle类的构造器执行了三步:
1. 设置子类声明的属性值
2. 调用父类的构造器
3. 改变父类定义的属性值。其他的工作比如调用方法、getters和setters也可以在这个阶段完成。
如果你不需要计算属性但是需要在设置一个新值之前运行一些代码,使用willSet和didSet。
比如,下面的类确保三角形的边长总是和正方形的边长相同。
  1. classTriangleAndSquare{
  2. vartriangle:EquilateralTriangle{
  3. willSet{
  4. square.sideLength=newValue.sideLength
  5. }
  6. }
  7. varsquare:Square{
  8. willSet{
  9. triangle.sideLength=newValue.sideLength
  10. }
  11. }
  12. init(size:Double,name:String){
  13. square=Square(sideLength:size,name:name)
  14. triangle=EquilateralTriangle(sideLength:size,name:name)
  15. }
  16. }
  17. vartriangleAndSquare=TriangleAndSquare(size:10,name:"anothertestshape")
  18. triangleAndSquare.square.sideLength
  19. triangleAndSquare.triangle.sideLength
  20. triangleAndSquare.square=Square(sideLength:50,name:"largersquare")
  21. triangleAndSquare.triangle.sideLength
类中的方法和一般的函数有一个重要的区别,函数的参数名只在函数内部使用,但是方法的参数名需要在调用的时候显式说明(除了第一个参数)。默认情况下,方法的参数名和它在方法内部的名字一样,不过你也可以定义第二个名字,这个名字被用在方法内部。
  1. classCounter{
  2. varcount:Int=0
  3. funcincrementBy(amount:Int,numberOfTimestimes:Int){
  4. count+=amount*times
  5. }
  6. }
  7. varcounter=Counter()
  8. counter.incrementBy(2,numberOfTimes:7)
处理变量的可选值时,你可以在操作(比如方法、属性和子脚本)之前加?。如果?之前的值是nil,?后面的东西都会被忽略,并且整个表达式返回nil。否则,?之后的东西都会被运行。在这两种情况下,整个表达式的值也是一个可选值。
  1. letoptionalSquare:Square?=Square(sideLength:2.5,name:"optionalsquare")
  2. letsideLength=optionalSquare?.sideLength
枚举和结构体
使用enum来创建一个枚举。就像类和其他所有命名类型一样,枚举可以包含方法。
  1. enumRank:Int{
  2. caseAce=1
  3. caseTwo,Three,Four,Five,Six,Seven,Eight,Nine,Ten
  4. caseJack,Queen,King
  5. funcsimpleDescription()->String{
  6. switchself{
  7. case.Ace:
  8. return"ace"
  9. case.Jack:
  10. return"jack"
  11. case.Queen:
  12. return"queen"
  13. case.King:
  14. return"king"
  15. default:
  16. returnString(self.toRaw())
  17. }
  18. }
  19. }
  20. letace=Rank.Ace
  21. letaceRawValue=ace.toRaw()
练习:写一个函数,通过比较它们的原始值来比较两个Rank值。
在上面的例子中,枚举原始值的类型是Int,所以你只需要设置第一个原始值。剩下的原始值会按照顺序赋值。你也可以使用字符串或者浮点数作为枚举的原始值。
使用toRaw和fromRaw函数来在原始值和枚举值之间进行转换。
  1. ifletconvertedRank=Rank.fromRaw(3){
  2. letthreeDescription=convertedRank.simpleDescription()
  3. }
枚举的成员值是实际值,并不是原始值的另一种表达方法。实际上,如果原始值没有意义,你不需要设置。
  1. enumSuit{
  2. caseSpades,Hearts,Diamonds,Clubs
  3. funcsimpleDescription()->String{
  4. switchself{
  5. case.Spades:
  6. return"spades"
  7. case.Hearts:
  8. return"hearts"
  9. case.Diamonds:
  10. return"diamonds"
  11. case.Clubs:
  12. return"clubs"
  13. }
  14. }
  15. }
  16. lethearts=Suit.Hearts
  17. letheartsDescription=hearts.simpleDescription()
练习:给Suit添加一个color方法,对spades和clubs返回“black”,对hearts和diamonds返回“red”。
注意:有两种方式可以引用Hearts成员:给hearts常量赋值时,枚举成员Suit.Hearts需要用全名来引用,因为常量没有显式指定类型。在switch里,枚举成员使用缩写.Hearts来引用,因为self的值已经知道是一个suit。已知变量类型的情况下你可以使用缩写。
使用struct来创建一个结构体。结构体和类有很多相同的地方,比如方法和构造器。它们结构体之间最大的一个区别就是 结构体是传值,类是传引用。
  1. structCard{
  2. varrank:Rank
  3. varsuit:Suit
  4. funcsimpleDescription()->String{
  5. return"The\(rank.simpleDescription())of\
  6. (suit.simpleDescription())"
  7. }
  8. }
  9. letthreeOfSpades=Card(rank:.Three,suit:.Spades)
  10. letthreeOfSpadesDescription=threeOfSpades.simpleDescription()
练习:给Card添加一个方法,创建一副完整的扑克牌并把每张牌的rank和suit对应起来。
一个枚举成员的实例可以有实例值。相同枚举成员的实例可以有不同的值。创建实例的时候传入值即可。实例值和原始值是不同的:枚举成员的原始值对于所有实例都是相同的,而且你是在定义枚举的时候设置原始值。
例如,考虑从服务器获取日出和日落的时间。服务器会返回正常结果或者错误信息。
  1. enumServerResponse{
  2. caseResult(String,String)
  3. caseError(String)
  4. }
  5. letsuccess=ServerResponse.Result("6:00am","8:09pm")
  6. letfailure=ServerResponse.Error("Outofcheese.")
  7. switchsuccess{
  8. caselet.Result(sunrise,sunset):
  9. letserverResponse="Sunriseisat\(sunrise)andsunsetisat\(sunset)."
  10. caselet.Error(error):
  11. letserverResponse="Failure...\(error)"
  12. }
练习:给ServerResponse和switch添加第三种情况。
注意:如何从ServerResponse中提取日升和日落时间。
接口和扩展
使用protocol来声明一个接口。
  1. protocolExampleProtocol{
  2. varsimpleDescription:String{get}
  3. mutatingfuncadjust()
  4. }
类、枚举和结构体都可以实现接口。
  1. classSimpleClass:ExampleProtocol{
  2. varsimpleDescription:String="Averysimpleclass."
  3. varanotherProperty:Int=69105
  4. funcadjust(){
  5. simpleDescription+="Now100%adjusted."
  6. }
  7. }
  8. vara=SimpleClass()
  9. a.adjust()
  10. letaDescription=a.simpleDescription
  11. structSimpleStructure:ExampleProtocol{
  12. varsimpleDescription:String="Asimplestructure"
  13. mutatingfuncadjust(){
  14. simpleDescription+="(adjusted)"
  15. }
  16. }
  17. varb=SimpleStructure()
  18. b.adjust()
  19. letbDescription=b.simpleDescription
练习:写一个实现这个接口的枚举。
注意:声明SimpleStructure时候mutating关键字用来标记一个会修改结构体的方法。SimpleClass的声明不需要标记任何方法因为类中的方法经常会修改类。
使用extension来为现有的类型添加功能,比如添加一个计算属性的方法。你可以使用扩展来给任意类型添加协议,甚至是你从外部库或者框架中导入的类型。
  1. extensionInt:ExampleProtocol{
  2. varsimpleDescription:String{
  3. return"Thenumber\(self)"
  4. }
  5. mutatingfuncadjust(){
  6. self+=42
  7. }
  8. }
  9. 7.simpleDescription
练习:给Double类型写一个扩展,添加absoluteValue功能。
你可以像使用其他命名类型一样使用接口名——例如,创建一个有不同类型但是都实现一个接口的对象集合。当你处理类型是接口的值时,接口外定义的方法不可用。
  1. letprotocolValue:ExampleProtocol=a
  2. protocolValue.simpleDescription
  3. //protocolValue.anotherProperty//Uncommenttoseetheerror
即使protocolValue变量运行时的类型是simpleClass,编译器会把它的类型当做ExampleProtocol。这表示你不能调用类在它实现的接口之外实现的方法或者属性。
泛型
在尖括号里写一个名字来创建一个泛型函数或者类型。
  1. funcrepeat<ItemType>(item:ItemType,times:Int)->ItemType[]{
  2. varresult=ItemType[]()
  3. foriin0..times{
  4. result+=item
  5. }
  6. returnresult
  7. }
  8. repeat("knock",4)
你也可以创建泛型类、枚举和结构体。
  1. //ReimplementtheSwiftstandardlibrary'soptionaltype
  2. enumOptionalValue<T>{
  3. caseNone
  4. caseSome(T)
  5. }
  6. varpossibleInteger:OptionalValue<Int>=.None
  7. possibleInteger=.Some(100)
在类型名后面使用where来指定一个需求列表——例如,要限定实现一个协议的类型,需要限定两个类型要相同,或者限定一个类必须有一个特定的父类。
  1. funcanyCommonElements<T,UwhereT:Sequence,U:Sequence,T.GeneratorType.Element:Equatable,T.GeneratorType.Element==U.GeneratorType.Element>(lhs:T,rhs:U)->Bool{
  2. forlhsIteminlhs{
  3. forrhsIteminrhs{
  4. iflhsItem==rhsItem{
  5. returntrue
  6. }
  7. }
  8. }
  9. returnfalse
  10. }
  11. anyCommonElements([1,3],[3])
练习:修改anyCommonElements函数来创建一个函数,返回一个数组,内容是两个序列的共有元素。
简单起见,你可以忽略where,只在冒号后面写接口或者类名。<T: Equatable>和<T where T: Equatable>是等价的。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


软件简介:蓝湖辅助工具,减少移动端开发中控件属性的复制和粘贴.待开发的功能:1.支持自动生成约束2.开发设置页面3.做一个浏览器插件,支持不需要下载整个工程,可即时操作当前蓝湖浏览页面4.支持Flutter语言模板生成5.支持更多平台,如Sketch等6.支持用户自定义语言模板
现实生活中,我们听到的声音都是时间连续的,我们称为这种信号叫模拟信号。模拟信号需要进行数字化以后才能在计算机中使用。目前我们在计算机上进行音频播放都需要依赖于音频文件。那么音频文件如何生成的呢?音频文件的生成过程是将声音信息采样、量化和编码产生的数字信号的过程,我们人耳所能听到的声音频率范围为(20Hz~20KHz),因此音频文件格式的最大带宽是20KHZ。根据奈奎斯特的理论,音频文件的采样率一般在40~50KHZ之间。奈奎斯特采样定律,又称香农采样定律。...............
前言最近在B站上看到一个漂亮的仙女姐姐跳舞视频,循环看了亿遍又亿遍,久久不能离开!看着小仙紫姐姐的蹦迪视频,除了一键三连还能做什么?突发奇想,能不能把舞蹈视频转成代码舞呢?说干就干,今天就手把手教大家如何把跳舞视频转成代码舞,跟着仙女姐姐一起蹦起来~视频来源:【紫颜】见过仙女蹦迪吗 【千盏】一、核心功能设计总体来说,我们需要分为以下几步完成:从B站上把小姐姐的视频下载下来对视频进行截取GIF,把截取的GIF通过ASCII Animator进行ASCII字符转换把转换的字符gif根据每
【Android App】实战项目之仿抖音的短视频分享App(附源码和演示视频 超详细必看)
前言这一篇博客应该是我花时间最多的一次了,从2022年1月底至2022年4月底。我已经将这篇博客的内容写为论文,上传至arxiv:https://arxiv.org/pdf/2204.10160.pdf欢迎大家指出我论文中的问题,特别是语法与用词问题在github上,我也上传了完整的项目:https://github.com/Whiffe/Custom-ava-dataset_Custom-Spatio-Temporally-Action-Video-Dataset关于自定义ava数据集,也是后台
因为我既对接过session、cookie,也对接过JWT,今年因为工作需要也对接了gtoken的2个版本,对这方面的理解还算深入。尤其是看到官方文档评论区又小伙伴表示看不懂,所以做了这期视频内容出来:视频在这里:本期内容对应B站的开源视频因为涉及的知识点比较多,视频内容比较长。如果你觉得看视频浪费时间,可以直接阅读源码:goframe v2版本集成gtokengoframe v1版本集成gtokengoframe v2版本集成jwtgoframe v2版本session登录官方调用示例文档jwt和sess
【Android App】实战项目之仿微信的私信和群聊App(附源码和演示视频 超详细必看)
用Android Studio的VideoView组件实现简单的本地视频播放器。本文将讲解如何使用Android视频播放器VideoView组件来播放本地视频和网络视频,实现起来还是比较简单的。VideoView组件的作用与ImageView类似,只是ImageView用于显示图片,VideoView用于播放视频。...
采用MATLAB对正弦信号,语音信号进行生成、采样和内插恢复,利用MATLAB工具箱对混杂噪声的音频信号进行滤波
随着移动互联网、云端存储等技术的快速发展,包含丰富信息的音频数据呈现几何级速率增长。这些海量数据在为人工分析带来困难的同时,也为音频认知、创新学习研究提供了数据基础。在本节中,我们通过构建生成模型来生成音频序列文件,从而进一步加深对序列数据处理问题的了解。
基于yolov5+deepsort+slowfast算法的视频实时行为检测。1. yolov5实现目标检测,确定目标坐标 2. deepsort实现目标跟踪,持续标注目标坐标 3. slowfast实现动作识别,并给出置信率 4. 用框持续框住目标,并将动作类别以及置信度显示在框上
数字电子钟设计本文主要完成数字电子钟的以下功能1、计时功能(24小时)2、秒表功能(一个按键实现开始暂停,另一个按键实现清零功能)3、闹钟功能(设置闹钟以及到时响10秒)4、校时功能5、其他功能(清零、加速、星期、八位数码管显示等)前排提示:前面几篇文章介绍过的内容就不详细介绍了,可以看我专栏的前几篇文章。PS.工程文件放在最后面总体设计本次设计主要是在前一篇文章 数字电子钟基本功能的实现 的基础上改编而成的,主要结构不变,分频器将50MHz分为较低的频率备用;dig_select
1.进入官网下载OBS stdioOpen Broadcaster Software | OBS (obsproject.com)2.下载一个插件,拓展OBS的虚拟摄像头功能链接:OBS 虚拟摄像头插件.zip_免费高速下载|百度网盘-分享无限制 (baidu.com)提取码:6656--来自百度网盘超级会员V1的分享**注意**该插件必须下载但OBS的根目录(应该是自动匹配了的)3.打开OBS,选中虚拟摄像头选择启用在底部添加一段视频录制选择下面,进行录制.
Meta公司在9月29日首次推出一款人工智能系统模型:Make-A-Video,可以从给定的文字提示生成短视频。基于**文本到图像生成技术的最新进展**,该技术旨在实现文本到视频的生成,可以仅用几个单词或几行文本生成异想天开、独一无二的视频,将无限的想象力带入生活
音频信号叠加噪声及滤波一、前言二、信号分析及加噪三、滤波去噪四、总结一、前言之前一直对硬件上的内容比较关注,但是可能是因为硬件方面的东西可能真的是比较杂,而且需要渗透的东西太多了,所以学习进展比较缓慢。因为也很少有单纯的硬件学习研究,总是会伴随着各种理论需要硬件做支撑,所以还是想要慢慢接触理论学习。但是之前总找不到切入点,不知道从哪里开始,就一直拖着。最近稍微接触了一点信号处理,就用这个当作切入点,开始接触理论学习。二、信号分析及加噪信号处理选用了matlab做工具,选了一个最简单的语音信号处理方
腾讯云 TRTC 实时音视频服务体验,从认识 TRTC 到 TRTC 的开发实践,Demo 演示& IM 服务搭建。
音乐音频分类技术能够基于音乐内容为音乐添加类别标签,在音乐资源的高效组织、检索和推荐等相关方面的研究和应用具有重要意义。传统的音乐分类方法大量使用了人工设计的声学特征,特征的设计需要音乐领域的知识,不同分类任务的特征往往并不通用。深度学习的出现给更好地解决音乐分类问题提供了新的思路,本文对基于深度学习的音乐音频分类方法进行了研究。首先将音乐的音频信号转换成声谱作为统一表示,避免了手工选取特征存在的问题,然后基于一维卷积构建了一种音乐分类模型。
C++知识精讲16 | 井字棋游戏(配资源+视频)【赋源码,双人对战】
本文主要讲解如何在Java中,使用FFmpeg进行视频的帧读取,并最终合并成Gif动态图。
在本篇博文中,我们谈及了 Swift 中 some、any 关键字以及主关联类型(primary associated types)的前世今生,并由浅及深用简明的示例向大家讲解了它们之间的奥秘玄机。