0.*
npm config set registry https://registry.npm.taobao.org --global
npm config set disturl https://npm.taobao.org/dist --global
1.判断系统
#define UMSYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)
调用方法:
UMSYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"8.0") //高于或等于 iOS8.0的系统
2.关于导航控制器下的高度 (以后整理)
iOS 7 : viewDidLoad中 viewDidAppear:中
iOS 8及以后:viewDidLoad中 viewDidAppear:中
3.用逗号分隔一串数字
- (void)formatMoney{ NSInteger moneyNum = ; NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init]; formatter.numberStyle = NSNumberFormatterDecimalStyle; NSString* formatMoney = [formatter stringFromNumber:[NSNumber numberWithInteger:moneyNum]]; NSLog(@"%@",formatMoney); }
4.nsdictionary的排序
// 按等级从小到大排序 NSArray *allKeys = [_dictLevelName allKeys]; allKeys = [allKeys sortedArrayUsingComparator:^NSComparisonResult(id _Nonnull obj1, id _Nonnull obj2) { NSString *str1 = (NSString *)obj1; NSString *str2 = (NSString *)obj2; NSInteger level1 = [str1 integerValue]; NSInteger level2 = [str2 integerValue]; return [@(level1) compare:@(level2)]; // compare:是NSNumber 的函数,不可以比较字符串,需要单独转换. }]; for (NSString *key in allKeys) { NSString *name = [_dictLevelName objectForKey:key]; if (ISSTRING(name)) { [_arrayLevelName addObject:name]; } }
5.NSAssert作用:若程序在此处崩溃,就能在不插入全局断点的情况下,崩在此处,代替全局断点的作用.
NSAssert(view, @"View must not be nil.");崩溃,倒退崩溃到了我的代码
[[PTVConfig instance] showToast:self.superview msg:@"解除屏蔽"];
是在 cell 中调用的,找不到父类 tableview 了,可见尽量少用 superview, 用父类作为代理直接处理.
6.查找最外层的控制器的方法:
UITabBarController *tabBar = (UITabBarController *)[[[[UIApplication sharedApplication] delegate] window] rootViewController];
UINavigationController *navi = tabBar.selectedViewController;
UIViewController *vc = navi.visibleViewController;
7.关于手势
- UITapGestureRecognizer
- UIPinchGestureRecognizer
- UIRotationGestureRecognizer
- UISwipeGestureRecognizer
- UIPanGestureRecognizer
- UILongPressGestureRecognizer
上面的手势对应的操作是:
- Tap(点一下)
- Pinch(二指往內或往外拨动,平时经常用到的缩放)
- Rotation(旋转)
- Swipe(滑动,快速移动)
- Pan (拖移,慢速移动)
- LongPress(长按)
8.运行 gif 图片,可以使用 UIImageView 动画. 代码如下:
- (void)test {
self.imgView.animationImages = [self animationImages]; //获取Gif图片列表
self.imgView.animationDuration = ; //执行一次完整动画所需的时长
self.imgView.animationRepeatCount = ; //动画重复次数
[self.imgView startAnimating];
} - (NSArray *)animationImages
{
NSFileManager *fielM = [NSFileManager defaultManager];
NSString *path = [[NSBundle mainBundle] pathForResource:@"vip_new_comer_tail" ofType:@"bundle"];
NSArray *arrays = [fielM contentsOfDirectoryAtPath:path error:nil]; NSMutableArray *imagesArr = [NSMutableArray array];
for (NSString *name in arrays) {
NSString *imagePath = [path stringByAppendingPathComponent:name];
NSData *data = [NSData dataWithContentsOfFile:imagePath];
UIImage *image = [UIImage imageWithData:data];
if (image) {
[imagesArr addObject:image];
}
}
return imagesArr;
}
9.对于字符串形式保存的用户配置,若将其转换成字典,可以先使用方法将其转换成 NSData 对象,再将该对象装换成 NSDictionary 对象.
NSString *conf = [dict objectForKey:@"conf"];
if (conf) {
NSData * data = [conf dataUsingEncoding:NSUTF8StringEncoding];
if (data) {
NSDictionary *confDict = [NSJSONSerialization JSONObjectWithData:data options: error:nil];
}
}
10.若给父视图添加了手势,则子视图UIControl 的点击事件被触发后,会先执行父视图的手势,后执行按钮的事件.
若想阻碍父视图的按钮事件,安静地执行按钮事件,可以在手势的delegate的代理方法中,查看当前用户点击的视图,来确定是否调用父视图的代理方法.
- (void)viewDidLoad {
[super viewDidLoad];
[self setupUI];
} - (void)setupUI{
UITapGestureRecognizer *recognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onViewTouchDonw:)];
recognizer.delegate = self;
[self.view addGestureRecognizer:recognizer]; [self.btn addTarget:self action:@selector(onBtnClick:) forControlEvents:UIControlEventTouchUpInside];
} -(BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
if([touch.view isKindOfClass:[UIButton class]])
{
NSLog(@"啦啦啦---%@",[touch.view class]); return NO;
}
return YES;
}
11.判断麦克风和相机使用权限并打开的代码,iOS系统要在 plist 中添加信任的字符串,参考iOS 10 开发适配系列之权限Crash问题- 简书.
/// 检查相机和麦克风的访问权限并提示设置
- (BOOL)checkMediaTypeVideoAndAudio{
BOOL bVideoAuthor = [self checkMediaTypeVideo];
BOOL bAudioAuthor = [self checkMediaTypeAudio]; if (bVideoAuthor && bAudioAuthor) {
return YES;
} else {
return NO;
}
} /// 检查相机的访问权限并提示设置
- (BOOL)checkMediaTypeVideo{
__block BOOL bAuthor = NO;
AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
if (authStatus == AVAuthorizationStatusNotDetermined ||
authStatus == AVAuthorizationStatusDenied ){ // 首次访问照像机权限的时候会弹出允许或不允许的对话框,后来访问失败的话,会在以下 block 中传值为 NO 的参数
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
if (!granted) {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:nil message:@"请在\"设置-隐私-相机\"选项中,允许熊猫直播访问你的相机" delegate:self cancelButtonTitle:@"确定" otherButtonTitles:nil];
[alertView show];
} else {
bAuthor = YES;
}
}];
}
return bAuthor;
} /// 检查麦克风的访问权限并提示设置
- (BOOL)checkMediaTypeAudio{
__block BOOL bAuthor = NO;
AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeAudio];
if (authStatus == AVAuthorizationStatusNotDetermined ||
authStatus == AVAuthorizationStatusDenied ) { // 首次访问麦克风权限的时候会弹出允许或不允许的对话框,后来访问失败的话,会在以下 block 中传值为 NO 的参数
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeAudio completionHandler:^(BOOL granted) {
if (!granted) {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:nil message:@"请在\"设置-隐私-麦克风\"选项中,允许熊猫直播访问你的麦克风" delegate:self cancelButtonTitle:@"确定" otherButtonTitles:nil];
[alertView show];
}
}]; }
return bAuthor;
}
12.YYModel不同变量的使用方法
+ (NSDictionary *)modelCustomPropertyMapper {
NSMutableDictionary *chatMappers = [@{@"text" : @"data.text",
@"color" : @"data.color",
@"size" : @"data.size",
@"font" : @"data.font",
} mutableCopy];
NSDictionary *baseMappers = @{@"rid" : @"from.rid",
@"nick" : @"from.nick",
@"level" : @"from.level",
@"fromLevelMin" : @"from.level_min",
@"fromLevelMax" : @"from.level_max",
@"exp" : @"from.exp",
@"roleName" : @"from.role_name",
@"roleVal" : @"from.role_val",
@"xroomId" : @"to",
@"type" : @"type",
};
[chatMappers addEntriesFromDictionary:baseMappers];
return chatMappers;
}
13.YYText 在 cell 中时,获取点击的位置
- (void)onTapChatMsg:(UITapGestureRecognizer *)tap{
CGRect rect = self.chatMsgLabel.textLayout.textBoundingRect;
CGPoint point = [tap locationInView:tap.view];
if (CGRectContainsPoint(rect, point)) {
NSLog(@"被点击了");
}
}
14.选中某个 cell 的常用代码:
/// 某个 cell 是否被选中, 在 cellForItemAtIndexPath 代理方法中调用
- (void)selectedCellIfNeeded:(PXYStickerCollectionViewCell *)cell indexPath:(NSIndexPath *)indexPath
{
if (self.lastSelectIndexPath == nil)
{
return;
}
if(indexPath.item == self.lastSelectIndexPath.item)
{
cell.backgroundColor = [UIColor colorWithRed:0.4 green:0.4 blue:0.4 alpha:0.4];
cell.gradientLayer.hidden = YES;
}
else
{
cell.backgroundColor = [UIColor clearColor];
cell.gradientLayer.hidden = NO;
}
} /// 选中某个 cell, 在 didSelectItemAtIndexPath 代理方法中调用
- (void)selectingIndexPath:(NSIndexPath *)indexPath collectionView:(UICollectionView *)collectionView{ PXYStickerCollectionViewCell *cell = (PXYStickerCollectionViewCell *)[collectionView cellForItemAtIndexPath:indexPath];
cell.backgroundColor = [UIColor colorWithRed:0.4 green:0.4 blue:0.4 alpha:0.4];
cell.gradientLayer.hidden = YES; if (self.lastSelectIndexPath == nil)
{
self.lastSelectIndexPath = indexPath;
return;
}
else if (self.lastSelectIndexPath.item == indexPath.item)
{
return;
} PXYStickerCollectionViewCell *lastCell = (PXYStickerCollectionViewCell *)[collectionView cellForItemAtIndexPath:self.lastSelectIndexPath];
lastCell.backgroundColor = [UIColor clearColor];
lastCell.gradientLayer.hidden = NO;
self.lastSelectIndexPath = indexPath;
}
15.限制输入多少个字符
- (void)textViewDidChange:(UITextView *)textView{
NSString *lang = [[UIApplication sharedApplication]textInputMode].primaryLanguage; // 键盘输入模式
if ([lang isEqualToString:@"zh-Hans"]) { // 简体中文输入,包括简体拼音,健体五笔,简体手写
UITextRange *selectedRange = [textView markedTextRange];
//获取高亮部分
UITextPosition *position = [textView positionFromPosition:selectedRange.start offset:];
// 没有高亮选择的字,则对已输入的文字进行字数统计和限制
if (!position) {
[self checkTextViewText:textView];
}
// 有高亮选择的字符串,则暂不对文字进行统计和限制
else{
[self checkTextViewText:textView];
}
}
// 中文输入法以外的直接对其统计限制即可,不考虑其他语种情况
else{ }
} - (void)textViewDidEndEditing:(UITextView *)textView{
[self checkTextViewText:textView];
} - (void)checkTextViewText:(UITextView *)textView {
if (textView.text.length > kMaxInputWindPlaneEditView) {
textView.text = [textView.text substringToIndex:kMaxInputWindPlaneEditView];
[[PTVConfig instance] showToast:self msg:[NSString stringWithFormat:@"文字长度不能超过%li个字符",(long)kMaxInputWindPlaneEditView]];
}
}
16.把崩溃日志转化为具体的某一行(crash 崩溃)(参考http://www.jianshu.com/p/da186c14db0f)
(/Users/liuzhu/Library/Developer/Xcode/DerivedData/xxx-atouolfjhjicfrgglhmhmicssual/Build/Products 中含有 dsym 文件)
chmod +x symbolicatecrash
export DEVELOPER_DIR="/Applications/XCode.app/Contents/Developer"
./symbolicatecrash .crash PandaTV-ios.app.dSYM > Control_symbol.crash
(PS:Xcode7.3
symbolicatecrash路径
/Applications/Xcode.app/Contents/SharedFrameworks/DVTFoundation.framework/Versions/A/Resources/symbolicatecrash)
17.在分类中添加属性,核心代码如下:
#import <objc/runtime.h>
@property (nonatomic,assign) CGFloat count; -(void)setCount:(CGFloat)count{
objc_setAssociatedObject(self, @selector(count), @(count), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
} -(CGFloat)count{
NSNumber *count = objc_getAssociatedObject(self, @selector(count));
return count.floatValue;
}
18.若 UIScrollView 的尺寸随着其中的图片尺寸在变化,则可以设置UIViewController中的automaticallyAdjustsScrollViewInsets属性来让其不变
- (void)viewDidLoad {
[super viewDidLoad];
[self setAutomaticallyAdjustsScrollViewInsets:NO];
}