0%

反馈请联系hertz@hertzwang.com,谢谢

前言:用Safari的访问一个网址,然后将网址添加到主屏幕,这时会在主屏幕上生成一个书签(带有Icon和标题),点击该书签后会访问指定的网址,在指定的网址中使用“scheme://”的方式打开应用,关于iOS 14上的使用参考底部的iOS 14 示例

使用远程Web

使用Safari打开链接并添加到主屏幕从而得到桌面快捷方式,通过window.navigator.standalone来区分状态,在Safari中加载时显示引导信息,独立全屏运行(点击主屏幕的快捷图标)时使用scheme来打开App,例如:scheme://modules?id=1

HTML示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
<!DOCTYPE html>
<html>
<head>
<meta name="apple-mobile-web-app-capable" content="yes" >
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta content="text/html charset=UTF-8" http-equiv="Content-Type"/>
<meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no"/>
<link rel='apple-touch-icon' href='https://xxx.png'>
<title>主屏幕显示的名称</title>
</head>
<body>
<a id="startApp" style="display:none"></a>
<div id="msg">
<div class="main">
<div>点击下方工具栏上\n并点击添加到主屏幕</div>
</div>
</div>
</body>
<script>
var url = location.search; // 获取url中"?"符后的字串
if (window.navigator.standalone == true) {
document.getElementById("msg").innerHTML= '';
document.getElementById("startApp").href = url.substring(1);
document.getElementById("startApp").click();
}
</script>
<style>
.main {
color: #333;
text-align: center;
width: auto;
}
</style>
</html>
  • apple-mobile-web-app-capable :仅支持Safari浏览器,以独立进程运行时全屏显示(Safari中输入网址打开链接称之为浏览器内打开,添加到主屏幕后,在主屏幕中点击生成的书签运行称之为独立进程运行)
  • apple-mobile-web-app-status-bar-style :仅支持Safari浏览器,设置状态栏颜色,apple-mobile-web-app-capable为YES时且独立进程运行时生效
  • apple-touch-icon:书签图标
  • title:标签内容为书签的名称
  • window.navigator.standalone:独立进行状态

参考:

Safari Supported Meta Tags

阅读全文 »

反馈请联系hertz@hertzwang.com,谢谢

前言:由于业务要求需要更新应用启动图,拿到新图时分分钟替换完事儿,经测试在iOS 13系统上未生效

问题排查

启动图使用 LaunchScreen.storyboard 的方式,在查阅资料与实践后得出结论:

  • 系统会根据LaunchScreen.stroboard的内容生成屏幕快照(@2x和@3x)
  • 快照存放在Library/SplashBoard/Snapshots
  • 第次运行时都会生成新的快照图片,根据屏幕倍数显示相应的快照图片
  • 在 iOS 13 系统中,更新图片名称、内容,并删除快照图片缓存后,下次启动时启动图才更新

也就是说在 iOS 13 上,更新启动图需要改图片名称、删除快照图片缓存,在下次启动时才生效!!!

解决方案

在 iOS 13 上冷启动时校验缓存图片与当前图片是否一致,若缓存图片不存在或图片不一致则删除快照缓存并更新缓存图片,图片一致时不处理

阅读全文 »

反馈请联系hertz@hertzwang.com,谢谢

问题

ibmtasdk.alibWeChatSDK.a 中都包含 MTASocket.o,从而出现重复的法名_responseErrorKey导致编辑失败
Log:
duplicate symbol ‘_responseErrorKey’ in:
TXUGCVideoUpload/COSSDK/libmtasdk.a(MTASocket.o)
UnifyPay/WeChat/libWeChatSDK.a(MTASocket.o)
ld: 1 duplicate symbol for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

解决方案

方案一:删除 libmtasdk.aMTASocket.o(失败)

步骤:

  1. 查看libmtasdk.a支持的架构类型
    $ lipo -info libmtasdk.a
    信息Architectures in the fat file: libmtasdk.a are: i386 x86_64 arm64 armv7 armv7s,表示该静态库支持i386、x86_64rm64、armv7、armv7s平台
  2. 获取各架构的动态库
    $ lipo -extract_family i386 -o libmtasdk_i386.a libmtasdk.a
    其它架构类型也是,最后得到libmtasdk_i386.a、libmtasdk_x86_64.a、libmtasdk_arm64.a、……
  3. 删除重复的MTASocket.o
    $ ar -d libmtasdk_i386.a MTASocket.o
    其它架构类型也是

    如果报错

     ar: libmtasdk_armv7.a is a fat file (use libtool(1) or lipo(1) and ar(1) on it)
    

    ar: libmtasdk_armv7.a: Inappropriate file type or format
    则需要执行$ lipo libmtasdk_armv7.a -thin armv7 -o libmtasdk_armv7_new.a,然后使用libmtasdk_armv7_new.a继续操作

  4. 合并所有架构类型的静态库
    $ lipo -create -output libmtasdk_xxx.a libmtasdk_i386.a libmtasdk_x86_64.a libmtasdk_arm64.a armv7.a armv7s.a
  5. 使用新的静态库libmtasdk_xxx.a
    工程中删除libmtasdk.a并导入libmtasdk_xxx.a

