Tips
1. TARGET_IPHONE_SIMULATOR
经常集成的第三方库,有些不支持模拟器,每一次调试代码要么就是一直连接真机,要么就是,把这个库相关的代码屏蔽,其实有更优雅的解决办法:TARGET_IPHONE_SIMULATOR
使用示例如下:
#if TARGET_IPHONE_SIMULATOR
#else
//只支持真机的第三方库
#import <LopeKit/LopeKit.h>
#endif
#if TARGET_IPHONE_SIMULATOR
//模拟器编译代码
@interface BluetoothManager()
<
CBCentralManagerDelegate
>
#else
//非模拟器编译代码
@interface BluetoothManager()
<
NPDSophKeyDelegate,//只支持真机的第三方库代理
CBCentralManagerDelegate
>
#endif
2. 构建版本一直不显示
从iOS10开始,苹果更加注重对用于隐私的保护,app里边如果需要访问用户隐私,必须要做相应隐私权限的描述,所以要在plist文件中添加描述。 下面是几种权限的描述,按需添加:
麦克风权限
:Privacy - Microphone Usage Description 是否允许此App使用你的麦克风?相机权限
: Privacy - Camera Usage Description 是否允许此App使用你的相机?相册权限
: Privacy - Photo Library Usage Description 是否允许此App访问你的媒体资料库?通讯录权限
: Privacy - Contacts Usage Description 是否允许此App访问你的通讯录?蓝牙权限
:Privacy - Bluetooth Peripheral Usage Description 是否允许此App使用蓝牙?语音转文字权限
:Privacy - Speech Recognition Usage Description 是否允许此App使用语音识别?日历权限
:Privacy - Calendars Usage Description 是否允许此App使用日历?定位权限
:Privacy - Location When In Use Usage Description 我们需要通过您的地理位置信息获取您周边的相关数据
3. IDFA
友盟的提供的无 IDFA 版本的 SDK。
使用命令行检查含有 IDFA,但是审核的时间选择 否
,又不影响审核。🤣🤣
➜ copm_staff grep -r advertisingIdentifier .
Binary file ./copm_staff/Business/lib/Share/UMSocial/UMSocialSDK/UMSocialCore.framework/UMSocialCore matches
Binary file ./copm_staff/Expand/UMessage/UMessage_Sdk_1.4.0/libUMessage_Sdk_1.4.0.a matches
Binary file ./copm_staff/Expand/UMessage/UMessage_Sdk_1.5.0a/libUMessage_Sdk_1.5.0a.a matches
Binary file ./UMMobClick.framework/UMMobClick matches
Binary file ./UMMobClick.framework/Versions/A/UMMobClick matches
Binary file ./UMMobClick.framework/Versions/Current/UMMobClick matches
4. 生成好看的代码图片
这个网站:https://carbon.now.sh/ 可以把代码生成一种很好看的格式。
5. 安装破解的文件
“通用”里有时没有“任何来源”这个选项:
显示”任何来源”选项在控制台中执行:
sudo spctl --master-disable
不显示”任何来源”选项(macOS 10.12默认为不显示)在控制台中执行:
sudo spctl --master-enable
6. 近距离感应器
// 打开距离传感器
[UIDevice currentDevice].proximityMonitoringEnabled = YES;
// 通过通知监听有物品靠近还是离开
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(proximityStateDidChange:) name:UIDeviceProximityStateDidChangeNotification object:nil];
- (void)proximityStateDidChange:(NSNotification *)note
{
if ([UIDevice currentDevice].proximityState) {
NSLog(@"有物品靠近");
} else {
NSLog(@"有物品离开");
}
}
7. 使用第三方库上层再来一次封装
使用第三方库上层再来一次封装,不要直接使用第三方库,这样的好处是替换第三方库的成本会低很多。譬如使用 AFNetworking
,MJRefresh
等。如果做了一层封装,以后替换就只需要修改封装的上层代码。
8. source
命令
在编译核心时,常常要反复输入一长串命令,如
make mrproper
make menuconfig
make dep
make clean
make bzImage
.......
这些命令既长,又繁琐。而且有时候容易输错,浪费你的时间和精力。如果把这些命令做成一个文件,让它自动按顺序执行,对于需要多次反复编译核心的用户来说,会很方便。
用source
命令可以办到这一点。它的作用就是把一个文件的内容当成是shell
来执行。
shell
编程中的命令有时和C语言是一样的。&&
表示与,||
表示或。把两个命令用 &&
联接起来,如 make mrproper && make menuconfig
,表示要第一个命令执行成功才能执行第二个命令。对执行顺序有要求的命令能保证一旦有错误发生,下面的命令不会盲目地继续执行。
9. AF 报错 Code=-1016
这个是因为通讯通里面包含的 content-type
包含的不是你支持的几种格式,一般我们用 json 指定响应格式,但是服务端经常返回的通讯头 content-type
值是:text/plain
,AF默认的响应是不支持这种响应的,要么是服务端改,要么是客户端改。。。但一般都客户端改。。。
一般会把 AFJSONResponseSerializer
里面改为
self.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript",@"text/html",@"text/plain", nil];
改了以后,有时候会有 Code=3840
的错误,这个一般是因为服务端返回的字符串带有转义字符导致的,没法解析出json
。
10. Mac OS 如何更改文件的默认打开方式
选中文件 邮件显示编辑菜单,点击显示简介(快捷键: ⌘ + i)。 然后会有一个打开方式的选项,更改后,点击下面的全部更改,以后打开这种文件,就默认使用你设定的App了。
11. 蒲公英、Fir 分发平台 无法直接替换 App Store 版本
今天测试告诉我,扫码安装测试包,不能像之前一样替换了,就搜索了一下,有两种场景,分别是蒲公英平台:
为什么在 iOS 9 中,点击“安装”按钮后,没有任何反应,桌面也没有出现应用图标,但是状态栏上的网络图标在转?
这是由于 iOS 9 中的一个 Bug 造成的。虽然看上去没有反应,其实应用已经在后台开始下载并安装了,状态栏上的网络图标在转就是一个证明。这个时候,只要多等待一会儿就好了,应用安装完成之后会在桌面上显示出来的。
和 fir平台
第五种:设备上已安装了该应用,并且与当前要安装的应用使用的证书不同
解决方法:删除旧的应用,重新安装
无法替换 App Store 版本的这种情景就属于第二种,App Store版本的证书与测试版本的证书不一致导致的。
12. 计算滑动距离
- (void)panGesture:(UIPanGestureRecognizer *)sender {
if (sender.state == UIGestureRecognizerStateBegan) {
startLocation = [sender locationInView:self.view];
}
else if (sender.state == UIGestureRecognizerStateEnded) {
CGPoint stopLocation = [sender locationInView:self.view];
CGFloat dx = stopLocation.x - startLocation.x;
CGFloat dy = stopLocation.y - startLocation.y;
CGFloat distance = sqrt(dx*dx + dy*dy );
NSLog(@"Distance: %f", distance);
}
}
13. show invisibles 显示对齐符
14. 一次删除多个 python 第三方库
之前下了一个 pyobjc的第三方库,但是又没用,就想把它删除,使用 pip list
看了一下,发现它安装了好几十个依赖库,如果一个个删除 pip uninstall
当然也可以,但是有一种更简单的方法。
就是第八条提到的 source
命令。
1.首先找出要卸载的第三方库
因为要卸载的库都是以 pyobjc-
开通的,使用 这个 命令看下要卸载的库有哪些,pip list | grep "pyobjc-*"
pyobjc-core
pyobjc-framework-Accounts
pyobjc-framework-SyncServices
...
...
...
pyobjc-framework-SystemConfiguration
pyobjc-framework-WebKit
2. 把要卸载的库名称保存到一个本地文件中
找到了要卸载的库名称,把它们保存到一个本地文件中,然后在开头统一添加前缀 pip uninstall
,sublime 可以这样操作,先选中全部文本,然后 command + Shift + L
进入多行编辑模式,然后 按 方向键 ←
,就可以多行添加了。
把要执行的命令保存到一个本地文本假设叫做 a.txt。
pip uninstall pyobjc-core
pip uninstall pyobjc-framework-Accounts
pip uninstall pyobjc-framework-AddressBook
pip uninstall pyobjc-framework-AppleScriptKit
pip uninstall pyobjc-framework-AppleScriptObjC
...
...
...
pip uninstall pyobjc-framework-StoreKit
pip uninstall pyobjc-framework-SyncServices
pip uninstall pyobjc-framework-SystemConfiguration
pip uninstall pyobjc-framework-WebKit
3. 使用 source 命令执行
进入 a.txt 所在的目录,执行命令 source a.txt
15. 文字绘制到屏幕上
- (void)drawRect:(CGRect)rect
{
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextSetBlendMode(ctx, kCGBlendModeCopy);
CGContextSetRGBFillColor(ctx, 1.0, 1.0, 1.0, 0.0);
CGContextSetLineWidth(ctx, 10.f);
CGContextSetCharacterSpacing(ctx, 10.f);
CGContextSetTextDrawingMode(ctx, kCGTextFill);
NSString *s = @"哈哈🐲";
[s drawAtPoint:CGPointMake(0, 50) withAttributes:@{NSFontAttributeName :[UIFont systemFontOfSize:40],NSForegroundColorAttributeName:[UIColor clearColor]}];
}
16. epub
转换为 mobi
格式
16.1 下载 KindleGen
去这个地址现在 KindleGen
16.2 设置 shell
别名
可以不设置,但是每次使用这个软件,都有进入
KindleGen
所在的文件夹再操作。
在 .zshrc
文件中输入(我使用的是 iterm 2
,其他终端设置别名可能不一样)
alias kindle='cd /Applications/KindleGen_v2_9;./kindlegen '
alias Kindle='cd /Applications/KindleGen_v2_9;./kindlegen '
/Applications/KindleGen_v2_9
是KindleGen
所在的路径
使用:
kindle your_file_path.epub
会生成 mobi
文件到 epub
文件所在的目录
17. 实用快捷键
系统
Command+Ctrl+d
启用字典翻译,触摸板三指轻点。Option + Esc
朗读选中文本(需自己去开启,路径:系统偏好设置-辅助功能-语音,就能看到一个 按下按键时朗读所选文本 的选项,勾选上就好了,我自己设置成了Option + `)。
Xcode
Command+L
跳转到指定代码行Command + Shift + o
打开指定文件Command + Shift + j
左侧文件目录栏 显示当前编辑的文件。Ctrl + Command + ↑/↓
切换 .h 和 .m 文件Ctrl + a/e/n/b/f/p
移动光标 (MAC 系统通用)Ctrl + Command + e
批量修改变量名
- 在上图中提示代码选项之间的切换 Ctrl + n/p,在mac 系统中通用,切换菜单都可以使用这个快捷键
18. Mac 预览/Preview
启动后就卡死的问题
打开 ~/Library/Containers
目录。
找到 com.apple.preview
相关目录,删掉后,重新打开 预览/Preview
就可以正常使用了。
19. application loader
无法连接到服务器
如果近期出现 “application loader
无法连接到服务器” 的问题,同时你又设置了 chrome
为默认浏览器的,可以把默认浏览器修改为 Safari
试试看能不能解决这个问题。
同时如果你出现 chrome
无法打开 itc 或者任何苹果开发者的网站,请使用 Safari
打开,应该会解决问题。
🍎💊
🍎💊
🍎💊
🍎💊
20. Guideline 2.1 - Information Needed
当审核被拒时,原因是 Information Needed
,这种情况是苹果需要你确认一些信息,如果你确认你的App没有违反邮件里面列出的条款,回复邮件向苹果承诺他们要求的信息就可以了。不用撤下来发新包。血的教训,因为英文比较差,没领会到苹果爸爸的意思,直接耽误了一个星期发版本的时间。
21. mac 修改本地DNS 地址解析
$ cd /private/etc
$ open .
然后找到 hosts
文件,copy出来一份编辑。
譬如添加一行 45.63.1.188 ssy.com
##
# Host Database
#
# localhost is used to configure the loopback interface
# when the system is booting. Do not change this entry.
##
127.0.0.1 localhost
255.255.255.255 broadcasthost
::1 localhost
127.0.0.1 windows10.microdone.cn
127.0.0.1 domain_used
45.63.1.188 ssy.com
以后再访问45.63.1.188
这个 ip 地址,只需要输入 ssy.com
就行了。只在本机生效
22. 获取 启动图 launchImage 图片
+ (UIImage *)getTheLaunchImage
{
CGSize viewSize = [UIScreen mainScreen].bounds.size;
NSString *viewOrientation = nil;
if (([[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationPortraitUpsideDown) || ([[UIApplication sharedApplication] statusBarOrientation] == UIInterfaceOrientationPortrait)) {
viewOrientation = @"Portrait";
} else {
viewOrientation = @"Landscape";
}
NSString *launchImage = nil;
NSArray* imagesDict = [[[NSBundle mainBundle] infoDictionary] valueForKey:@"UILaunchImages"];
for (NSDictionary* dict in imagesDict)
{
CGSize imageSize = CGSizeFromString(dict[@"UILaunchImageSize"]);
if (CGSizeEqualToSize(imageSize, viewSize) && [viewOrientation isEqualToString:dict[@"UILaunchImageOrientation"]])
{
launchImage = dict[@"UILaunchImageName"];
}
}
return [UIImage imageNamed:launchImage];
}
23. Register Multiple Devices
选中 Register Multiple Devices
按照下面的文本格式写就行了,文件名保存为 multiple-device-upload-ios.txt
,其他名称没有试。
Device ID Device Name
XXXX unknown_05
XXXX unknown_06
XXXX unknown_07
XXXX unknown_08
24. 莫名其妙的错误信息
如果出现了下面的错误信息,有茫然没有头绪,除了网上说的哪几种解决方法外,还有一种可能。
就是观察一个对象后,观察者销毁后没有移除观察者模式
。这就是我今天查了半天才查到的一个崩溃问题。
invalid mode 'kCFRunLoopCommonModes' provided to CFRunLoopRunSpecific - break on _CFRunLoopError_RunCalledWithInvalidMode to debug. This message will only appear once per execution.
libc++abi.dylib: terminate_handler unexpectedly threw an exception
25 查找特定名称的文件夹,并拷贝文件夹下的文件到指定目录
查找目录下特定名称的文件夹,并将文件夹下的文件移动到响应名称的文件夹下。
#! /bin/zsh
# 在当前目录下查找名称为 Images 的文件夹
# 读作变量 f
find . -type d -name Images | while read f; do
# 取出上一个文件夹的名称
resFile=`echo $f | awk -F "/" '{print $4}'`
echo $resFile
# 创建相应的文件夹
mkdir -p ./123/$resFile
#拷贝 f 文件夹下的所有文件 到新创建的文件夹
cp $f/* ./123/$resFile/
done
#! /bin/zsh
mypath=`pwd`
echo $mypath
for dic in `ls $mypath/test/`
do
# 读取文件夹名称的前缀 文件夹名称为 9.1 读取 9
resFile=`echo $dic | awk -F "." '{print $1}'`
# 拼接目标路径
p=${mypath}/Projet/Chapter${resFile}/
echo $p
#拷贝文件到目标路径
cp -r $mypath/test/$dic $p
done
26 建立ssh信任关系
本地机器 A(Mac) 远程登录机器 B(Linux),每次都要输入密码,很烦躁,搜索后发现可以建立两个机器之间的信任关系,具体步骤如下:
- A 中 进入
~/.ssh/
- 运行
ssh-keygen
,所有的提示都默认回车即可 - 完成后会多出来一个
id_rsa.pub
的文件。 scp -r id_rsa.pub root@1.2.3.4:/root/.ssh/authorized_keys
root 是 B 机器的账户- 输入 B 机器 root 账户密码。
- 搞定
如果提示
scp: /root/.ssh/authorized_keys: No such file or directory
需要先在远程登录机器 B(Linux),root
目录(root
账户登录后的默认目录)建立一个.ssh
的文件夹,mkdir .ssh
。
再次远程登录 B 后,再也不需要输入密码了。
27 Xcode sort by name
不知道从哪个版本,当你重新组织下代码的目录结构,然后删除添加到原工程中时,源文件的排列结构就像下面一样混乱。
通常我们可以通用右键 sort by name
来重新排列
也可以设置快捷键来快速完成这个常用的操作
网上找到脚本自动设置的方案没有成功。地址如下:How to automatically sort by name in Xcode project
28 UITableViewCell 自适应高度 在 iOS 10.3.x 出现页面错乱
检查如下几项:
- 是否包含多行
UILabel
,如果包含,设置preferredMaxLayoutWidth
属性。 UITableView
设置estimatedRowHeight
,rowHeight = UITableViewAutomaticDimension
;
29 获取 statusBar 高度的宏定义
#define SY_StatusHight \
({\
CGRect rectStatus = [[UIApplication sharedApplication] statusBarFrame];\
rectStatus.size.height;\
})\
30 UIButton remove all target-actions
UIButton remove all target-actions
[someControl removeTarget:nil
action:NULL
forControlEvents:UIControlEventAllEvents];
31 convert NSDictionary to NSString
这个写法太简洁了。
[NSString stringWithFormat:@"my dictionary is %@", aDictionary];
convert NSDictionary to NSString
32 利用正则搜索项目中的中文字符
commend + shift + f
进入搜索页面,选择 Find
-> Regular Expression
,输入 \p{Han}+
可以搜索项目中的中文字符。
33 UITableViewCell
内容改变时,动态修改高度
设置好约束条件后,如果 cell 的内容发生改变了,这个时候需要实时的更新页面高度,做法是:
[weakSelf.parentTableView beginUpdates];
[weakSelf.parentTableView endUpdates];
34 UIViewController
不准确的 self.view.frame
在 UIViewController
的生命周期中,viewDidLoad
和viewWillAppear
、viewDidAppear
中,获取 self.view.frame
的值是不同的。
调用方法 viewDidLoad
中,所有的控件的 frame
都是在当前 storyboard
中状态,所以获取到是数值是不对的。
setFrame
的方法一定要放在 viewDidAppear
里,在 viewDidLoad
里是没有效果的。因为 viewDidLoad
的时候, view
还没有加载完成。
记一次坑。由于我的手机是 X,然后
storyboard
里面我选择的也是 X ,开发中就没发现这个问题。
35 找到页面特定的标签,然后出发相应的事件
var allclasss=document.getElementsByTagName('button');
var allcspanlasss=document.getElementsByClassName('span')
var allcspanlasss=document.getElementById("sp").click();
for(var count = 0; count < allclasss.length; count++){
var button = links[count];
button.click()
}
36 优雅的根据字符串判断代码执行
一般来说 OC 对字符串没有很好的办法,大多数会这样写。
NSString *str;
if ([str isEqualToString:@""]) {
code
}else if (str isEqualToString:@"")
{
code
}
......
由于现在做的一个项目有大量的这种判断,就搜了一下有没有更优雅的写法,找到了下面的这种写法,感觉好了很多。
NSDictionary *d = @{
@"Diamonds":
^{
YX_after_run(3, {
HUDError(@"测试测试测试", nil);
})
},
@"Hearts":
^{
},
@"Clubs":
^{
},
@"Spades":
^{
}
};
typedef void (^CaseBlock)(void);
//匹配 执行
((CaseBlock)d[@"Diamonds"])();
// default
CaseBlock c = d[lookup];
if (c) c(); else { NSLog(@"Joker"); }
37 加载 HTML 文件时,<img>
标签不显示的问题
有时候我们加载 HTMl
的时候,并不是加载链接地址,而是服务端直接返回了 HTML
字符串给你[黑人问号.jpg],咱也搞不懂为什么不直接返回一个链接地址,脱裤子放屁多次一举?不管为什么这样,反正已经是这个情况了,然后就老老实实的加载字符串:
[self.webView loadHTMLString:htmlString baseURL:nil];
然后有一个问题,<img>
标签的网络图片不显示。找了半天解决方案,绕了一些弯路,最终解决方法如下,在 info.plist
文件加入这个选项就行了。
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoadsInWebContent</key>
<true/>
</dict>
ps 原来只是因为这个链接是 HTTP 链接!!!!!
tableHeaderView 为 xib 时,如何设置 frame
如果 xib 生成的 view 不在外面包裹一层的话,加载出来的头视图会莫名其妙被拉大!!
let headView = UITableViewHeaderFooterView.init(frame: CGRect.init(x: 0, y: 0, width: SCREEN_WIDTH, height: 180))
if let xibHeadView = xibHeadView {
headView.addSubview(xibHeadView)
xibHeadView.snp.makeConstraints({$0.edges.equalToSuperview()})
}
tableView.tableHeaderView = headView