xcode中,全局去掉项目warning的开头在Builder Setttings->Inhibit All Warnings(抵制所有的警告).当把它设置为Yes时,编译项目就不会出现warning警告了. 因为部分引入的第三方的项目 去掉警告
清理icon 角标 对于ios11 没有去测试
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
刷新本地和服务器的图标 (不在appIcon上显示推送数量,但是在系统通知栏保留推送通知的方法)
@param noti <#noti description#>
*/
- (void )refreshPushBageValue:(NSNotification *)noti{
NSNumber *value = [noti object];
if (kiOS11Later){
iOS 11后,直接设置badgeNumber = -1就生效了
*/
[UIApplication sharedApplication].applicationIconBadgeNumber = value.integerValue;
[JPUSHService setBadge:value.integerValue];
}else {
UILocalNotification *clearEpisodeNotification = [[UILocalNotification alloc] init];
clearEpisodeNotification.fireDate = [NSDate dateWithTimeIntervalSinceNow:(0.3 )];
clearEpisodeNotification.timeZone = [NSTimeZone defaultTimeZone];
clearEpisodeNotification.alertTitle = @"清理icon" ;
clearEpisodeNotification.applicationIconBadgeNumber = value.integerValue;
[[UIApplication sharedApplication] scheduleLocalNotification:clearEpisodeNotification];
}
}
终端代理(临时方案)
1
2
3
在终端中执行以下代码, 1 为http 代理, 2 为全部代理 . ;电脑开启代理软件
export http_proxy=http:
export all_proxy=socks5:
通过宏定义判断是否引入的是framework,反之则使用双引号,实用!
1
2
3
4
5
6
7
8
9
10
#if __has_include(<xxx/xxx.h> )
#import <xxx/xxx.h>
#else
#import "xxx.h"
#endif
#if __has_include(<GPUImage/GPUImageFramework.h> )
#import <GPUImage/GPUImageFramework.h>
#else
#import "GPUImage.h"
swift 打印内存地址
Unmanaged.passRetained(self as AnyObject)//这个引用计数会+1 Unmanaged.passUnretained(self as AnyObject) // 这个引用计数+0
如下输出 Unmanaged(_value: )
部分服务端更改, 验证了cookie app 中没有cookie 清除 造成服务端返回400 和413, 然后加入cookie 清理
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
URLCache.shared .removeAllCachedResponses ()
let cookies = HTTPCookieStorage.shared .cookies
if cookies != nil && cookies!.count>0 {
for cookie in cookies!{
HTTPCookieStorage.shared .deleteCookie (cookie)
}
}
if #available(iOS 9.0 , *) {
let dataStore = WKWebsiteDataStore.default()
dataStore.fetchDataRecords(ofTypes: WKWebsiteDataStore.allWebsiteDataTypes(), completionHandler: { (records) in
for record in records{
if record.displayName .contains ("sina.com" ){
WKWebsiteDataStore.default().removeData(ofTypes: record.dataTypes , for : [record], completionHandler: {
print("清除成功\(record)" )
})
}
}
})
} else {
let libraryPath = NSSearchPathForDirectoriesInDomains(FileManager.SearchPathDirectory .libraryDirectory , FileManager.SearchPathDomainMask .userDomainMask , true).first
let cookiesPath = libraryPath! + "/Cookies"
try!FileManager.default .removeItem (atPath: cookiesPath)
}
1 宏 1.1 has_include 用于判断是否包含某些头文件 例如: `#if has_include()`
1.2 NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_END 两者搭配使用,在这两个宏之间的所有函数变量都是不可空。如果在这两个宏之间,想要可空的函数变量,需要单独设置 nullable关键字。
1.3 UNAVAILABLE_ATTRIBUTE 不可用。在方法或者属性 加上这个宏之后。将变成不可用。
1.4 UI_APPEARANCE_SELECTOR 加到属性后面,所有该属性的实例都统一设置。
IPv6 问题: 1 使用域名 2 手动转换 假设访问http://67.218.154.33 转换为ipv6 形式 : http://[::ffff:67.218.154.33 ]
注 找了一个解释:https://www.jianshu.com/p/1312e98cd35b
—- 获取类名— oc
1
2
3
4
NSString *selfClassName = NSStringFromClass ([self class ]);
selfClassName = [selfClassName componentsSeparatedByString:@"." ].lastObject;
swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
print ("class: \(object_getClassName(self ) )" )
print ("class: \(NSStringFromClass(self .dynamicType ) )" )
print ("class: \(NSStringFromClass(self .dynamicType ) .componentsSeparatedByString(" .").last!)" )
print ("class: \(self ) " )
print ("class: \(self .description) " )
print ("class: \(self .dynamicType ) " )
Swizzle touchesBegan:withEvent:事故
得实现override touches 方法原因见地址
ios 设备目录获取
1
2
3
4
5
6
7
8
9
10
NSString *homeDir = NSHomeDirectory ();
NSString *docDir = [NSSearchPathForDirectoriesInDomains (NSDocumentDirectory , NSUserDomainMask , YES ) firstObject];
NSString *libDir = [NSSearchPathForDirectoriesInDomains (NSLibraryDirectory , NSUserDomainMask , YES ) lastObject];
NSString *cachesDir = [NSSearchPathForDirectoriesInDomains (NSCachesDirectory , NSUserDomainMask , YES ) firstObject];
NSString *tmpDir = NSTemporaryDirectory ();
程序目录
1
2
3
NSLog (@"%@" ,[[NSBundle mainBundle] bundlePath]);
NSString *imagePath = [[NSBundle mainBundle] pathForResource:@"apple" ofType:@"png" ];
UIImage *appleImage = [[UIImage alloc] initWithContentsOfFile:imagePath];
libstdc++适配Xcode10与iOS12
原因是苹果在XCode10和iOS12中移除了libstdc++这个库,由libc++这个库取而代之,苹果的解释是libstdc++已经标记为废弃有5年了,建议大家使用经过了llvm优化过并且全面支持C++11的libc++库。
beta 版本的xcode 10 拷贝下xcode9 的文件(注 模拟器 还是崩溃)
1
2
3
cp /Applications/ Xcode.app/Contents/ Developer/Platforms/i PhoneOS.platform/Developer/ SDKs/iPhoneOS.sdk/u sr/lib/ libstdc++.* /Applications/ Xcode-beta.app/Contents/ Developer/Platforms/i PhoneOS.platform/Developer/ SDKs/iPhoneOS.sdk/u sr/lib/
cp /Applications/ Xcode.app/Contents/ Developer/Platforms/i PhoneSimulator.platform/Developer/ SDKs/iPhoneSimulator.sdk/u sr/lib/ libstdc++.* /Applications/ Xcode-beta.app/Contents/ Developer/Platforms/i PhoneSimulator.platform/Developer/ SDKs/iPhoneSimulator.sdk/u sr/lib/
根本解决办法:
如果你自己的业务模块使用了libstdc++,那么就把模块代码重新调整为依赖libc++,然后重新检查是否存在问题,重新编译 如果你引用的三方库使用了libstdc++,那么向三方库寻求支持,进行升级
查看应用初始化时间 在Xcode中,可以通过设置环境变量来查看App的启动时间,DYLD_PRINT_STATISTICS和DYLD_PRINT_STATISTICS_DETAILS。(这个是更详细的) 如图设置:控制台会输出时间
一个App在执行main函数前包括app delegate的系列方法如applicationWillFinishLaunching时,会做许多系统级别的准备.而在iOS10之前,开发者很难清楚自己App为何启动加载慢.而通过在工程的scheme中添加环境变量DYLD_PRINT_STATISTICS,设置Value为1,App启动加载时就会有启动过程的日志输出. 现在(iOS 10之后)Apple对DYLD_PRINT_STATISTICS的日志输出结果进行了简化,使得更容易让开发者理解.
iOS开发之使用P3图片导致崩溃的解决方法
最近app刚上架,突然收到大面积投诉….一看bugly,9.0-9.3的机器无一幸免,由于项目里有些图标是我直接从阿里图库下载的,问了UI P3,16进制的图片是什么他也说不清,索性让他重新做图了,这个问题只要图片是UI做图基本就可避免
1.打包成ipa
2.把ipa的后缀改成zip,解压缩(这时候会看到一个Payload文件夹)
3.打开终端 输入 cd
4.把 Payload 拖动到终端里(这里的拖动只是为了获取这个文件在电脑上的地址), 回车
5.在终端输入 find . -name ‘Assets.car’ 回车(会输出找到的位置)
6.在终端输入 sudo xcrun –sdk iphoneos assetutil –info ./Assets.car > /tmp/Assets.json 回车 (car 地址可以根据上面找到的位置填入)
7.在终端输入 open /tmp/Assets.json 回车
8.这时候会打开一个text 搜索 DisplayGamut 看看后面是不是P3 如果搜索到的是p3 图片格式还是不对,如果是空或者搜索到显示的不是P3,那图片就对了,根据Name去查找项目里的这张图片吧,然后将其替换.
转自点击
UIView 设置单边圆角
1
2
3
4
5
6
7
8
9
10
11
private func setMaskLayer () {
let corner = self .height/2
let maskPath = UIBezierPath (roundedRect: self .bounds, byRoundingCorners: [UIRectCorner .bottomLeft,UIRectCorner .topLeft], cornerRadii: CGSize .init (width: corner, height: corner));
let maskLayer = CAShapeLayer .init ()
maskLayer.frame = self .bounds
maskLayer.path = maskPath.cgPath
self .layer.mask = maskLayer;
}
jsonp 转json 正则
str.match(“.?({. }).*”)返回数组第一个
记录一个逗号分隔用法
1
2
3
4
5
6
7
// 多值的设置,使用逗号分隔
// 注意:if let 语句中不能使用&& || 条件
// if let 中只要有任何一个条件为nil,就跳出循环
if let name = oName, age = oAge {
print("Hi~" + name + "年龄:" + String(age))
}
IOS脚本打包 IPA(.APP转.IPA)
将要转化的.app文件放到 convertToIpa.sh 同目录之中
运行 convertToIpa.sh 脚本
打开 Terminal,cd 到 convertToIpa.sh 的目录,执行
./convertToIpa.sh appName(.app 的名字)
如果提示 permission denied,则用 chmod 777 distribute.sh 命令赋予权限后,再执行一次。
等脚本之行结束后,会在当前文件夹下生成 appName 文件夹,里面的 appName.ipa 就是我们最终想要的包。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#!/bin/bash
mkdir $1
mkdir $1 /Payload
cp -r $1 .app $1 /Payload/$1 .app
cp Icon.png $1 /iTunesArtwork
cd $1
zip -r $1 .ipa Payload iTunesArtwork
exit 0
xcode 编译线程数
1.获取当前内核数: $ sysctl -n hw.ncpu 2.设置编译线程数: $ defaults write com.apple.dt.Xcode IDEBuildOperationMaxNumberOfConcurrentCompileTasks 8 3.获取编译线程数: $ defaults read com.apple.dt.Xcode IDEBuildOperationMaxNumberOfConcurrentCompileTasks 4.显示编译时长:
iOS12.1 使用 UINavigationController + UITabBarController( UITabBar 磨砂),设置hidesBottomBarWhenPushed后,在 pop 后,会引起TabBar布局异常
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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
@interface CYLTabBar : UITabBar
@end
#import "CYLTabBar.h"
* 用 block 重写某个 class 的指定方法
* @param targetClass 要重写的 class
* @param targetSelector 要重写的 class 里的实例方法,注意如果该方法不存在于 targetClass 里,则什么都不做
* @param implementationBlock 该 block 必须返回一个 block,返回的 block 将被当成 targetSelector 的新实现,所以要在内部自己处理对 super 的调用,以及对当前调用方法的 self 的 class 的保护判断(因为如果 targetClass 的 targetSelector 是继承自父类的,targetClass 内部并没有重写这个方法,则我们这个函数最终重写的其实是父类的 targetSelector,所以会产生预期之外的 class 的影响,例如 targetClass 传进来 UIButton.class,则最终可能会影响到 UIView.class),implementationBlock 的参数里第一个为你要修改的 class,也即等同于 targetClass,第二个参数为你要修改的 selector,也即等同于 targetSelector,第三个参数是 targetSelector 原本的实现,由于 IMP 可以直接当成 C 函数调用,所以可利用它来实现“调用 super”的效果,但由于 targetSelector 的参数个数、参数类型、返回值类型,都会影响 IMP 的调用写法,所以这个调用只能由业务自己写。
*/
CG_INLINE BOOL
OverrideImplementation(Class targetClass, SEL targetSelector, id (^implementationBlock)(Class originClass, SEL originCMD, IMP originIMP)) {
Method originMethod = class_getInstanceMethod(targetClass, targetSelector);
if (!originMethod) {
return NO ;
}
IMP originIMP = method_getImplementation(originMethod);
method_setImplementation(originMethod, imp_implementationWithBlock(implementationBlock(targetClass, targetSelector, originIMP)));
return YES ;
}
@implementation CYLTabBar
+ (void )load {
出现这个现象的直接原因是 tabBar 内的按钮 UITabBarButton 被设置了错误的 frame,frame.size 变为 (0, 0) 导致的。如果12.1正式版Apple修复了这个bug可以移除调这段代码(来源于QMUIKit的处理方式)*/
static dispatch_once_t onceToken;
dispatch_once (&onceToken, ^{
if (@available(iOS 12.1 , *)) {
OverrideImplementation(NSClassFromString (@"UITabBarButton" ), @selector (setFrame:), ^id (__unsafe_unretained Class originClass, SEL originCMD, IMP originIMP) {
return ^(UIView *selfObject, CGRect firstArgv) {
if ([selfObject isKindOfClass:originClass]) {
if (!CGRectIsEmpty (selfObject.frame) && CGRectIsEmpty (firstArgv)) {
return ;
}
}
void (*originSelectorIMP)(id , SEL, CGRect );
originSelectorIMP = (void (*)(id , SEL, CGRect ))originIMP;
originSelectorIMP(selfObject, originCMD, firstArgv);
};
});
}
});
}
@end
来源 https://github.com/ChenYilong/iOS12AdaptationTips/issues/3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
pod 'AFNetworking'
pod 'AFNetworking' , '~>0'
pod 'AFNetworking' , '~> 0.1.2'
pod 'AFNetworking' , '~>0.1'
pod 'AFNetworking' , '2.0'
pod 'AFNetworking' , '= 2.0'
pod 'AFNetworking' , '> 2.0'
pod 'AFNetworking' , '>= 2.0'
pod 'AFNetworking' , '< 2.0'
pod 'AFNetworking' , '<= 2.0'
pod 'AFNetworking' , :git => 'http://gitlab.xxxx.com/AFNetworking.git' , :branch => 'R20161010'
pod 'AFNetworking' , :path => '../AFNetworking'
1
2
3
4
// // 排序
// NSSortDescriptor *isDefault = [NSSortDescriptor sortDescriptorWithKey:@"isDefault" ascending:NO];
// NSSortDescriptor *isUse = [NSSortDescriptor sortDescriptorWithKey:@"isOnlyUse" ascending:NO];
// [self.dataArray sortUsingDescriptors:@[isDefault,isUse]];
系统装 carthage 造成的终端编译ipa找不到编辑器
1
sudo xcode-select --switch /Applications/ Xcode.app/Contents/ Developer/
——node link— 失败问题
Could not symlink share/doc/node/gdbinit Target /usr/local/share/doc/node/gdbinit already exists. You may want to remove it: rm ‘/usr/local/share/doc/node/gdbinit’
解决 1 sudo chown -R $USER /usr/local 2 brew link –overwrite node
xcode 打包多taget 版本号自动同步 添加 Shell 脚本; 在Xcode Build Phases -> 添加 Run Script; 注: 会影响打包, 直接自动打包shell 脚步直接处理, 方法同样
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
if [ $CONFIGURATION == Release ]; then
echo "Bumping build number..."
plist=${INFOPLIST_FILE}
buildnum=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "${plist} " )
if [[ "${buildnum} " == "" ]]; then
echo "No build number in $plist "
exit 2
fi
echo "Bumped build number to $buildnum "
buildnum=$(expr $buildnum + 1)
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildnum " "${INFOPLIST_FILE} "
echo "Update build number to Current Project Version"
agvtool new-version -all $buildnum
echo "Keep Extension Target build version and number as same as app"
buildver=$(/usr/libexec/PlistBuddy -c "Print CFBundleShortVersionString" "${plist} " )
/usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString $buildver " "$SRCROOT /$ZBiOSNotificationService /Info.plist"
/usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString $buildver " "$SRCROOT /$ZBiOSNotificationService /Info.plist"
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildnum " "$SRCROOT /$ZBiOSNotificationService /Info.plist"
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $buildnum " "$SRCROOT /$ZBiOSNotificationService /Info.plist"
else
echo $CONFIGURATION "build - Not bumping build number."
fi
时间的一个处理
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
let gregorian = Calendar(
identifier: .gregorian)
let dt = Date()
let comp = gregorian.dateComponents(
[.year , .month , .day , .hour , .minute , .second , .weekday],
from: dt)
var comp2 = DateComponents()
comp2.year = comp.year
comp2.month = comp.month
comp2.day = comp.day
comp2.hour = comp.hour
comp2.minute = 34
let date = gregorian.date(from: comp2)
if let date = date {
print("获取的日期为:\(date)" )
}
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
NSCalendar *gregorian = [[NSCalendar alloc]
initWithCalendarIdentifier:NSCalendarIdentifierGregorian ];
NSDate * dt = [NSDate date];
unsigned unitFlags = NSCalendarUnitYear |
NSCalendarUnitMonth | NSCalendarUnitDay |
NSCalendarUnitHour | NSCalendarUnitMinute |
NSCalendarUnitSecond | NSCalendarUnitWeekday ;
NSDateComponents * comp = [gregorian components: unitFlags
fromDate:dt];
NSLog (@"现在是%ld年" , comp.year);
NSLog (@"现在是%ld月 " , comp.month);
NSLog (@"现在是%ld日" , comp.day);
NSLog (@"现在是%ld时" , comp.hour);
NSLog (@"现在是%ld分" , comp.minute);
NSLog (@"现在是%ld秒" , comp.second);
NSLog (@"现在是星期%ld" , comp.weekday);
NSDateComponents * comp2 = [[NSDateComponents alloc]
init];
comp2.year = 2013 ;
comp2.month = 4 ;
comp2.day = 5 ;
comp2.hour = 18 ;
comp2.minute = 34 ;
NSDate *date = [gregorian dateFromComponents:comp2];
NSLog (@"获取的日期为:%@" , date);
pod 组件,使用时, 头文件报 重复导入,使用检查头文件的方式导入
1
2
3
4
5
#if __has_include(<ShareSDK/ShareSDK.h> )
#import <ShareSDK/ShareSDK.h>
#else
#endif
格式化数据
1
2
3
4
5
6
7
8
NSLog (@"%02ld ",2 );
NSLog (@"%0 .2f ",0 .2656 );
NSLog (@"%0 .2f ",0 .2646 );
注意的是%0.2f 是会对数字进行一个四舍五入
14:57 :28.506 App [4010:98217] 02
2016-06-20 14:57 :28.507 App [4010:98217] 0.27
2016-06-20 14:57 :28.507 App [4010:98217] 0.26