xml地图|网站地图|网站标签 [设为首页] [加入收藏]
Swift语言中与C,微信小程序豆瓣电影项目的改造
分类:编程

1.什么是闭包(Closure)?

闭包是一个完整的设计功能模块,可以在代码中传递和使用,类似于Object-C的block(但是还是有区别,下面会说明)或者其他语言的匿名函数(lambdas)。闭包可以捕获或者储存它们所在上下文的常量和变量。在Swift里等价于函数,是一等公民。

闭包有三种形式:

  • 全局函数,有名字的闭包并且不捕获任何值(定义的一般函数)
  • 嵌套函数,有名字的闭包,可以在闭包所在函数内部捕获值(函数里嵌套函数)
  • 闭包表达式,没有名字的闭包,使用简洁的语法,可以在包裹闭包的上下文捕获值(闭包)

举例说明:

 1 //Global function
 2 func block() {
 3     print("block")    //block
 4 }
 5 
 6 //Nested function
 7 func block(){
 8     let name = "block"
 9     func printStr() {
10         print(name)
11     }
12     printStr()
13 }
14 block()    //block
15 
16 //Closure expression
17 let block = {
18     print("block")
19 }
20 block()    //block

 

swift对闭包的表达式做了相关的优化:

  • 从上下文推断传入参数和返回值
  • 单一表表达式闭包的隐式返回
  • 简短的参数名
  • 尾随闭包

举例说明:

let numbers = [1, 3, 2, 4, 7, 8, 5]
let sortedNums = numbers.sorted { (a: Int, b: Int) -> Bool in
    return a > b
}
//下面常量返回的都是[8, 7, 5, 4, 3, 2, 1]

//从上下文推断传入参数和返回值
let sortedNums2 = numbers.sorted { (a, b) in
    return a > b
}

//单一表表达式闭包的隐式返回
let sortedNums = numbers.sorted { $0 > $1 }

//简短的参数名
let sortedNums2 = numbers.sorted { (a, b) in
    return a > b
}

//尾随闭包
let sortedNums = numbers.sorted { $0 > $1 }

 

2.闭包的表达式语法(Closure Expressions)

定义:

{(parameters) -> return type in
  statements
}

 

举一些例子:

//没有参数和返回值的block定义
let noParameterAndNoReturnValue: () -> () = {
    print("Hello world!")
}

//没有参数,有返回值的block定义
let noParameterAndReturnValue: () -> (Int) = {
    return 5
}

//有一个参数和返回值的block定义
let oneParameterAndNoReturnValue: (Int) -> (Int) = { x in
    return x + 2
}

//有多个参数和返回值的block定义
let mutipleParameterAndNoReturnValue: (Int, Int) -> (Int) = { (x, y) in
    return x + y
}

 

3.简短的参数名字(Shorthand argument syntax)

 1 // swift支持类型推断,什么意思呢?就是闭包的参数和返回类型都可以交给编译器去推断,在编码阶段就可以省略。闭包里面$0,$1代表的是传入的第一个参数和第二个参数,下面看代码:
 2 
 3 //$0代表第一个参数,$1代表第二个参数,语法非常简洁
 4 let numbers = [1, 3, 2, 4, 7, 8, 5]
 5 let sortedNums = numbers.sorted { $0 > $1 }    //[8, 7, 5, 4, 3, 2, 1]
 6 // 顺便提一下函数(闭包)参数省略的过程,还是以数组降序为例:
 7 
 8 let numbers = [1, 3, 2, 4, 7, 8, 5]
 9 let sortedNums = numbers.sorted { (a: Int, b: Int) -> Bool in
10     return a > b
11 }    //[8, 7, 5, 4, 3, 2, 1]
12 // 如果一个函数的返回类型和参数类型可以推导出来,则返回类型和参数类型都可以省略。删除:Int,-> Bool,上面的表达式变成:
13 
14 let numbers = [1, 3, 2, 4, 7, 8, 5]
15 let sortedNums = numbers.sorted { (a, b) in
16     return a > b
17 }    //[8, 7, 5, 4, 3, 2, 1]
18 // 如果参数的个数可以推导出来,则参数可以省略,使用$0,$1的方式代表参数。参数省略了,in关键字在这里就没有意义了,也可以省略,则上面的表达式变成:
19 
20 let numbers = [1, 3, 2, 4, 7, 8, 5]
21 let sortedNums = numbers.sorted {
22     return $0 > $1
23 }    //[8, 7, 5, 4, 3, 2, 1]
24 // 在swift里,如果函数体只有一行,则可以把return关键字省略,单一表达式闭包隐式返回,则代码进一步演变成:
25 
26 let numbers = [1, 3, 2, 4, 7, 8, 5]
27 let sortedNums = numbers.sorted {
28    $0 > $1
29 }    //[8, 7, 5, 4, 3, 2, 1]
30 // 最后,还能更近一步简化。可能很多人都郁闷了,就剩两个参数和操作符了,还能怎么简化?别急,swift里面还有一个简化规则,因为<也是函数,并且和函数sorted函数接收的参数个数,类型和返回值都一样,所以,能推导出来的东西都能简化,那么,更暴力的简化来了:
31 
32 let numbers = [1, 3, 2, 4, 7, 8, 5]
33 let sortedNums = numbers.sorted (by: > )    //[8, 7, 5, 4, 3, 2, 1]
34 // 看出来什么了没有?没错,这里的简化不是放在闭包里面的。我的理解是,整个闭包等价于>函数,所以,可以把整个闭包替换成了>函数,举个例子:
35 
36 let block: (Int, Int) -> (Int) = { $0 + $1 }
37 func testBlock(block: (Int, Int) -> (Int)) -> Int {
38     return block(1,3)
39 }
40 
41 testBlock{ $0 + $1 }    //3
42 testBlock(block: block)    //3

 

