IOS开发基础知识--碎片40
1:Masonry快速查看报错小技巧
self.statusLabel = [UILabel new]; [self.contentView addSubview:self.statusLabel]; MASAttachKeys(self.statusLabel); [self.statusLabel mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(self.contentView).offset(15.0f); make.left.equalTo(self.contentView).offset(10.f); make.height.equalTo(10); make.bottom.equalTo(self.contentView); }];
注意:MASAttachKeys会显示出比较明了的错误信息;
2:iOS跳转到系统设置
注意:想要实现应用内跳转到系统设置界面功能,需要先在Targets-Info-URL Types-URL Schemes中添加prefs
跳转到WIFI设置 if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"prefs:root=WIFI"]]) { [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root=WIFI"]]; } 跳转到蓝牙 if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"prefs:root=Bluetooth"]]) { [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root=Bluetooth"]]; } 跳转到通用 if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"prefs:root=General"]]) { [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs:root=General"]]; } 跳转到关于本机 if ([[UIApplication sharedApplication] canOpenURL:[NSURLURLWithString: @"prefs:root=General&path=About"]]) { [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs: root=General&path=About"]]; } 跳转到定位服务 if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"prefs: root=LOCATION_SERVICES"]]) { [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs: root=LOCATION_SERVICES"]]; } 跳转到通知 if ([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:@"prefs: root=NOTIFICATIONS_ID"]]) { [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"prefs: root=NOTIFICATIONS_ID"]]; }
3:UITableView section随着cell滚动
实现UITableView 的下面这个方法, #pragma mark - Scroll - (void)scrollViewDidScroll:(UIScrollView *)scrollView{ CGFloat sectionHeaderHeight = 40; //固定section 随着cell滚动而滚动 if (scrollView.contentOffset.y<=sectionHeaderHeight&&scrollView.contentOffset.y>=0) { scrollView.contentInset = UIEdgeInsetsMake(-scrollView.contentOffset.y, 0, 0, 0); } else if (scrollView.contentOffset.y>=sectionHeaderHeight) { scrollView.contentInset = UIEdgeInsetsMake(-sectionHeaderHeight, 0, 0, 0); } }
4:TableView如何刷新指定的cell 或section
//一个section刷新 NSIndexSet *indexSet=[[NSIndexSet alloc]initWithIndex:2]; [tableview reloadSections:indexSet withRowAnimation:UITableViewRowAnimationAutomatic]; //一个cell刷新 NSIndexPath *indexPath=[NSIndexPath indexPathForRow:3 inSection:0]; [tableView reloadRowsAtIndexPaths:[NSArray arrayWithObjects:indexPath,nil] withRowAnimation:UITableViewRowAnimationNone];
5:TableView另一种实现隔行空白的效果
增加总体条数,然后再求余判断
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ static NSString *CELL_ID2 = @"SOME_STUPID_ID2"; // even rows will be invisible if (indexPath.row % 2 == 1) { UITableViewCell * cell2 = [tableView dequeueReusableCellWithIdentifier:CELL_ID2]; if (cell2 == nil) { cell2 = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CELL_ID2]; [cell2.contentView setAlpha:0]; [cell2 setUserInteractionEnabled:NO]; // prevent selection and other stuff } return cell2; } [ccTableView setBackgroundColor:[UIColor clearColor]]; cardsCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cardsCell"]; if(cell == nil){ NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"cardsCell" owner:self options:nil]; cell = [topLevelObjects objectAtIndex:0]; } // Use indexPath.row/2 instead of indexPath.row for the visible section to get the correct datasource index (number of rows is increased to add the invisible rows) NSString *nmCard = [[self.cards valueForKeyPath:@"cards.name"] objectAtIndex:(indexPath.row/2)]; cell.descCardLabel.text = nmCard; return cell; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ // two times minus one (invisible at even rows => visibleCount == invisibleCount+1) return [[self.cards valueForKeyPath:@"cards"] count] * 2 - 1; } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { if (indexPath.row % 2 == 1) return 40; return 162; }
6:滚动TableView,滚动到指定的位置
- (void)scrollToRowAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UITableViewScrollPosition)scrollPosition animated:(BOOL)animated
typedef enum { UITableViewScrollPositionNone, UITableViewScrollPositionTop, UITableViewScrollPositionMiddle, UITableViewScrollPositionBottom } UITableViewScrollPosition;
7:iOS-检测UI主线程小工具
在iOS开发中需要保证所有UI操作一定是在主线程进行,通过 hook UIView的-setNeedsLayout,-setNeedsDisplay,-setNeedsDisplayInRect三个方法,确保它们都是在主线程执行。
#import "UIView+NBUIKitMainThreadGuard.h" #import <objc/runtime.h> static inline void swizzling_exchangeMethod(Class clazz ,SEL originalSelector, SEL swizzledSelector){ Method originalMethod = class_getInstanceMethod(clazz, originalSelector); Method swizzledMethod = class_getInstanceMethod(clazz, swizzledSelector); BOOL success = class_addMethod(clazz, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod)); if (success) { class_replaceMethod(clazz, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod)); } else { method_exchangeImplementations(originalMethod, swizzledMethod); } } @implementation UIView (NBUIKitMainThreadGuard) +(void)load { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ SEL needsLayoutOriginalSelector = @selector(setNeedsLayout); SEL needsLayoutSwizzleSelector = @selector(guard_setNeedsLayout); swizzling_exchangeMethod(self, needsLayoutOriginalSelector,needsLayoutSwizzleSelector); SEL needsDisplaOriginalSelector = @selector(setNeedsDisplay); SEL needsDisplaSwizzleSelector = @selector(guard_setNeedsDisplay); swizzling_exchangeMethod(self, needsDisplaOriginalSelector,needsDisplaSwizzleSelector); SEL needsDisplayInRectOriginalSelector = @selector(setNeedsDisplayInRect:); SEL needsDisplayInRectSwizzleSelector = @selector(guard_setNeedsDisplayInRect:); swizzling_exchangeMethod(self, needsDisplayInRectOriginalSelector,needsDisplayInRectSwizzleSelector); }); } - (void)guard_setNeedsLayout { [self UIMainThreadCheck]; [self guard_setNeedsLayout]; } - (void)guard_setNeedsDisplay { [self UIMainThreadCheck]; [self guard_setNeedsDisplay]; } - (void)guard_setNeedsDisplayInRect:(CGRect)rect { [self UIMainThreadCheck]; [self guard_setNeedsDisplayInRect:rect]; } - (void)UIMainThreadCheck { NSString *desc = [NSString stringWithFormat:@"%@", self.class]; NSAssert([NSThread isMainThread], desc); } @end