结束失败了,运行时报错

阅读全文 »

反馈请联系hertz@hertzwang.com,谢谢

通过删除缓存和无用的工具来实现腾空间

应用缓存

  • 企业微信
    ~/Library/Containers/com.tencent.WeWorkMac/Data/Library/Application\ Support/WXWork/Data

  • 微信
    ~/Library/Containers/com.tencent.xinWeChat/Data/Library/Caches

  • QQ:
    ~/Library/Containers/com.tencent.qq/Data/Library/Caches

  • 网易云音乐
    ~/Library/Containers/com.netease.163music/Data/Library/Caches

开发工具

  • ~/Library/Developer/
    • Xcode
      • Archives(Xcode Archive后文件夹,无用时可删除)
      • watchOS DeviceSupport(watchOS 模拟器SDK,非watch开发可删除)
      • iOS DeviceSupport(iOS 模拟器SDK,可将用不着的iOS版本删除)
      • DerivedData(所有用Xcode Build的项目文件,可根据工程删除)
    • CoreSimulator
      • Caches(SimRuntime文件,可删除无用平台,如watch、tv)
      • Devices(Xcode运行时选的模拟器,可在Xcode->Window->Devices and Simulators中删除)

反馈请联系hertz@hertzwang.com,谢谢

业务中需要支持WebP图片,然后在Pod时提示超时,解决思路是先fork一份libwebp项目,然后添加libwebp.podspec文件,最后在Podfile中指定源

Fork项目

  1. 终端执行 pod search libwebp查看仓库地址,或使用Github上找到的https://github.com/webmproject/libwebp

     -> libwebp (1.1.0)
        Library to encode and decode images in WebP format.
        pod 'libwebp', '~> 1.1.0'
        - Homepage: https://developers.google.com/speed/webp/
        - Source:   https://chromium.googlesource.com/webm/libwebp
        - Versions: 1.1.0, 1.1.0-rc2, 1.0.3, 1.0.2, 1.0.1, 1.0.0, 0.6.1, 0.6.0,
        0.5.2, 0.5.1, 0.5.0, 0.4.4, 0.4.3, 0.4.2, 0.4.1 [trunk repo]
        - Subspecs:
          - libwebp/webp (1.1.0)
          - libwebp/demux (1.1.0)
          - libwebp/mux (1.1.0)
    
  2. 新建Git仓库并上传

添加 libwebp.podspec

在Git根目录新建文件libwebp.podspec,格式参考Podspec Syntax Reference,大体如下:

Pod::Spec.new do |s|
  s.name             = 'libwebp'
  s.version          = '1.1.0'
  s.summary          = 'Library to encode and decode images in WebP format.'

  s.description      = <<-DESC
Library to encode and decode images in WebP format.
                       DESC

  s.homepage         = 'https://developers.google.com/speed/webp/'
  s.license          = { :type => 'BSD', :file => 'COPYING' }
  s.author           = { 'Google Inc.' => 'mail@google.com' }
  s.source           = { :git => 'https://example/libwebp.git', :tag => s.version.to_s }
  s.compiler_flags   = '-D_THREAD_SAFE'
  s.requires_arc     = false
  s.platforms        = { :ios => '6.0' }
  s.pod_target_xcconfig = { "USER_HEADER_SEARCH_PATHS": "$(inherited) ${PODS_ROOT}/libwebp/ ${PODS_TARGET_SRCROOT}/" }
  s.preserve_paths   = 'src'

  s.ios.deployment_target = '6.0'

  s.source_files = 'src/webp/decode.h', 'src/webp/encode.h', 'src/webp/types.h', 'src/webp/mux_types.h', 'src/webp/format_constants.h', 'src/utils/*.{h,c}', 'src/dsp/*.{h,c}', 'src/dec/*.{h,c}', 'src/enc/*.{h,c}'
  
end

注意:

  1. libwebp.podspec中的信息源于libwebp.podspec.json文件
  2. s.source中的git为fork后的新地址
  3. 由于使用的是tag,所以需要新建名为s.version对应的tag
  4. s.source_files这块的写法是只用到了webp

指定源

指定Git库及分支,在Podfile文件中添加如下:

1
pod 'libwebp', :git => 'https://example/libwebp.git', :branch => 'master'

其它

GIF vs APNG vs WebP