在学习微信小程序开发过程中,一部分的难点是前端逻辑的处理,也就是对前端JS的代码编辑;一部分的难点是前端界面的设计展示;本篇随笔基于一个豆瓣电影接口的小程序开源项目进行重新调整,把其中遇到的相关难点和改进的地方进行讨论介绍,希望给大家提供一个参考的思路,本篇随笔是基于前人小程序的项目基础上进行的改进,因此在开篇之前首先对原作者的辛劳致敬及感谢。

这一节,我们将会讨论一下Swift中的函数相关的基本内容

4.尾随闭包(Trailing Closures)

If you need to pass a closure expression to a function as the function’s final argument and the closure expression is long, it can be useful to write it as a trailing closure instead. A trailing closure is written after the function call’s parentheses, even though it is still an argument to the function. When you use the trailing closure syntax, you don’t write the argument label for the closure as part of the function call.

如果函数的最后一个参数是闭包,可以使用尾随闭包代替,举个例子:

func someFunctionThatTakesAClosure(closure: () -> Void) {
    // function body goes here
}

// Here's how you call this function without using a trailing closure:
//没有使用尾随闭包的函数调用情况
someFunctionThatTakesAClosure(closure: {
    // closure's body goes here
})

// Here's how you call this function with a trailing closure instead:
//使用了尾随闭包函数的调用情况
someFunctionThatTakesAClosure() {
    // trailing closure's body goes here
}

以数组的排序函数作为例子来看一下:

let numbers = [1, 3, 2, 4, 7, 8, 5]
let sortedNums = numbers.sorted(by: { $0 > $1 })    //没有使用尾随闭包,整个闭包写在sorted函数参数圆括号内,闭包内容多的话会显的很乱
let sortedNums = numbers.sorted() { $0 > $1 }    //使用尾随闭包,这样会使代码看起来很整洁

swift里还有一个规则,如果函数只有闭包一个参数,作为尾随闭包,可以把()去掉,使代码更为简洁,代码如下:

let numbers = [1, 3, 2, 4, 7, 8, 5]
let sortedNums = numbers.sorted(){ $0 > $1 }    //没有去掉"()"
let sortedNums = numbers.sorted { $0 > $1 }    //去掉"()"

1、豆瓣电影接口的小程序项目情况

豆瓣电影接口提供了很多相关的接口给我们使用,豆瓣电影接口的API地址如下所示:

图片 1

在GitHub的开源库里面,可以搜索到很多关于豆瓣电影接口的小程序,我本篇随笔是基于 weapp-douban-movie 这个小程序进行的改造处理,后来找到了原作者的项目地址:wechat-weapp-movie,原作者对版本做了一次升级,后来我对照我的调整和作者最新版本的源码,发现有些地方改造的思路有些类似,如对于URL地址外放到统一的配置文件中的处理,不过还是有很多地方改造不同。

本篇随笔的改造方案是基于小程序项目 weapp-douban-movie 的,因此对比的代码也是和这个进行比较,不知道这个版本是不是原作者的旧版本,不过这个版本对文件目录的区分已经显得非常干净利落了,对电影信息的展示也统一到了模板里面,进行多次的重复利用,整体的布局和代码都做的比较好,看得出是花了不少功夫进行整理优化的了。

