# LXR_BaiSi **Repository Path**: ios67/LXR_BaiSi ## Basic Information - **Project Name**: LXR_BaiSi - **Description**: 仿写百思不得姐客户端 - **Primary Language**: Objective-C - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 14 - **Forks**: 3 - **Created**: 2016-10-17 - **Last Updated**: 2022-10-25 ## Categories & Tags **Categories**: mobile-app **Tags**: None ## README #LXR_BaiSi # BSBDJ 百思不得姐相关知识点 ####解决图片渲染问题 - 方法1.解决图片渲染问题 ```objc UIImage* image = [UIImage imageNamed:@"tabBar_essence_click_icon"]; //设置image模式是原始效果,不要渲染 image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; vc1.tabBarItem.selectedImage = image; ``` - 方法2.解决图片渲染问题 ![解决图片渲染问题](http://git.oschina.net/uploads/images/2016/1017/210258_8718b2bf_1026001.png "在这里输入图片标题") ####修改项目名称 ![修改项目名称](http://git.oschina.net/uploads/images/2016/1017/210342_926a4f1d_1026001.png "在这里输入图片标题") ####通过appearance同一设置所有UITabBarItem的文字属性 ```objc NSMutableDictionary* attrs = [NSMutableDictionary new]; //文字 字体大小 attrs[NSFontAttributeName] = [UIFont systemFontOfSize:12]; //文字 Foreground前景颜色 attrs[NSForegroundColorAttributeName] = [UIColor grayColor]; NSMutableDictionary* selectesAttrs = [NSMutableDictionary new]; selectesAttrs[NSFontAttributeName] = [UIFont systemFontOfSize:12]; selectesAttrs[NSForegroundColorAttributeName] = [UIColor darkGrayColor]; UITabBarItem* item = [UITabBarItem appearance]; [item setTitleTextAttributes:attrs forState:UIControlStateNormal]; [item setTitleTextAttributes:selectesAttrs forState:UIControlStateSelected]; ``` ![1](http://git.oschina.net/uploads/images/2016/1017/210451_4078bca2_1026001.png "在这里输入图片标题") ####设置cell默认选中第一行 ```objc //设置左边列表cell默认选中首行 [self.LeftTableView selectRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] animated:NO scrollPosition:UITableViewScrollPositionTop]; ``` ####李明杰第三方转模型框架使用 ```objc //通过数组responseObject[@"list"]进行转模型LXRRecommendLeftModel到LeftDataArray数组里 self.LeftDataArray = [LXRRecommendLeftModel mj_objectArrayWithKeyValuesArray:responseObject[@"list"]]; ``` ####重写方法 ```objc #pragma mark - 重写选中方法,系统默认选中将所有子控件显示为高亮状态---------重点 //selected会打印出选中第几组第几行信息 /**可以在这个方法中监听cell的选中和取消选中*/ -(void)setSelected:(BOOL)selected animated:(BOOL)animated{ [super setSelected:selected animated:animated]; self.SelctedView.hidden = !selected; //设置文字颜色,如果是选中状态是红色,如果不是就是正常颜色 self.textLabel.textColor = selected ? LXR_RGB_Color(219, 21, 26) : LXR_RGB_Color(78, 78,78); //设置正常状态下文本颜色 //self.textLabel.textColor = LXR_RGB_Color(78, 78, 78); //默认选中cell时textLable就会变成高亮颜色 //self.textLabel.highlightedTextColor = LXR_RGB_Color(219, 21, 26); } ``` ####pch文件设置 ```objc //调试 #ifdef DEBUG #define LXRLog(...) NSLog(__VA_ARGS__) #else #define LXRLog(...) #endif //打印执行方法 #define LXRLogFunc LXRLog(@"%s",__func__) //设置颜色 #define LXR_RGB_Color(r,g,b) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:1.0] ``` ####自定义NavigationController 重写方法 ```objc //可以在这个方法中拦截所有PUSH进来的控制器 -(void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated{ //统一设置控制器返回按钮的文字 if (self.childViewControllers.count > 0) { //如果push进来的不是第一个控制器 UIButton* button = [UIButton buttonWithType:UIButtonTypeCustom]; //设置文字 颜色 [button setTitle:@"返回" forState:UIControlStateNormal]; [button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal]; [button setTitleColor:[UIColor redColor] forState:UIControlStateHighlighted]; //设置按钮图片 [button setImage:[UIImage imageNamed:@"navigationButtonReturn"] forState:UIControlStateNormal]; [button setImage:[UIImage imageNamed:@"navigationButtonReturnClick"] forState:UIControlStateHighlighted]; //设置按钮大小,一定要设置大小,不然显示不出来 button.Size = CGSizeMake(60, 30); //让按钮内容的所有内容左对齐 //button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft; //根据大小填充 建议使用 [button sizeToFit]; //设置按钮贴着屏幕左边 ---------重点!!! button.contentEdgeInsets = UIEdgeInsetsMake(0, -20, 0, 0); //添加点击事件 返回界面功能 [button addTarget:self action:@selector(Back) forControlEvents:UIControlEventTouchUpInside]; viewController.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc]initWithCustomView:button]; //当push下一界面的时候,隐藏tabBar viewController.hidesBottomBarWhenPushed = YES; } //这句super的push要放在后面,让viewController可以覆盖上面设置的leftBarButtonItem [super pushViewController:viewController animated:animated]; } ``` ####重写initialize方法 作用 ```objc #pragma mark - 设置主题 这个方法只调用一次 +(void)initialize{ //通过appearance同一设置所有UITabBarItem的文字属性 NSMutableDictionary* attrs = [NSMutableDictionary new]; //文字 字体大小 attrs[NSFontAttributeName] = [UIFont systemFontOfSize:12]; //文字 Foreground前景颜色 attrs[NSForegroundColorAttributeName] = [UIColor grayColor]; NSMutableDictionary* selectesAttrs = [NSMutableDictionary new]; selectesAttrs[NSFontAttributeName] = attrs[NSFontAttributeName]; selectesAttrs[NSForegroundColorAttributeName] = [UIColor darkGrayColor]; UITabBarItem* item = [UITabBarItem appearance]; [item setTitleTextAttributes:attrs forState:UIControlStateNormal]; [item setTitleTextAttributes:selectesAttrs forState:UIControlStateSelected]; } ``` ####重写setFrame和setBounds方法作用 ```objc /** * 需要重写setFrame和setBounds方法作用: * 重新布局cell,拦截设置方法后进行重新赋值,别人无法改变 */ -(void)setFrame:(CGRect)frame{ //cell效果,x往右移动10,宽度减少2倍的x,高度减少1 frame.origin.x = 10; frame.size.width -= 2*frame.origin.x; frame.size.height -= 1; [super setFrame:frame]; } -(void)setBounds:(CGRect)bounds{ //cell效果,x往右移动10,宽度减少2倍的x,高度减少1 bounds.origin.x = 10; bounds.size.width -= 2*bounds.origin.x; bounds.size.height -= 1; [super setBounds:bounds]; } ``` ####修改UITextField的placeholder颜色 - 使用属性 ```objc @property(nonatomic,copy) NSAttributedString *attributedPlaceholder; // 文字属性 NSMutableDictionary *attrs = [NSMutableDictionary dictionary]; attrs[NSForegroundColorAttributeName] = [UIColor grayColor]; // NSAttributedString : 带有属性的文字(富文本技术) NSAttributedString *placeholder = [[NSAttributedString alloc] initWithString:@"手机号" attributes:attrs]; self.phoneField.attributedPlaceholder = placeholder; NSMutableAttributedString *placehoder = [[NSMutableAttributedString alloc] initWithString:@"手机号"]; [placehoder setAttributes:@{NSForegroundColorAttributeName : [UIColor whiteColor]} range:NSMakeRange(0, 1)]; [placehoder setAttributes:@{ NSForegroundColorAttributeName : [UIColor yellowColor], NSFontAttributeName : [UIFont systemFontOfSize:30] } range:NSMakeRange(1, 1)]; [placehoder setAttributes:@{NSForegroundColorAttributeName : [UIColor redColor]} range:NSMakeRange(2, 1)]; self.phoneField.attributedPlaceholder = placehoder; ``` - 重写方法 ```objc - (void)drawPlaceholderInRect:(CGRect)rect { [self.placeholder drawInRect:CGRectMake(0, 10, rect.size.width, 25) withAttributes:@{ NSForegroundColorAttributeName : [UIColor grayColor], NSFontAttributeName : self.font}]; } ``` - 使用KVC ```objc [self setValue:[UIColor grayColor] forKeyPath:@"_placeholderLabel.textColor"]; ``` ## 运行时(Runtime) - 苹果官方一套C语言库 - 能做很多底层操作(比如访问隐藏的一些成员变量\成员方法....) - 访问成员变量举例 ```objc unsigned int count = 0; // 拷贝出所有的成员变量列表 Ivar *ivars = class_copyIvarList([UITextField class], &count); for (int i = 0; i ``` * 这时候需要尝试更新gem源或者pod * `sudo gem update --system` * `sudo gem install cocoapods` * `sudo gem install cocospods-trunk` ##### 创建podspec文件 * 接下来需要在项目根路径创建一个podspec文件来描述你的项目信息 * `pod spec cretae 文件名` * 比如pod spec cretae MJExtension就会生成一个MJExtension.podspec ##### 填写podspec内容 ``` Pod::Spec.new do |s| s.name = "MJExtension" s.version = "0.0.1" s.summary = "The fastest and most convenient conversion between JSON and model" s.homepage = "https://github.com/CoderMJLee/MJExtension" s.license = "MIT" s.author = { "MJLee" => "xxxxx@qq.com" } s.social_media_url = "http://weibo.com/exceptions" s.source = { :git => "https://github.com/CoderMJLee/MJExtension.git", :tag => s.version } s.source_files = "MJExtensionExample/MJExtensionExample/MJExtension" s.requires_arc = true end ``` * 值得注意的是,现在的podspec必须有tag,所以最好先打个tag,传到github * `git tag 0.0.1` * `git push --tags` ##### 检测podspec语法 * `pod spec lint MJExtension.podspec` ##### 发布podspec * `pod trunk push MJExtension.podspec` * 如果是第一次发布pod,需要去https://trunk.cocoapods.org/claims/new认领pod ##### 检测 * `pod setup` : 初始化 * `pod repo update` : 更新仓库 * `pod search MJExtension` ##### 仓库更新 * 如果仓库更新慢,可以考虑更换仓库镜像 * `pod repo remove master` * `pod repo add master http://git.oschina.net/akuandev/Specs.git` ## UIMenuController的示例 ![UIMenuController](http://git.oschina.net/uploads/images/2016/1017/211425_6fa78d30_1026001.png "在这里输入图片标题") ### UIMenuController须知 - 默认情况下, 有以下控件已经支持UIMenuController - UITextField - UITextView - UIWebView ### 让其他控件也支持UIMenuController(比如UILabel) - 自定义UILabel - 重写2个方法 ```objc /** * 让label有资格成为第一响应者 */ - (BOOL)canBecomeFirstResponder { return YES; } /** * label能执行哪些操作(比如copy, paste等等) * @return YES:支持这种操作 */ - (BOOL)canPerformAction:(SEL)action withSender:(id)sender { if (action == @selector(cut:) || action == @selector(copy:) || action == @selector(paste:)) return YES; return NO; } ``` - 实现各种操作方法 ```objc - (void)cut:(UIMenuController *)menu { // 将自己的文字复制到粘贴板 [self copy:menu]; // 清空文字 self.text = nil; } - (void)copy:(UIMenuController *)menu { // 将自己的文字复制到粘贴板 UIPasteboard *board = [UIPasteboard generalPasteboard]; board.string = self.text; } - (void)paste:(UIMenuController *)menu { // 将粘贴板的文字 复制 到自己身上 UIPasteboard *board = [UIPasteboard generalPasteboard]; self.text = board.string; } ``` - 让label成为第一响应者 ```objc // 这里的self是label [self becomeFirstResponder]; ``` - 显示UIMenuController ```objc UIMenuController *menu = [UIMenuController sharedMenuController]; // targetRect: MenuController需要指向的矩形框 // targetView: targetRect会以targetView的左上角为坐标原点 [menu setTargetRect:self.bounds inView:self]; // [menu setTargetRect:self.frame inView:self.superview]; [menu setMenuVisible:YES animated:YES]; ``` ## 自定义UIMenuController内部的Item - 添加item ```objc // 添加MenuItem(点击item, 默认会调用控制器的方法) UIMenuItem *ding = [[UIMenuItem alloc] initWithTitle:@"顶" action:@selector(ding:)]; UIMenuItem *replay = [[UIMenuItem alloc] initWithTitle:@"回复" action:@selector(replay:)]; UIMenuItem *report = [[UIMenuItem alloc] initWithTitle:@"举报" action:@selector(report:)]; menu.menuItems = @[ding, replay, report]; ``` ## 自定义布局 - 继承UICollectionViewFlowLayout #### 重写prepareLayout方法 - 作用:在这个方法中做一些初始化操作 - 注意:一定要调用[super prepareLayout] #### 重写layoutAttributesForElementsInRect:方法 - 作用: - 这个方法的返回值是个数组 - 这个数组中存放的都是UICollectionViewLayoutAttributes对象 - UICollectionViewLayoutAttributes对象决定了cell的排布方式(frame等) #### 重写shouldInvalidateLayoutForBoundsChange:方法 - 作用:如果返回YES,那么collectionView显示的范围发生改变时,就会重新刷新布局 - 一旦重新刷新布局,就会按顺序调用下面的方法: - prepareLayout - layoutAttributesForElementsInRect: #### 重写targetContentOffsetForProposedContentOffset:withScrollingVelocity:方法 - 作用:返回值决定了collectionView停止滚动时最终的偏移量(contentOffset) - 参数: - proposedContentOffset:原本情况下,collectionView停止滚动时最终的偏移量 - velocity:滚动速率,通过这个参数可以了解滚动的方向 ####2种方法设置按钮四周圆角 - 方法1:`代码实现` ![代码实现](http://git.oschina.net/uploads/images/2016/1017/211333_5fd88727_1026001.png "在这里输入图片标题") - 方法2:`KVC视图设置` ![KVC](http://git.oschina.net/uploads/images/2016/1017/211345_11f2684f_1026001.png "在这里输入图片标题") ####找出类隐藏属性列表方法 - 查找方法 ```objc //导入系统头文件 #import @implementation LXRInputField //此方法只调用一次 +(void)initialize{ unsigned int count = 0; //拷贝出所有成员变量列表 //查找哪个类就传参输入[类名 class] Ivar* ivars = class_copyIvarList([UITextField class], &count); //遍历 for (int i =0; idouble类型 NSTimeInterval delta = [now timeIntervalSinceDate:create]; } ``` ####字典转模型 第三方框架使用 - 替换key值 ```objc /**把系统返回的id重新命名新的ID*/ /**第一种方法*/ +(NSDictionary *)mj_replacedKeyFromPropertyName{ return @{@"ID" : @"id"}; } /**第二种方法*/ +(NSString *)mj_replacedKeyFromPropertyName121:(NSString *)propertyName{ if ([propertyName isEqualToString:@"id"]) return @"ID"; return propertyName; } ``` ####当设置好Frame,打印结果与设置无问题的时候,达不到预期的效果 ![2](http://git.oschina.net/uploads/images/2016/1017/211249_2f63a916_1026001.png "在这里输入图片标题") ```objc //首先考虑是系统的自动调整属性-->设置不用自动调整 self.autoresizingMask = UIViewAutoresizingNone; ``` ####图片保存到相册 - 系统自带方法 ![系统自带方法](http://git.oschina.net/uploads/images/2016/1017/210815_ad3e56bd_1026001.png "在这里输入图片标题") - 代码写入 ```objc /**保存图片*/ - (IBAction)Save { //将图片写入相册 UIImageWriteToSavedPhotosAlbum(self.imageView.image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil); } /**系统建议命名此方法*/ - (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo{ if (error) { [MBProgressHUD showError:@"保存失败!"]; }else{ [MBProgressHUD showSuccess:@"保存成功!"]; } } ``` ####第三方FaceBook动画框架使用 ```objc #if 0 pop和CoreAnimation的区别: 1.CoreAnimation的动画只能添加到Layer上 2.pop的动画能添加到任何对象上 3.pop的底层并非基于CoreAnimation,是基于CADisplayLink 4.CoreAnimation的动画仅仅是表象,并不会真正修改对象的Frame/Size等值 5.pop的动画实时修改对象的属性,真正地修改了对象的属性 #endif /**pop简介*/ -(void)POPintro{ //kPOPViewCenter是根据 View 中心点进行动画 POPSpringAnimation* ani = [POPSpringAnimation animationWithPropertyNamed:kPOPViewCenter]; //动画开始时间(拿到当前时间+自定义时间) ani.beginTime = CACurrentMediaTime() + 1.0; //弹簧效果设置 ani.springBounciness = 20;//弹力效果模式是4,范围是[0.20] ani.springSpeed = 20; //速度模式是12,范围是[0,20] //包装View开始值--->CGPoint ani.fromValue = [NSValue valueWithCGPoint:CGPointMake(self.sloganView.centerX, self.sloganView.centerY)]; //包装View最终值--->CGPoint ani.toValue = [NSValue valueWithCGPoint:CGPointMake(self.sloganView.centerX, 400)]; //添加动画 key可是储存值,方便查找和释放 [self.sloganView pop_addAnimation:ani forKey:nil]; //kPOPLayerPositionY是根据 Layer 中心点进行动画 POPSpringAnimation* ani = [POPSpringAnimation animationWithPropertyNamed:kPOPLayerPositionY]; //动画开始时间(拿到当前时间+自定义时间) ani.beginTime = CACurrentMediaTime() + 1.0; //弹簧效果设置 ani.springBounciness = 20;//弹力效果模式是4,范围是[0.20] ani.springSpeed = 20; //速度模式是12,范围是[0,20] //包装Layer改变范围 ani.fromValue = @(self.sloganView.layer.position.y); ani.toValue = @(400); //添加动画 key可是储存值,方便查找和释放 [self.sloganView pop_addAnimation:ani forKey:nil]; } ``` ####IOS8版本 系统自动计算Cell高度方法 ![cellHeight](http://git.oschina.net/uploads/images/2016/1017/211053_a6c01795_1026001.png "在这里输入图片标题") ```objc /***重点:cell的高度高度 (IOS8版本以后可以自动设置Cell的高度)****/ //估计高度 self.tableView.estimatedRowHeight = 44; //系统自带自动根据估计高度计算Cell合适的高度 self.tableView.rowHeight = UITableViewAutomaticDimension; ``` ####设置状态栏方法 - `1.info文件修改设置` ![info文件修改设置](http://git.oschina.net/uploads/images/2016/1017/211153_02e798a5_1026001.png "在这里输入图片标题") - `2.代码设置状态` ![输入图片说明](http://git.oschina.net/uploads/images/2016/1017/211216_4cfb755c_1026001.png "在这里输入图片标题") ####得到按钮有图片时的Size,和图片大小一样 ```objc /**得到按钮有图片时的Size,和图片大小一样*/ addButton.size = [UIImage imageNamed:@"tag_add_icon"].size; addButton.size = [addButton imageForState:UIControlStateNormal].size; addButton.size = addButton.currentImage.size; ``` #### `重点!!!`找出上一界面的导航控制器(Push和Modal两种方法) - 通过`Push` ```objc // 如果控制器'a'->通过Push->另一个控制器'b',控制器'b'要拿到'a'导航栏控制器 // 1.取出当前的TabBarController->通过系统keyWindow的跟控制器拿到 UITabBarController *tabBarVc = (UITabBarController *)[UIApplication sharedApplication].keyWindow.rootViewController; // 2.在通过拿到的tabBarVc->通过当前选中的selectedViewController拿到当前所在的导航控制器 UINavigationController *navVc = (UINavigationController *)tabBarVc.selectedViewController; // 3.通过Push到下一界面 [navVc pushViewController:想要跳转到的控制器 animated:YES]; ``` - 通过`modal` ```objc // 如果控制器'a'->通过modal->另一个控制器'b',控制器'b'要拿到'a'导航栏控制器 // 根据展示控制器的属性 //a.presentedViewController -> b控制器 //b.presentingViewController -> a控制器 UIViewController* root = [UIApplication sharedApplication].keyWindow.rootViewController; UINavigationController* navVc = (UINavigationController*)root.presentedViewController; [navVc pushViewController:想要跳转到的控制器 animated:YES]; ```