反馈请联系hertz@hertzwang.com,谢谢

记录WDS

  1. 修改登录口令
  2. 设置无线密码
  3. 开启WDS(信道与桥接的SSID一致)
  4. 关闭DHCP服务器
  5. 修改路由IP(LAN口设置-IP地址)

反馈请联系hertz@hertzwang.com,谢谢

前言:

安装xlrd

执行 pip install xlrd安装

  • 注:提示-bash: pip: command not found,执行sudo easy_install pip 安装pip

执行Python

# -*- coding: utf-8 -*-
import xdrlib ,sys
import xlrd
import os

# 文件名
fileName = 'yapi.xlsx'
# 属性名称列
propertyNameCol = 0
# 属性类型列
propertyTypeCol = 1
# 属性注释列
propertyDescCol = 4

#打开excel文件
def open_excel():
    try:
        data = xlrd.open_workbook(fileName)
        return data
    except Exception,e:
        print str(e)

def print_excel():
    data = open_excel() #打开excel文件
    sheet1 = data.sheet_by_index(0) #选择第1个Sheet
    nrows = sheet1.nrows
    os.system('clear')
    for rownum in range(0, nrows):
        name = sheet1.cell_value(rownum, propertyNameCol)
        type = sheet1.cell_value(rownum, propertyTypeCol)
        desc = sheet1.cell_value(rownum, propertyDescCol)
        nstype = 'NSNumber'
        if type == 'string':
            nstype = 'NSString'
        print ('/// %s' % (desc))
        print ('@property (nonatomic, copy) %s* %s;' % (nstype, name))

    print('')

#主函数
def main():
    print_excel()

if __name__=="__main__":
    main()

反馈请联系hertz@hertzwang.com,谢谢

属性类型

property_getAttributes获取至的结构:数据类型,修饰词...,V_属性名称,如:T@,R,C,N,V_idValue

  • 数据类型,以”T”开始至第一个”,”
    • @ -> id
    • @”XXX” -> XXX,如:@”NSString”、@”NSArray”
    • i -> int
    • d -> double
    • f -> float
  • 修饰词,以第一个”,”开始至最后一个”,”
    • N -> nonatomic
    • R -> reonly
    • C -> copy
    • & -> strongretain
    • W -> weak
  • V_属性名称,以"V_"开始至结尾,"V_"后面的就是属性名称

代码

  • 属性声名

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    @property (nonatomic, copy, readonly, nullable) id idValue;
    @property (nonatomic, copy) NSNumber *numberValue;
    @property (nonatomic, strong) NSString *stringValue;
    @property (nonatomic, copy) NSArray *arrayValue;
    @property (nonatomic, copy) NSDictionary *dictionaryValue;
    @property (nonatomic, assign) int intValue;
    @property (nonatomic, assign) double doubleValue;
    @property (nonatomic, assign) float floatValue;
    @property (nonatomic, assign, readwrite) CGFloat cgfloatValue;
    @property (nonatomic, retain) NSString *retainStringValue;
    @property (nonatomic, weak) NSString *weakStringValue;
    @property (nonatomic, strong) NSString *__weakStringValue;
  • 获取属性列表及属性类型

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    #import <objc/runtime.h>

    ...

    uint count;
    objc_property_t *propertys = class_copyPropertyList(ObjectClass.class, &count);
    @try {
    for (int i = 0; i < count; i++) {
    objc_property_t property = propertys[i];
    NSLog(@"%s -> %s", property_getName(property), property_getAttributes(property));
    }
    } @finally {
    free(propertys);
    }

  • 打印结果

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    idValue -> T@,R,C,N,V_idValue
    numberValue -> T@"NSNumber",C,N,V_numberValue
    stringValue -> T@"NSString",&,N,V_stringValue
    arrayValue -> T@"NSArray",C,N,V_arrayValue
    dictionaryValue -> T@"NSDictionary",C,N,V_dictionaryValue
    intValue -> Ti,N,V_intValue
    doubleValue -> Td,N,V_doubleValue
    floatValue -> Tf,N,V_floatValue
    cgfloatValue -> Td,N,V_cgfloatValue
    retainStringValue -> T@"NSString",&,N,V_retainStringValue
    weakStringValue -> T@"NSString",W,N,V_weakStringValue
    __weakStringValue -> T@"NSString",&,N,V___weakStringValue

反馈请联系hertz@hertzwang.com,谢谢

搭建OTA

前言:我使用阿里的ECS,万网购买的域名,赛门铁克签发的证书,使用Nginx做的反向代理及Web服务

目录

-> xxx.ipa
-> manifest.plist
-> xxx.crt
-> index.html
-> images
    -> 57x57.png
    -> 512x512.png

xxx.ipa

打包略

阅读全文 »