小程序主界面效果如下所示:

图片 2

小程序源码目录结构如下所示:

图片 3

不过每个人都有不同的经验和看法,对于开发小程序来说,我侧重于使用配置文件减少硬编码的常量,使用Promise来优化JS代码的使用,将获取和提交JSON数据的方法封装到辅助类,以及使用地理位置接口动态获取当前城市名称和坐标等等。

本篇随笔下面的部分就是介绍使用这些内容进行代码优化的处理过程。

首先是函数的创建:

5.闭包捕获值(Capturing Values)

A closure can capture constants and variables from the surrounding context in which it is defined.

闭包可以捕获包裹它的上下文所定义的常量和变量。

(1)全局函数

var number = 0
var add = {
    number += 1
    print(number)
}

add()    //1
add()    //2
add()    //3
print(number)    //3

从上面的代码可以看出来,闭包捕获的是值的引用,当闭包内修改闭包外的值,闭包外的值也会跟着改变。

(2)函数嵌套函数

func makeIncrementer(from start: Int, amount: Int) -> ()->Int {
    var number = start
    return {
        number += amount
        return number
    }
}

let incrementer = makeIncrementer(from: 0, amount: 1)
incrementer()  //1
incrementer()  //2
incrementer()  //3

函数makeIncrementer返回的是一个没有参数返回整数的函数(闭包),所以,常量incrementer其实就是一个函数。每次调用incrementer()都会执行闭包里面的操作,而闭包的上下文就是makeIncrementer函数。从这也可以看出来,函数既能当返回值,也可以做参数,在swift妥妥的一等公民,比在Object-C的功能强大多了。

(3)swift中closure(闭包)和Object-C中block的区别

//block
NSInteger number = 1;
NSMutableString *str = [NSMutableString stringWithString: @"hello"];
void(^block)() = ^{
  NSLog(@"%@--%ld", str, number);
};
[str appendString: @" world!"];
number = 5;
block();    //hello world!--1

//closure
var str = "hello"
var number = 1
let block = {
    print(str + "--" + " (number)")
}
str.append(" world!")
number = 5
block()    //hello world!--5

一句话来说,block内部会对值类型做一份复制,并不指向之前的值的内存地址,而对于对象类型则会指向对象当前的内存地址,所以修改number时,block里的number数值不变,而修改字符串时,block里的字符串则改变了;closure则默认给外部访问的变量加上了__block修饰词的block。至于闭包里的循环引用,可以看一下OC与Swift闭包对比总结这篇文章。

1、使用配置文件定义常量内容

我们在使用任何代码开发程序的时候,我们都是非常注意一些变量或常量的使用,如果能够统一定义那就统一定义好了,这种在小程序的JS代码里面也是一样,我们尽可能抽取一些如URL,固定参数等信息到独立的配置文件中,这样在JS代码引入文件,使用变量来代替

例如原来的config.js文件里面,只是定义了一个地址和页面数量的大小常量,如下所示

module.exports = {
    city: '杭州',
    count: 20
}

原来的小程序代码在获取待映的电影内容时候,部分源码如下所示

图片 4

其他页面JS代码也和这个类似,头部依旧有很多类似这样URL地址,这个是我希望统一到config.js文件的地方,另外这个调用的函数是使用回调函数的处理方式,如下所示。

douban.fetchFilms.call(that, url, config.city, that.data.start, config.count)

其实我认为这里面既然是定义的外部函数,那么这里面的url, city, config.city, config.cout都不需要这里,在封装函数内部使用这些常量即可,因此可以对他们进行改造,如下我们统一抽取各个文件里面的URL,以及一些常见变量到config.js里面。

下面代码是我优化整理后的配置参数信息。

module.exports = {
    city: '',
    location:'0,0',
    count: 20,

    coming_soon_url: 'https://api.douban.com/v2/movie/coming_soon',
    in_theaters_url: 'https://api.douban.com/v2/movie/in_theaters',
    top_url: 'https://api.douban.com/v2/movie/top250',
    search_url: 'https://api.douban.com/v2/movie/search?tag=',
    detail_url: 'https://api.douban.com/v2/movie/subject/', //?id=
    celebrity_url: 'https://api.douban.com/v2/movie/celebrity/',
    baidu_ak:'6473aa8cbc349933ed841467bf45e46b',
    baidu_movie:'https://api.map.baidu.com/telematics/v3/movie',

    hotKeyword: ['功夫熊猫', '烈日灼心', '摆渡人', '长城', '我不是潘金莲', '这个杀手不太冷', '驴得水', '海贼王之黄金城', '西游伏妖片', '我在故宫修文物', '你的名字'],
    hotTag: ['动作', '喜剧', '爱情', '悬疑'],
}

