vscode 切换 python 版本
2023-01-07 tech vscode python 1 mins 2 图 76 字
使用快捷键 Ctrl+Shift+P
打开命令窗口:
选择 “Python: Select Interpreter”,弹窗显示现有的 Python 版本:
使用快捷键 Ctrl+Shift+P
打开命令窗口:
选择 “Python: Select Interpreter”,弹窗显示现有的 Python 版本:
做一个 appium 在 Mac M1 下的安装备忘,系统 Ventura 13.0。
官方网站:https://appium.io/
官方的快速安装命令:
> brew install node # get node.js
> npm install -g appium # get appium
> npm install wd # get appium client
> appium & # start appium
> node your-appium-test.js
可以在官网下载,也可以用homebrew下载。在官网下载 npm install -g
时候会报权限问题,只有用 sudo 才行。为了避免这种问题,我还是使用 homebrew下载了,避免以后可能出现权限问题还需要定位。
官网:https://nodejs.org/zh-cn/download/
• Node.js v18.12.1 to /usr/local/bin/node • npm v8.19.2 to /usr/local/bin/npm 
出现权限问题的错误:
改用
homebrew
了:
brew install node
which node
which npm
node -v
npm -v
npm install -g appium
npm install wd
Appium doctor是一个小型软件,它检查Appium成功运行的所有(几乎所有)前提条件。
npm install -g appium-doctor
brew install java
再把这部分内容塞到 /etc/profile
文件去。
JAVA_HOME=/opt/homebrew/opt/openjdk
export JAVA_HOME
然后source一下:
source /etc/profile
Carthage是一个依赖管理器,WebDriverAgent 需要它
brew install carthage
在GitHub上下载安装即可。
接下来我先尝试在iOS上运行出来,warning的内容也在iOS部分解决了。
一定要先安装好 xcode,可以参考我这篇:《iOS 开发环境配置备忘》
检查 iOS依赖有没有安装好
appium-doctor --ios
下文运行获得一些数据,所以装这两个工具方便获取。
brew install libimobiledevice
brew install ideviceinstaller
idevice_id
instruments -s devices # 列出设备包括模拟器、真机及 mac 电脑本身
ideviceinfo # 可以在返回的数据中找到 udid
ideviceinstaller --list-apps # 列出app
ideviceinstaller -l # 列出app
idevicenotificationproxy -h
首先手机要在 设置> 隐私与安全性 下找到 “开发者模式”开关 开启开发者模式。
我看到有的教程直接使用 appium 自带的 webdriveragent
代码,因为我的xcode版本比较新,使用这些老代码 编译 都不过,所以还是直接使用最新的源码代替了。
去 https://github.com/appium/WebDriverAgent/releases 下载源码
双击 WebDriverAgent.xcodeproj
后打开:
然后修改WebDriverAgentRunner
和 WebDriverAgentLib
证书为自己的证书(在真机上运行需要),新建的话只要登陆我们的apple id即可,不需要付费。
同时修改 Bundle identifier
,把 Facebook
的内容换成自己的。
选择 Product->Scheme->WebDriverAgentRunner
,
选择 Product->Destination
, 运行的设备为本机设备,例如我的设备名叫 とある血衫のiPhone
。
接下来点击三角形▶️先进行编译。
Ps:如果某个开发者账号签名的所有 App 都被删除的话下次再安装又要重新信任才能运行,你可能会遇到这个错误:
在手机上也能看到这样的提示:
在设备上
通用->VPN与设备管理->开发者APP
里选择信任证书即可。
编译OK后运行test:
本机访问 127.0.0.1:8100/status
遇到了诸多问题,记录几个:
ld: cannot link directly with dylib/framework, your binary is not an allowed client arm64
根据一个答案的提示,换了最新的webdriveragent源码:https://developer.apple.com/forums/thread/712039
着手解决 opencv4nodejs 的 warning。也是尽力而为了,最后只把ffmpeg的warning消掉了(安装opencv自动装好的)
https://appium.io/docs/en/writing-running-appium/image-comparison/
我遇到了好些错误,比如:
npm ERR! info install OPENCV_LIB_DIR is not set, looking for default lib dir npm ERR! info install using lib dir: /usr/local/lib npm ERR! /opt/homebrew/lib/node_modules/opencv4nodejs/install/install.js:45 npm ERR! throw new Error(‘no OpenCV libraries found in lib dir: ‘ + libDir)
查了一些问题:https://github.com/justadudewhohacks/opencv4nodejs/issues/733#issuecomment-988898236
brew install cmake
brew install opencv
npm i -g opencv4nodejs
opencv 要装的依赖还挺多的,等的比较久:
==> Fetching dependencies for opencv: eigen, gflags, glog, metis, gmp, isl, mpfr, libmpc, xz, gcc, openblas, suite-sparse, tbb, ceres-solver, highway, imath, libpng, openexr, webp, jpeg-xl, libvmaf, aom, dav1d, frei0r, bdw-gc, m4, libtool, libunistring, guile, libidn2, libtasn1, nettle, p11-kit, unbound, gnutls, lame, fribidi, pcre2, glib, libxau, libxdmcp, libx11, libxrender, pixman, harfbuzz, libunibreak, libass, libbluray, cjson, cmocka, mbedtls, librist, libsoxr, libvidstab, libogg, libvorbis, libvpx, opencore-amr, openjpeg, opus, rav1e, flac, mpg123, libsndfile, libsamplerate, rubberband, sdl2, snappy, speex, srt, leptonica, libb2, libarchive, pango, tesseract, theora, x264, x265, xvid, libsodium, zeromq, zimg, ffmpeg, numpy, protobuf, sqlite, python@3.11, boost, double-conversion, gl2ps, glew, libaec, hdf5, jsoncpp, netcdf, pugixml, qt@5, pyqt@5, utf8cpp and vtk
https://developer.android.com/studio#downloads
点击进入默认会要求下载模拟器
不小心点掉了的话,在 Preference 里搜索 SDK ,点击 edit 可以继续下载:
增加 android 版本:
完成:
再把这部分内容塞到 /etc/profile
文件去。
ANDROID_HOME=/Users/kelu/Library/Android/sdk
export ANDROID_HOME
然后source一下:
source /etc/profile
一些安装相关的问题:
Set ANDROID_HOME environment variable in mac
‘apkanalyzer’ is not recognized as an internal or external command
appium &
能跑了之后先把命令行kill掉,我们改用 gui 运行。
其他不用改,选中 Allow CORS
即可,然后 startServer
安卓的试运行和iOS/android的详细使用方法再开新的文章讲讲,这里简单列一下iOS试运行的配置和结果。
配置参考:Appium Desired Capabilities
Remote Path 要填 /wd/hub
:
可以直接修改右侧的json,填入一下内容:
{
"platformName": "iOS",
"platformVersion": "13.2",
"deviceName": "填写手机的deviceName",
"automationName": "XCUITest",
"udid": "填手机的udid",
"bundleId": "填应用的bundleId",
"xcodeOrgId": "填开发者id",
"xcodeSigningId": "iPhone Developer",
"useNewWDA": false,
"noReset": true,
"newCommandTimeo": "60"
}
具体的参数如下获取:
platformVersion 如上文在本机浏览器访问 127.0.0.1:8100/status
获得。
idevice_id -l # 获取udid
ideviceinfo -k DeviceName # 获取deviceName
ideviceinfo -k ProductVersion # 获取系统版本
ideviceinstaller -l -o list_user # 获取bundleId,也就是应用名
获取xcodeOrgId
,在这个界面下点击那个 Other
就能获取了:
最后的 json:
{
"platformName": "iOS",
"platformVersion": "16.1",
"deviceName": "とある血衫のiPhone",
"automationName": "XCUITest",
"udid": "xxx",
"bundleId": "com.reederapp.5.iOS",
"xcodeOrgId": "xxx",
"xcodeSigningId": "iPhone Developer",
"useNewWDA": false,
"noReset": true,
"newCommandTimeo": "60"
}
Server GUI 显示:
手机显示:
Inspector显示:
为了防止你的手机自动锁定,建议可以选择取消自动锁定,在iOS16下层级为:
设置->显示与亮度->自动锁定->永不
python 代码驱动:
pip install appium-python-client
几个代码备忘:
selenium.common.exceptions.WebDriverException: Message: An unknown server-side error occurred while processing the command. Original error: The attribute 'accessibility_id' is unknown. Valid attribute names are: (
UID,
accessibilityContainer,
accessible,
enabled,
focused,
frame,
index,
label,
name,
rect,
selected,
type,
value,
visible,
wdAccessibilityContainer,
wdAccessible,
wdEnabled,
wdFocused,
wdFrame,
wdIndex,
wdLabel,
wdName,
wdRect,
wdSelected,
wdType,
wdUID,
wdValue,
wdVisible
)
Stacktrace:
UnknownError: An unknown server-side error occurred while processing the command. Original error: The attribute 'accessibility_id' is unknown. Valid attribute names are: (
UID,
accessibilityContainer,
accessible,
enabled,
focused,
frame,
index,
label,
name,
rect,
selected,
type,
value,
visible,
wdAccessibilityContainer,
wdAccessible,
wdEnabled,
wdFocused,
wdFrame,
wdIndex,
wdLabel,
wdName,
wdRect,
wdSelected,
wdType,
wdUID,
wdValue,
wdVisible
)
金融科技标准解读系列之《金融服务 生僻字处理指南》,视频链接可微信扫描海报二维码
做个简单备忘。以后还得继续练习补充。
官方reference:https://developer.apple.com/cn/documentation/swift/
https://swiftgg.gitbook.io/swift/huan-ying-shi-yong-swift
let bmi = wight / (height * height)
bmiValue = String(format: "%.1f", bmi)
基础数据类型
Int
表示整型值;
UInt
无符号类型;
Double
和 Float
表示浮点型值;
Bool
是布尔型值;
String
是文本型数据。
var stringA = "Hello, World!"
let stringB = String("kelu.org")
var stringC = stringA + stringB
// 字符串长度使用 String.count 属性来计算
stringC.count
相关函数:
Character 字符。
nil
空。
可选类型 optional
如果一个可选类型的实例包含一个值,可以用后缀操作符 !来访问这个值(强制解析),但去获取值为nil的可选变量会有运行时错误。
var optionalInteger: Int?
var optionalInteger: Optional<Int>
var username:<data type> = <optional initial value>
var username: String? = nil
也可以在声明可选变量时使用感叹号(!)替换问号(?)。这样可选变量在使用时就不需要再加一个感叹号(!)来获取值,它会自动解析。
方法4相当于三元操作符?:
。我比较喜欢这种方式。
类型别名
对当前的类型定义了另一个名字,类型别名通过使用 typealias 关键字来定义。语法格式如下:
typealias newname = type
类型安全
在编译代码时进行类型检查(type checks),并把不匹配的类型标记为错误。
类型推断
没有显式指定类型,Swift 会使用类型推断(type inference)来选择合适的类型。
变量
var variableName = <initial value>
常量
let constantName = <initial value>
let constB:Float = 3.14159 // 3.14159 为字面量
let constantName:<data type> = <optional initial value>
字面量是指由字母,数字等构成的字符串或者数值,它只能作为右值出现。
数组Array
var someInts = [Int](repeating: 0, count: 3)
var someInts:[Int] = [10, 20, 30]
字典Dictionary
var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
var removedValue = someDict.removeValue(forKey: 2)
for (key, value) in someDict {
print("字典 key \(key) - 字典 value \(value)")
}
for (key, value) in someDict.enumerated() {
print("字典 key \(key) - 字典 (key, value) 对 \(value)")
}
// 转数组
let dictKeys = [Int](someDict.keys)
let dictValues = [String](someDict.values)
错误处理
func makeASandwich() throws {
// ...
}
do {
try makeASandwich()
eatASandwich()
} catch SandwichError.outOfCleanDishes {
washDishes()
} catch SandwichError.missingIngredients(let ingredients) {
buyGroceries(ingredients)
}
枚举
// 定义枚举
enum DaysofaWeek {
case Sunday
case Monday
case TUESDAY
case WEDNESDAY
case THURSDAY
case FRIDAY
case Saturday
}
Swift中的闭包有很多优化的地方:
{(parameters) -> return type in
statements
}
{(Int, Int) -> Bool in
Statement1
Statement 2
---
Statement n
}
闭包表达式
排序完成后,sorted(by:) 方法会返回一个与原数组大小相同,包含同类型元素且元素已正确排序的新数组。原数组不会被 sorted(by:) 方法修改。
import Cocoa
let names = ["AT", "AE", "D", "S", "BE"]
// 使用普通函数(或内嵌函数)提供排序功能,闭包函数类型需为(String, String) -> Bool。
func backwards(s1: String, s2: String) -> Bool {
return s1 > s2
}
var reversed = names.sorted(by: backwards)
print(reversed)
// ["S", "D", "BE", "AT", "AE"]
参数名称缩写,$0,$1,$2
import Cocoa
let names = ["AT", "AE", "D", "S", "BE"]
var reversed = names.sorted( by: { $0 > $1 } )
print(reversed)
运算符函数
import Cocoa
let names = ["AT", "AE", "D", "S", "BE"]
var reversed = names.sorted(by: >)
print(reversed)
尾随闭包是一个书写在函数括号之后的闭包表达式,函数支持将其作为最后一个参数调用。
func someFunctionThatTakesAClosure(closure: () -> Void) {
// 函数体部分
}
// 以下是不使用尾随闭包进行函数调用
someFunctionThatTakesAClosure({
// 闭包主体部分
})
// 以下是使用尾随闭包进行函数调用
someFunctionThatTakesAClosure() {
// 闭包主体部分
}
import Cocoa
let names = ["AT", "AE", "D", "S", "BE"]
//尾随闭包
var reversed = names.sorted() { $0 > $1 }
print(reversed)
// ["S", "D", "BE", "AT", "AE"]
sort() 后的 { $0 > $1} 为尾随闭包。
注意: 如果函数只需要闭包表达式一个参数,使用尾随闭包时,可以把
()
省略掉。reversed = names.sorted { $0 > $1 }
struct MarksStruct {
var mark: Int
init(mark: Int) {
self.mark = mark
}
}
var aStruct = MarksStruct(mark: 98)
var bStruct = aStruct // aStruct 和 bStruct 是使用相同值的结构体!
bStruct.mark = 97
print(aStruct.mark) // 98
print(bStruct.mark) // 97
class SomeClass: SomeSuperclass {
// 类的定义
}
Class 必须提供init函数,struct 不需要提供。
class 是引用传递,所以直接let class1 = class2
,对class1进行操作,class2取出来也会变化,因为是同一个class。
struct 是值传递,所以 let struct1 = struct2
,得到的是两个不同的struct。
Struct 是immutable
的,方法要修改struct
的值必须声明mutating
。
从父类强制指定子 class: as!
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destination.
// Pass the selected object to the new view controller.
if segue.identifier == "testSeg" {
let destinationVC = segue.destination as! ResultViewController
destinationVC.bmiValue = calculatorBrain.getBMIValue()
destinationVC.advice = calculatorBrain.getAdvice()
destinationVC.color = calculatorBrain.getColor()
}
}
https://docs.swift.org/swift-book/LanguageGuide/Closures.html
如果函数最后一个参数是闭包,可以直接扔在最后,叫尾随闭包。
protocol 就是一种简易灵活的继承方式。
delegate 设计模式。(有点像用类继承的方式封装的观察者模式/事件模式。普通的事件模式你需要监听事件和传输内容,在delegate中你只需在controller中写明某个组件的delegate为self,即可在controller中直接使用对应的事件方法。)
扩展就是向一个已有的类、结构体或枚举类型添加新功能。扩展可以对一个类型添加新的功能,但是不能重写已有的功能:
extension SomeType: SomeProtocol, AnotherProctocol {
// 协议实现写到这里
}
sudo gem install cocoapods
拉数据。
pod setup --verbose
pod init
pod install
2019 WWDC发布。
很多灵感来自网页设计。
元素堆叠的感觉,让我想起了前端vue的自定义标签。
看来多学一点框架也不是坏事,可以互通各自的设计理念。搞的我有点想看一下另一个前端框架了。
按照一些教学视频做的简单备忘:
这篇文章主要记录一些环境配置的内容,涉及代码的地方以 objectc为主,interface以storyboard为主。
后续分成几篇分别记录 objectc , swift , swiftUI 的 reference。
个人认为,对于有代码能力的人来说,这些教程内容都太过冗长,实际操作中我一般快速扫过视频,让脑子有个印象即可,需要学习特定内容再使用 chatgpt + 返回教程回顾,可以省下大量时间,并且在学习的过程中给自己更强的信心。
iOS和其他后端语言相比,乍一看让人生畏的地方,可能就是可视化的那些内容。至少我一开始是这样看的。稍微掌握之后就可以直接实战了。我甚至想到了photoshop的一些操作。
一台MacBook Air/Pro 或者 Mac mini/studio 或者 iMac
一台iPhone,iPad也可以。
macOS,一个较新的版本。
Xcode:,一个较新的版本。
https://developer.apple.com/support/xcode,这里列了不同版本 xcode 的OS、sdk支持情况。
Xcode也可以直接在 app store 中下载,但就不能选择特定版本了。
另外不要下载Beta版本,以免有奇怪的bug。
一个apple 开发者账号。
只开发不发布的话,是免费的,不需要付费。 https://developer.apple.com
一个良好、稳定的网络环境。
Xcode
的Help链接里有文档:
还有一个app,名字叫 Developer:
GitHub Awesome :https://github.com/dkhamsing/open-source-ios-apps
udemy 教材相关链接:https://www.appbrewery.co/p/ios-course-resources/,我也保存了一份pdf备份。
令人发指的函数式编程和相关语法糖
Project interface分为 Storyboard 和 SwiftUI。这两者的区别为:
storyboards
和 XIB
(Xml Interface Builder) 包含相当多的 XML
语句,不容易阅读,也不容易编辑。storyboards
随着时间的推移越来越大。XIB
和 Swift
是非常独立的东西,XIB
对 Swift
代码不了解,而 Swift
代码对 XIB
也不了解。Swift
的框架。storyboards
的 XML
更容易阅读和管理。最简单的创建:
Main.storyboard
文件用来设计、拖拽。如果是在真机上运行:
以上都是免费的,不需要注册开发者账号。如果使用模拟器,则不用这么麻烦。
另外如果是从互联网上下载的代码,建议不要随意在真机上运行,有安全风险。
设置-> 通用->VPN与设备管理:
如果你的账号是团队的成员,我这边遇到好几个问题顺便记录一下(2023.08.20):
在账号中不显示团队信息,
大概率是在web配置页面,管理员没有配置你为开发者,并且开启了拉取配置信息的权限。
Failed to register bundle identifier The app identifier “xxx” cannot be registered to your development team because it is not available. Change your bundle identifier to a unique string to try again.
这里参考 Xcode Error: “The app ID cannot be registered to your development team.”
cd ~/Library/MobileDevice/Provisioning\ Profiles rm * Xcode > Preferences... > Accounts > click your Account and Team name > click Download Manual Profiles
running,点击这个三角形
就在真机运行。
在Windows-> Devices and Simulators 可以看到设备列表:
Preview 可以在这里设置:
框架:
一般后端常讲 mvc,在iOS等前端语言中一般说mvvm,个人感觉是一样的概念。MVC:
(视频在model里)声明protocol:
controller 里实现:
关键字是 in
转成闭包:
将函数作为返回值,如下。
最后精简为:
calculator(n1:2,n2:3){$0 * $1}
这种场景下,就可以用闭包代替。一步一步代替:
把multiply改成闭包:
挪到调用的地方:
让编译器自个判断闭包的返回值类型
return可以省略:
把3行换成1行显示
用匿名参数$0 $1
swift的规则,如果函数的最后一个参数是闭包,可以直接把这个参数省略掉,扔到括号外。(逆天!!!,可读性逆天!!!)
另一个逆天的缩写,这次用map函数:
一步一步来:
最终结果:
UI的内容更新要在主线程里:DispatchQueue.main
以下开始是 xcode 的一些简单功能
右上角的+用得最多了,添加各种组件。
asset 目录里有很多不同尺寸的图(注意设置All Size
):
Image Set -> Appearance -> 设置明色与暗色
Image Set-> Resizing -> 保留矢量信息
选择 Assistant 可以将代码和界面放一起:
声明组件和Action可以用拖拽的方式,ctrl+拖动
放在 class的前部分默认就是 outlet,放在后部分默认就是Action。
关联关系可以在图形上右键查看:
选集,061 Setting Constraints and working with the Safe Area
指定item和边缘的距离。
iOS里的stack view组件可以类比为html中的div组件。
view controller里的文件视图类似于photoshop里的图层反过来。
上图右下角的最右边那个收纳的图标。
这样在图形化界面里我们就根本看不见这个view了,没办法用拖拽的方式给它添加东西。
swift
文件:命名为ViewController secondVC,改一下 import 为
UIKit`
定义一些基本的变量保存数据
override func viewDidLoad
定义一个组件,例如 UILabel
在上一个页面的ViewController
里给 secondVC 的变量赋值
在上一个页面的ViewController
里 self.present(secondVC, animated:true, completion: nil)
在图形界面新建一个viewController
新建一个cocoa touch class
:
然后在 storyboard 里点一下还没有绑定 vc 的图形:
选择之后就可以看到它绑定好了。
点击中间那个关联的方块,设定segues的identifier名字:
然后在代码中触发这个切换:
self.performSegue(withIdentifier: "testSeg", sender: self)
同时,在前一个 controller 里我们可以做这个view 在切换前的准备工作。
先点击第一个viewcontroller(黄色的图标),再点击再菜单栏上选择 Editor->Embed In->Navigation Controller
,
navitationItem.hidesBackButton = true
给另一个 vc 创建变量:
转场的时候,将数值传过去:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destination.
// Pass the selected object to the new view controller.
if segue.identifier == "testSeg" {
let destinationVC = segue.destination as! ResultViewController
destinationVC.bmiValue = calculatorBrain.getBMIValue()
destinationVC.advice = calculatorBrain.getAdvice()
destinationVC.color = calculatorBrain.getColor()
}
}
在新的vc里返回上一个view: 用 dismiss
方法
@IBAction func recalculatePressed(_ sender: UIButton) {
dismiss(animated: true, completion: nil)
}
确保应用在运行时,可以用3D的方式查看图层,点击中间那个三个图层叠加的图标Debug View Hierarchy
:
sudo gem install cocoapods
pod setup --verbose
更详细内容参考这篇《cocoapods 初接触》
Udemy付费课程 iOS13 & Swift - The Complete iOS App Development Bootcamp
up 推荐面向Google 和stack overflow编程。
swift相关,没啥看头
看一个时间控制器:
也没啥看头
同样一个时间控制器:
用 UISlider
也教了一些使用reference文档的方法,124
查查api开发之类的。
https://github.com/appbrewery/Flash-Chat-iOS13
Timer.scheduledTimer
这些内容我觉得 斯坦福 那个视频更好。
Firebase 是由 Google 提供的一套为开发者提供后端服务的平台,可以帮助开发者快速构建高质量的移动应用、Web 应用和桌面应用。Firebase 提供了多种功能,包括实时数据库、身份认证、云存储、云函数、分析、消息推送等。
对于 iOS 和 Android 开发者来说,Firebase 提供了一系列 SDK 和工具,使他们可以轻松地集成 Firebase 功能到他们的应用中。以下是 Firebase 提供的一些主要功能:
实时数据库 (Realtime Database):Firebase 的实时数据库是一个云托管的 NoSQL 数据库,它能够实时同步数据,使得多个客户端能够同时查看和修改数据,而不需要编写复杂的同步代码。
身份认证 (Authentication):Firebase 身份认证提供了简单易用的身份验证功能,支持电子邮件/密码、手机号码、Google、Facebook、Twitter、GitHub 等多种登录方式。
云存储 (Cloud Storage):Firebase 的云存储可以让开发者轻松地将用户生成的内容,如图像、视频或用户数据存储到云端,而无需自己搭建服务器。
云函数 (Cloud Functions):Firebase 云函数让开发者能够以事件驱动的方式在云端运行代码,例如在数据库写入时触发某些操作。
分析 (Analytics):Firebase 分析提供了应用的使用情况分析,包括用户行为、用户流、转化率等指标,帮助开发者了解用户并改进应用。
消息推送 (Cloud Messaging):Firebase 云消息推送可以向应用的用户发送通知消息,包括文字、图像和声音等。
性能监控 (Performance Monitoring):Firebase 提供了性能监控功能,帮助开发者监控应用的性能指标,并定位性能问题。
A/B 测试 (A/B Testing):Firebase 提供了 A/B 测试功能,让开发者能够测试不同功能或设计对用户行为的影响,从而优化应用。
总的来说,Firebase 提供了一整套的后端解决方案,使得开发者可以专注于应用的前端开发,而无需花费大量精力在搭建和管理后端服务上。
一直卡在 install
中。重启了好几次都没用。
下班回家第二天来,发现已经装好了。
微信的路径根据各自需要改:
@ECHO OFF
start /d "C:\Program Files (x86)\Tencent\WeChat\" WeChat.exe
start /d "C:\Program Files (x86)\Tencent\WeChat\" WeChat.exe
exit
把文件保存成 xxx.bat
,双击运行即可。原理就是趁着系统还没反应过来多开几个微信实例。
如果想多开几个,把 start 那行多写几遍就可以了。
echo "nohup /Applications/WeChat.app/Contents/MacOS/WeChat >/dev/null 2>&1 &" > ~/Desktop/WeChat.command
chmod +x ~/Desktop/WeChat.command
双击桌面的WeChat.command
文件即可。
Mac下还有相关的插件可以使用,比如这个 A dynamic library tweak for WeChat macOS
ps: 这个插件还能防撤回
Pps: 如果注入出错,可以尝试换一个终端。系统弹出允许提示有时候没法显示,就会导致注入出错。