开发实用技巧
1、label展示两行超出...
shell
UILabel *titleLab = [[UILabel alloc] initWithFrame:CGRectMake(0, 100, 200, 40)];
titleLab.numberOfLines = 2;
titleLab.lineBreakMode = NSLineBreakByTruncatingTail;
2、tableView滚动到顶部生效
shell
[self.tableView reloadData];
[self.tableView layoutIfNeeded]; //这句是关键
[self.tableView setContentOffset:CGPointMake(0,0) animated:NO];
3、静音状态下播放音频
TIP
- 静音状态下播放音频需要开启权限
- 使用
AVAudioPlayer
播放, 使用AudioServicesPlaySystemSound
播放无声音
开启静音播放
shell
#pragma mark - app保持后台静音播放声音
- (void)appKeepAVAudioActive {
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback withOptions:AVAudioSessionCategoryOptionAllowBluetooth error:nil];
[[AVAudioSession sharedInstance] setActive:YES error:nil];
}
播放声音
shell
NSString *bundlePath = [[ NSBundle mainBundle] pathForResource:@"bundleName" ofType :@"bundle"];
NSBundle *bundle = [NSBundle bundleWithPath:bundlePath];
NSString *voicePath = [bundle pathForResource:[NSString stringWithFormat:@"mp3/%@",name] ofType:@"mp3"];
NSURL *filePath = [NSURL fileURLWithPath:voicePath isDirectory:NO];
NSError *error;
AVAudioPlayer *audioPlayer = = [[AVAudioPlayer alloc]initWithContentsOfURL:filePath error:&error];
if (error) return;
[audioPlayer prepareToPlay];
//获取系统音量
AVAudioSession *audioSession = [AVAudioSession sharedInstance];
CGFloat volume = audioSession.outputVolume;
audioPlayer.volume = volume;
[audioPlayer play];
退出取消
shell
[[UIApplication sharedApplication] endReceivingRemoteControlEvents];
4、app保持常亮
shell
#pragma mark - app保持常亮
- (void)appKeepLight {
[[UIApplication sharedApplication] setIdleTimerDisabled:YES];
[[UIScreen mainScreen] setBrightness:0.5];
}
shell
#pragma mark - app退出
-(void)appTerminate {
[[UIApplication sharedApplication] setIdleTimerDisabled:NO];
}
5、app保持后台
TIP
setMinimumBackgroundFetchInterval()是iOS中设置App在后台最小获取新数据时间间隔的方法。
shell
#pragma mark - app保持后台
- (void)appKeepBackground {
[[UIApplication sharedApplication] setMinimumBackgroundFetchInterval:UIApplicationBackgroundFetchIntervalMinimum];
}
6、设置屏幕亮度
TIP
参数范围0-1.0
shell
[[UIScreen mainScreen] setBrightness:0.5];
7、极光推送
7.1、极光推送自定义提示音
TIP
系统静音状态下,极光推送声音无法播放声音
1、在项目根目录下新建push_sound.caf
文件
2、在极光发送推送通知时,只需配置sound
字段的值为导入到工程中的音频文件名,这里即就是 push_sound.caf
8、webview白屏检测
https://www.cnblogs.com/qfww/p/13863789.html
shell
typedef NS_ENUM(NSUInteger,webviewLoadingStatus) {
WebViewNormalStatus = 0, //正常
WebViewErrorStatus, //白屏
WebViewPendStatus, //待决
};
// 判断是否白屏
- (void)judgeLoadingStatus:(WKWebview *)webview withBlock:(void (^)(webviewLoadingStatus status))completionBlock{
webviewLoadingStatus __block status = WebViewPendStatus;
if (@available(iOS 11.0, *)) {
if (webview && [webview isKindOfClass:[WKWebView class]]) {
CGFloat statusBarHeight = [[UIApplication sharedApplication] statusBarFrame].size.height; //状态栏高度
CGFloat navigationHeight = webview.viewController.navigationController.navigationBar.frame.size.height; //导航栏高度
WKSnapshotConfiguration *shotConfiguration = [[WKSnapshotConfiguration alloc] init];
shotConfiguration.rect = CGRectMake(0, statusBarHeight + navigationHeight, webview.bounds.size.width, (webview.bounds.size.height - navigationHeight - statusBarHeight)); //仅截图检测导航栏以下部分内容
[webview takeSnapshotWithConfiguration:shotConfiguration completionHandler:^(UIImage * _Nullable snapshotImage, NSError * _Nullable error) {
dispatch_async(dispatch_get_global_queue(0, 0), ^{
if (snapshotImage) {
// 对图片进行缩放
UIImage *scaleImage = [self scaleImage:snapshotImage];
// 白屏检测, 在主线程会卡线程
BOOL isWhiteScreen = [self searchEveryPixel:scaleImage rgb:rgb proportion:proportion];
if (isWhiteScreen) { // 白屏
status = WKWebViewErrorStatus;
}else{
status = WKWebViewNormalStatus;
}
}
dispatch_async(dispatch_get_main_queue(), ^{
//回到主线程,执行UI刷新操作
if (completionBlock) {
completionBlock(status);
}
});
});
}];
}
}
}
// 遍历像素点 白色像素占比大于95%认定为白屏
- (BOOL)searchEveryPixel:(UIImage *)image {
CGImageRef cgImage = [image CGImage];
size_t width = CGImageGetWidth(cgImage);
size_t height = CGImageGetHeight(cgImage);
size_t bytesPerRow = CGImageGetBytesPerRow(cgImage); //每个像素点包含r g b a 四个字节
size_t bitsPerPixel = CGImageGetBitsPerPixel(cgImage);
CGDataProviderRef dataProvider = CGImageGetDataProvider(cgImage);
CFDataRef data = CGDataProviderCopyData(dataProvider);
UInt8 * buffer = (UInt8*)CFDataGetBytePtr(data);
int whiteCount = 0;
int totalCount = 0;
for (int j = 0; j < height; j ++ ) {
for (int i = 0; i < width; i ++) {
UInt8 * pt = buffer + j * bytesPerRow + i * (bitsPerPixel / 8);
UInt8 red = * pt;
UInt8 green = *(pt + 1);
UInt8 blue = *(pt + 2);
// UInt8 alpha = *(pt + 3);
totalCount ++;
if (red == 255 && green == 255 && blue == 255) {
whiteCount ++;
}
}
}
float proportion = (float)whiteCount / totalCount ;
NSLog(@"当前像素点数:%d,白色像素点数:%d , 占比: %f",totalCount , whiteCount , proportion );
if (proportion > 0.95) {
return YES;
}else{
return NO;
}
}
//缩放图片
- (UIImage *)scaleImage: (UIImage *)image {
CGFloat scale = 0.2;
CGSize newsize;
newsize.width = floor(image.size.width * scale);
newsize.height = floor(image.size.height * scale);
if (@available(iOS 10.0, *)) {
UIGraphicsImageRenderer * renderer = [[UIGraphicsImageRenderer alloc] initWithSize:newsize];
return [renderer imageWithActions:^(UIGraphicsImageRendererContext * _Nonnull rendererContext) {
[image drawInRect:CGRectMake(0, 0, newsize.width, newsize.height)];
}];
}else{
return image;
}
}
9、多线程
9.1、异步处理主线程刷新
shell
dispatch_async(dispatch_get_global_queue(0, 0), ^{
//执行耗时的异步操作..
dispatch_async(dispatch_get_main_queue(), ^{
//回到主线程,执行UI刷新操作
});
});
9.2、
10、加载离线包
shell
NSString *basePath = [NSString stringWithFormat: @"%@/%@", [[NSBundle mainBundle] bundlePath], @"2.2.13"];
NSURL *baseUrl = [NSURL fileURLWithPath: basePath isDirectory: YES];
NSString *filePath = [NSString stringWithFormat: @"file://%@/index.html#/page", basePath];
NSURL *fileUrl = [NSURL URLWithString: filePath];
[self.webview loadFileURL: fileUrl allowingReadAccessToURL: baseUrl];