上面的配置文件config.js里面,我统一抽取了各个页面的URL地址、关键词和标签(hotKeyword和hotTag)、城市及地址(city和location后面动态获取)、页面数量count等参数信息。

另外由于部分参数统一通过config.js获取,就不需要再次在调用的时候传入了,因此简化调用代码的参数传入,如下代码所示。

douban.fetchComming(that, that.data.start)

对于原先的代码

douban.fetchFilms.call(that, url, config.city, that.data.start, config.count)

简化的虽然不多,但是尽可能的保持干净简单的接口是我们的目标,而且这里把常规的URL等参数提取到函数里面,更加符合我们编码的习惯。

这里定义的douban.fetchComming(that, that.data.start) 使用了Promise来简化代码,传入的that参数是因为需要在函数体里面设置该页面里面的Data等处理。

 关于Promise的相关处理,我们在下面进行介绍。

 

func sayHello (name:String) -> String {
   return "Hello"+name            
} 

6.逃逸闭包(Escaping Closures)

A closure is said to escape a function when the closure is passed as an argument to the function, but is called after the function returns. When you declare a function that takes a closure as one of its parameters, you can write @escaping before the parameter’s type to indicate that the closure is allowed to escape.

逃逸闭包,指的是当一个函数有闭包作为参数,但是闭包的执行比函数的执行要迟。通俗来说,这个闭包的作用域本来是在当前函数里面的,然后它要逃出这个作用域,不想和函数同归于尽。那么闭包怎么逃逸呢?最简单的方法是把闭包赋值给外面的变量,举个例子:

var completionHandlers: [() -> Void] = []
//必须加上@escaping,不然编译会报错
func someFunctionWithEscapingClosure(completionHandler: @escaping () -> Void) {
    completionHandlers.append(completionHandler)
}

someFunctionWithEscapingClosure {
    print("hello")
}    //函数执行完,不会打印"hello"
completionHandlers.first?()    //打印"hello"

如果逃逸闭包访问的是类里面的成员,必须带上self来访问;如果访问的是全局的变量,则和非逃逸闭包一样。我的理解是,既然闭包逃逸了,则出了函数的作用域,则如果需要访问类里面的成员也找不到地址,因为函数已经被销毁,所以,需要带上类的地址self指针。

var completionHandlers: [() -> Void] = []
func someFunctionWithEscapingClosure(completionHandler: @escaping () -> Void) {
    completionHandlers.append(completionHandler)
}
func someFunctionWithNonescapingClosure(closure: () -> Void) {
    closure()
}

class SomeClass {
    var x = 10
    func doSomething() {
        someFunctionWithEscapingClosure { self.x = 100 }
        someFunctionWithNonescapingClosure { x = 200 }
    }
}

let instance = SomeClass()
instance.doSomething()
print(instance.x)
// Prints "200"

completionHandlers.first?()
print(instance.x)
// Prints "100"

2、使用Promise来优化JS代码

关于Promise的好处和如何使用Promise插件介绍,我在随笔《在微信小程序的JS脚本中使用Promise来优化函数处理》中已有介绍,我很喜欢使用这种Promise的风格代码,而且可以定义一些常用的辅助类来提高代码的重用。在我参考的这个豆瓣电影小程序还是使用常规回调的函数,对比原作者最新版本的 wechat-weapp-movie 小程序,也依旧使用回调函数模式来处理,有点奇怪为什么不引入Promise插件来开发。

原来的小程序,电影接口的相关处理,统一在fetch.js里面进行处理,这里封装对各种豆瓣API接口的调用。

图片 5

这里我们来看看原来程序没有采用Promise的回调函数处理代码

var config = require('./config.js')
var message = require('../../component/message/message')

module.exports = {
    fetchFilms: function(url, city, start, count, cb) {
      var that = this
      if (that.data.hasMore) {
        wx.request({
          url: url,
          data: {
            city: config.city,
            start: start,
            count: count
          },
          method: 'GET', 
          header: {
            "Content-Type": "application/json,application/json"
          },
          success: function(res){
            if(res.data.subjects.length === 0){
              that.setData({
                hasMore: false,
              })
            }else{
              that.setData({
                films: that.data.films.concat(res.data.subjects),
                start: that.data.start + res.data.subjects.length,
                showLoading: false
              })
            }
            wx.stopPullDownRefresh()
            typeof cb == 'function' && cb(res.data)
          },
          fail: function() {
            that.setData({
                showLoading: false
            })
            message.show.call(that,{
              content: '网络开小差了',
              icon: 'warning',
              duration: 3000
            })
          }
        })
      }
    },

这个函数是一个通用的函数,用来获取待映、热映、top250口碑的记录信息,不过它把参数抛给调用者传入,因此显得调用比较复杂一些,我们经过使用Promise优化代码处理,并对接口的参数进行简化,代码改造如下所示。

var config = require('./config.js')
var message = require('../../component/message/message')
var app = getApp()//获取应用实例

module.exports = {
    //待映
    fetchComming : function(page, start) {
      return this.fetchFilms(page, config.coming_soon_url, config.city, start, config.count);
    },
    //热映
    fetchPopular : function(page, start) {
      return this.fetchFilms(page, config.in_theaters_url, config.city, start, config.count);
    },
    //top250口碑
    fetchTop : function(page, start) {
      return this.fetchFilms(page, config.top_url, config.city, start, config.count);
    },

    //通用的热映、待映的获取方式
    fetchFilms: function(page, url, city, start, count) {
      return new Promise((resolve, reject) => {
        var that = page;
        var json = {city: city, start: start, count: count };
        var type = "json";//特殊设置,默认是application/json
        if (that.data.hasMore) {
          app.utils.get(url, json, type).then(res => {
              if(res.subjects.length === 0){
                that.setData({
                  hasMore: false,
                })
              }else{
                that.setData({
                  films: that.data.films.concat(res.subjects),
                  start: that.data.start + res.subjects.length,
                  showLoading: false
                })
              }
              wx.stopPullDownRefresh();

              resolve(res);            
          })
        }
      })
    },

最终的请求接口参数只有两个,一个是页面对象,一个是请求的起始位置,如下代码所示

function(page, start)

另外我们使用了代码

app.utils.get(url, json, type)

来对wx.request方法的统一封装,直接使用工具类里面的方法即可获取结果,不需要反复的、臃肿的处理代码。这就是我们使用Promise来优化JS,并抽取常用代码到工具类里面的做法。

我们再来对比一下获取电影详细信息的接口函数封装,原来代码如下所示。

    fetchFilmDetail: function(url, id, cb) {
      var that = this;
      wx.request({
        url: url + id,
        method: 'GET',
        header: {
          "Content-Type": "application/json,application/json"
        },
        success: function(res){
          that.setData({
            filmDetail: res.data,
            showLoading: false,
            showContent: true
          })
          wx.setNavigationBarTitle({
              title: res.data.title
          })
          wx.stopPullDownRefresh()
          typeof cb == 'function' && cb(res.data)
        },
        fail: function() {
          that.setData({
              showLoading: false
          })
          message.show.call(that,{
            content: '网络开小差了',
            icon: 'warning',
            duration: 3000
          })
        }
      })
    },

我改造后的函数代码如下所示。

    //获取电影详细信息
    fetchFilmDetail: function(page, id) {      
      return new Promise((resolve, reject) => {
        var that = page;
        var url = config.detail_url + id;
        var type = "json";//特殊设置,默认是application/json
        app.utils.get(url, {}, type).then(res => {
            that.setData({
              filmDetail: res,
              showLoading: false,
              showContent: true
            });

            wx.setNavigationBarTitle({
                title: res.title
            });
            wx.stopPullDownRefresh(); 

            resolve(res);   
        });
      })
    },

通过对fetch.js函数代码的改造处理,可以看到调用的JS代码参数减少了很多,而且页面也不用保留那么多连接等参数常量信息了。

    onLoad: function() {
        var that = this
        douban.fetchComming(that, that.data.start)
    },

 

上述即是函数的创建方法:

7.自动闭包(Autoclosures)

An autoclosure is a closure that is automatically created to wrap an expression that’s being passed as an argument to a function. It doesn’t take any arguments, and when it’s called, it returns the value of the expression that’s wrapped inside of it. This syntactic convenience lets you omit braces around a function’s parameter by writing a normal expression instead of an explicit closure.

自动闭包,我理解是,没有参数,函数体只有返回值,没有多余的其他变量,举个例子:

let printStr = { "hello" }
print(printStr())  //hello

var customersInLine = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
let customerProvider = { customersInLine.remove(at: 0) }
print("Now serving (customerProvider())!")  // Prints "Now serving Chris!"

注意:要保证自动闭包里面代码能正确执行,比如,在执行customerProvider()之前把数组清空,那么执行customerProvider()会报错,代码如下:

customersInLine.removeAll()
customerProvider()    //fatal error: Index out of range

自动闭包作为函数参数,不写"{}",直接写返回值

 1 var customersInLine = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
 2 
 3 //一般闭包
 4 func serve(customer customerProvider: () -> String) {
 5     print("Now serving (customerProvider())!")
 6 }
 7 serve(customer: {customersInLine.remove(at: 0)})    //Now serving Chris!
 8 
 9 //自动闭包
10 func serve(customer customerProvider: @autoclosure () -> String) {
11     print("Now serving (customerProvider())!")
12 }
13 serve(customer: customersInLine.remove(at: 0))    //Now serving Chris!

 

逃逸的自动闭包:

var customersInLine = ["Barry", "Daniella"]

// customersInLine is ["Barry", "Daniella"]
var customerProviders: [() -> String] = []
func collectCustomerProviders(_ customerProvider: @autoclosure @escaping () -> String) {
    customerProviders.append(customerProvider)
}
collectCustomerProviders(customersInLine.remove(at: 0))
collectCustomerProviders(customersInLine.remove(at: 0))

print("Collected (customerProviders.count) closures.")
// Prints "Collected 2 closures."
for customerProvider in customerProviders {
    print("Now serving (customerProvider())!")
}
// Prints "Now serving Barry!"
// Prints "Now serving Daniella!"

 

8.总结

swift的闭包比Object-C的block功能强大很多,更简洁,更高效。而且,很多集合类型都集成了闭包,比如:map,flatMap等等。这些闭包的功能都很强大,也为swift添加了不少便利性。

 

原文链接:

3、使用地理位置接口动态获取当前城市名称和坐标

原来程序使用硬编码的方式设置当前城市,如下脚本所示

module.exports = {
    city: '杭州',
    count: 20
}

不过我们不同地方的人员使用的时候,这个城市名称肯定需要变化的,因此可以使用微信的地理位置接口动态获取当前位置信息,然后写入到配置文件里面即可。

//获取当前位置信息
function getLocation (type) {
  return new Promise((resolve, reject) => {
    wx.getLocation({ type: type, success: resolve, fail: reject })
  })
}

//根据坐标获取城市名称
function getCityName (latitude = 39.90403, longitude = 116.407526) {
  var data = { location: `${latitude},${longitude}`, output: 'json', ak: '6473aa8cbc349933ed841467bf45e46b' };
  var url =  'https://api.map.baidu.com/' + 'geocoder/v2/';
  var type = 'json';

  return this.get(url, data, type).then(res => res.result.addressComponent.city);
}

然后我们在app.js里面编写代码,在app启动的时候,动态获取城市名称、坐标信息然后写入配置文件即可,这里使用的还是Promise的函数调用实现。

const utils  = require('./comm/script/util.js')
const config = require('./comm/script/config.js')

App({
  onLaunch: function() { 
    utils.getLocation()
    .then(res=>{
      const { latitude, longitude } = res;
      config.location = `${longitude},${latitude}`;//当前坐标
      console.log(`currentLocation : ${config.location}`);

      return utils.getCityName(latitude, longitude)
    })
    .then(name=>{
        config.city = name.replace('市', ''); //当前城市名称
        console.log(`currentCity : ${config.city}`)
    })
    .catch(err => {
      config.city = '广州'
      console.error(err)
    })
  },
...

最后呈上改造过代码的运行界面,还是保留原来的功能正常使用。

图片 6

以上就是我对这个小程序进行不同方面的调整思路和经验总结,希望大家有所收益或者建议,感谢阅读支持。 

 

func函数声明的关键字 
sayHello函数名 
(name:String)参数列表 
-> String函数的返回值
 {
   return "Hello"+name函数体         
} 

当函数没有返回值的时候可以这样写:

本文由澳门新葡亰手机版发布于编程,转载请注明出处:Swift语言中与C,微信小程序豆瓣电影项目的改造

上一篇:字符和字符串,零基础Python知识点回顾 下一篇:Python数据结构澳门新葡亰手机版
猜你喜欢
热门排行
精彩图文