iOS学习笔记

  1. autoLayout

Autolayout的作用非常明确:帮我们确定在不同设备、不同(父view)环境下,同一个可视单元所应具有合适的位置和尺寸,因此,当一个UIView上所施加的约束能够唯一确定它的frame(x, y, width, height)的时候我们的自动布局的使用才是正确的。而新手通常犯的两类错误就是约束不足(约束太少)和约束冲突两种(约束太多)。如果你给出的约束只能够确定这个view的大小,或者位置或者位置中的某一个项(比如x)的时候,就会出现约束不足的情况,在xib或者storyboard中,会以黄色的警告出现在左侧提示框内;如果你给出的约束推导出了两个甚至多个互相矛盾的位置尺寸结果的时候,就产生了布局错误,在编译的时候直接就build不过。

  1. 画布中角度是顺时针转的angle

贝泽尔曲线添加圆弧clocwise参数就是常规理解顺时针,core graphics添加圆弧时此参数正好相反

*更新:关于角度的旋转方向,其实是按逆时针转动的,但是因为在一些坐标系里对Y轴进行了变换(乘以-1)导致成了顺时针转动,这也解释了上边引用里的说明* [参考](https://developer.apple.com/documentation/coregraphics/cgcontext/1456228-rotate)
  1. 引用

在绘制的方法中,使用 UIGraphicsBeginImageContextWithOptions 来取代 UIGraphicsGetCurrentContext 出处

  1. 应用间相互调用只要知道双方设置好的URL就行了,打开另一个应用时可以把当前应用的URL传过去,要打开的应用就可以根据响应的代码就可以让用户触发返回原始应用了
  2. 事件的响应链是从子视图到父视图层层传递的,模式是子视图调用父视图相同的方法([super XXX]),所以触发该事件的先后顺序应该是从父视图到子视图,当然这是默认情况,如果你重写了事件方法,就可以控制是否把事件传递给父视图,或者哪个视图先触发事件
    上面的理解貌似不够准确,重新整理如下:
    .事件链的建立 简单讲是发生在addSubView时,被添加的视图的nextResponder(下一个响应者)就是它的父视图。如果一个veiw(下面简称A)不是普通的view,它是某个viewcontroller的根veiw,那么A的nextResponder在A从初始化完后就赋值为viewController。然后当A被addsubview到rootview的时候(addChildViewController时会发生),Controller A的nextresponder被复制为rootview。
    .事件的传递 当用户触摸时,UIKit先创建一个事件对象,加到事件队列中去,然后UIAPPlication从中取出来,从window开始查找,发现点击位置在window的范围内,那就继续查找window的subViews,直到找到视图树最顶部的叶子视图,然后把事件交给这个顶部视图,视图处理事件,如果不处理就交给它的nextResponser,层层往下,直到window再到UIApplacation。
  3. 像素就是一个小点,px就表示一个真正的点,pt就是标准中定好的有大小的点,1/72英寸,分辨率是指指每单位面积(平方英寸)像素的个个数,即dpi,之所以谈到具体的设备时经常用W*H表示分辨率,是用了当前设备的长宽方向上的像素除以当前设备相应的尺寸
  4. devices只有选择了universal(通用)才可以让iPhone和iPad共用界面或者说不同尺寸的设备共用界面
  5. IQKeyboardManager 必须是在push或者present的VC的视图上才可以自动调整位置 事后问过作者,说怎么都可以,但是我用的版本却实不行,作者给意见,可以考虑addChildViewCOntroller
  6. 从UINavigationController里出来的UIViewController无法不会执行shouldAutorotate,这种情况必须自定义一个继承UINavigationController的类
  7. 要实现UITableViewCell的编辑必须实现下面两个方法
    (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath;
    (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath;
  8. 关于堆栈的理解 :栈 — 战死 栈是死的,一般是提前分配好的,除非你malloc出来,堆的可控性就比较强,也就是自己控制它的创建,当然它的消亡也应该你来控制
    举个小栗:在一个函数中定义了 NSArray *a = [[NSArray alloc] init] a是个指针,他就是放在栈中的,但是它指向的那个数组就是存在堆中的。
  9. objective-c因为字符串比较特殊,所以在写正则的时候,碰到转义字符必须多加一个”\\”,比如:全数字字符:@"^\\\\d\\+$"
  10. UITableView竟然被我发现了一个新用法(当然这个用法是旧的),它在编辑状态下可以左边显示圆圈,didSelected会自动选中,再按一次didDeselect会自动消失
  11. 下面这句话的意思是获取aView在window中的位置,注意最前边是aView的父视图
    [aView.superview convertPoint:aView.frame.origin toView:nil];
  12. UIView不能同事加多个由make生成的transform,如果加多个,第二个应该用原始方法,如下self.contentViewContainer.transform = CGAffineTransformMakeTranslation(point.x, 0);
    self.contentViewContainer.transform = CGAffineTransformScale(self.contentViewContainer.transform,scale, scale);
  13. extern 是表明这个这个变量是全局的,在其他类里也可以使用这个变量不必把首次声明这个变量的类引入就行,但是必须得再次声明,static是仅限于此类里使用,其他类要想使用必须引入该类
  14. 图片的坐标原点在左下角
  15. 关于刷新子视图

-layoutSubviews方法:这个方法,默认没有做任何事情,需要子类进行重写
-setNeedsLayout方法: 标记为需要重新布局,异步调用layoutIfNeeded刷新布局,不立即刷新,但layoutSubviews一定会被调用
-layoutIfNeeded方法:如果,有需要刷新的标记,立即调用layoutSubviews进行布局(如果没有标记,不会调用layoutSubviews)
如果要立即刷新,要先调用[view setNeedsLayout],把标记设为需要布局,然后马上调用[view layoutIfNeeded],实现布局

  1. 我勒个去哎,self.navigationController.toolbarHidden = NO 这样可以在View下边有显示一个toolbar哎,这个是可以利用的哟,完成任务必须抽时间好好研究一番,新发现啊
  2. 下面的代码输出什么
    @implementation Son : Father
    • (id)init{
      self = [super init]; if (self) {
      NSLog(@"%@", NSStringFromClass([self class]));
      NSLog(@"%@", NSStringFromClass([super class]));
      }
      return self;
      }
      @end

答案:都输出”Son”解释:objc中super是编译器标示符,并不像self一样是一个对象,遇到向super发的方法时会转译成objc_msgSendSuper(...),而参数中的对象还是self,于是从父类开始沿继承链寻找- class这个方法,最后在NSObject中找到(若override)此时,[self class]和[super class]已经等价了。

所以,子类调用父类的某个方法,父类的这个方法又调用了一个跟子类有相同名字的某个方法,相当于子类直接调用了这个方法

  1. UITextField是有leftView和rightView的,可以利用leftView在添加了背景图片后添加左边留白,但是得注意要设置属性
    leftViewMode = UITextFieldViewModeAlways
  2. load方法会在类实例话的时候调用,如果要用runtime黑魔法的话就可以在这里用。initializer方法会在第一次调用该类的方法时调用这个方法,属于懒加载
  3. UITableView的header是searchBar的时候拖拽时searchBar背景会被拉伸
  4. 视图控制器切换方法
    • (void)transitionFromViewController:(UIViewController *)fromViewController toViewController:(UIViewController *)toViewController duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^)(BOOL finished))completion NS_AVAILABLE_IOS(5_0);
      不用你再去给容器视图添加(addSubView)和删除(removeFromSuperView)子视图,它会帮你处理好
  5. 哈哈哈,XCode好傻哟,如果你在.m文件里提前有了 setX和x方法,然后才在.h文件里用@property声明x属性,.m里就不允许你使用_x这个变量。此时,@synthesize 就派上了用场。@dynamic@synthesize的区别在于:使用@synthesize编译器会确实的产生getter和setter方法,而@dynamic仅仅是告诉编译器这两个方法在运行期会有的,无需产生警告。

假设有这么个场景,B类,C类分别继承A类,A类实现某个协议(@protocol),协议中某个属性( somePropety )我不想在A中实现,而在B类,C类中分别实现。如果A中不写任何代码,编译器就会给出警告:
“use @synthesize, @dynamic or provide a method implementation"
这时你给用@dynamic somePropety; 编译器就不会警告,同时也不会产生任何默认代码。

  1. UITableView在编辑状态下如果指定编辑样式是添加和删除,可以在视图上显示复选框,利用这个特性可以方便实现多选。

    • (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
      {
      return UITableViewCellEditingStyleDelete | UITableViewCellEditingStyleInsert;
      }注意:以上是在UITableView单选的情况下,如果是多选就会自动出现复选框,不会执行上段代码。😂说了好多废话哟
  2. UITableView在调用了reloadData之后,tableView会在调用完cell的高度获知contentSize之后就调用reloadData之后的语句了,完了之后才去加载cell

  3. 在 MRC 下,使用 __block 说明符也可以避免循环引用。因为当 block 从栈拷贝到堆时,__block 对象类型的变量不会被 retain,没有 __block 说明符的对象类型的变量则会被 retian。正是由于 __block 在 ARC 和 MRC 下的巨大差异,我们在写代码时一定要区分清楚到底是 ARC 还是 MRC。

  4. 实现下面的方法,我们就可以对一个类进行使用想NSArray和NSDictionary那样的语法糖用下标或者key来存取数据了, so cool

    - (id)objectAtIndexedSubscript:(NSUInteger)idx;
    - (void)setObject:(id)objatIndexedSubscript:(NSUInteger)idx;
    - (void)setObject:(id)objforKeyedSubscript:(id <NSCopying>)key;
    - (id)objectForKeyedSubscript:(id)key;
    
  5. CALayer的border是出现在layer内部的,比如说layerWidth为10,那么border就会占据layer的content的四周宽度为10的空间。

  6. 系统视频的上传必须拷贝到沙盒目录中才能上传。😥

  7. 手撸NSLayoutConstraint需要注意firstItem和secondItem的顺序

  8. 注意了,注意了,keyWindow不知道什么时候会被系统干掉,所以把hud加在keyWindow上的时候一定要注意哦。最近遇到的在把mov转换成mp4的时候系统起了个异步线程,然后kenWindow就被干掉了。

  9. 用CGContextClearRect就可以实现画一张中间透明的图片了。

  10. 想知道某个变量在程序调试时的状态,可以用借助dispatch_source_t 监控调试开始,打印变量 from

    dispatch_queue_t queue = dispatch_get_main_queue();
    static dispatch_source_t source = nil;
    __typeof(self) __weak weakSelf = self;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        source = dispatch_source_create(DISPATCH_SOURCE_TYPE_SIGNAL, SIGSTOP, 0, queue);
        if (source)
        {
            dispatch_source_set_event_handler(source, ^{
                NSLog(@"Hi, I am: %@", weakSelf);
            });
            dispatch_resume(source); // 10
        }
    });
  1. 当UINavigationController push或者pop操作时NavigationBar右侧底部会变灰,解决这种问题需要把最接近当前vc的view的view的背景色修改一下就可以了。
  2. 企业账户 往App Store上发布应用必须是Agent账户
  3. 用Xcode写C,即使仅仅有C也要把Compile Sources As改为Objective C++
  4. 我一直以为下边的代码是默认的,然而并不是,需要明确写出来。😂
    self.tableView.rowHeight = UITableViewAutomaticDimension;
  5. CALayer对path的动画执行完后path为初始值,如果想要最后停留住状态就可以把初始值设为toValue的值
  6. iOS11的本地通知要想在前台显示必须实现代理willPresent的方法,文档有说明的,记住
  7. 像素就是绘画的基本单元,就是一个方格,但是并不一定是一个物理点,在高清屏上是有多个包含多个物理点的。DPI就是每英寸有多少个像素。分辨率在用ps的设计那里就是DPI,但是一般在移动开发那里就是图片的长宽。
  8. 关于在Swift中self.propertyproperty,提倡不用self,这样如果在闭包中使用的属性是属于当前的实例对象时编译器就会报错,你就必须加上self,当你加上self的时候你就意识到self要被循环引用了,你就知道要处理这个问题了。
  9. Paste_Image.png
  10. UIScrollView在iOS11中如果设置了自动调整内容位置之后,contentInset默认是0,一些需要用到contentInset的地方可以参考adjustedContentInset
  11. FileURL读取文件内容时要用path属性,不要用absoluteString
  12. Podfile指定Swift版本
post_install do |installer|
installer.pods_project.targets.each do |target|
   target.build_configurations.each do |config|
     config.build_settings['SWIFT_VERSION'] = '4.2'
   end
 end
end
  1. UICollectionViewFlowLayoutminimumLineSpacingminimumInteritemSpacing在滚动方向不同时表示的间距不一样哦
  2. 如果您的UISearchBar激活后位置抛出屏幕,请先尝试用frame的方式代替autoLayout设置UISearchBar的位置
  3. 在UITableView使用自动布局计算高度时,对Cell的布局是要确保约束加载contentView上,而不是safeArea上

51.definesPresentationContext设置在支撑视图上会让USearchConstroller的searchBar不会无故消失

  1. iOS新系统11之后contentInsetAdjustmentBehavior默认为自动,如果UITableView的frame跟父视图一样就可以实现NavigationBar或TabBar的底层模糊效果
  2. PhotoKit以url的形式导入资源时注意url要有后缀名
  3. UICollectionView的layout如果是UICollectionViewFlowLayout,如果不设置estimatedItemSizeCGSize.zero,将使估算大小起作用,导致界面跟预期不同
  4. iOS10之后的推送如果想要显示的话需要在func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions) -> Void)调用completionHandler([.sound, .list, .banner]),参数传空就不显示推送
  5. iOS 事件传递https://mp.weixin.qq.com/s/OFwC7Z3iir2wKPJoRpLhFw

图片

当事件到来时,会通过 hitTestpointInside两个方法,从 Window开始向上面的视图查找,找到第一响应者的视图。找到第一响应者后,系统会判断其是继承自 UIControl还是 UIResponder,如果是继承自 UIControl,则直接通过 UIApplication直接向其派发消息,并且不再向响应者链派发消息。

如果是继承自 UIResponder的类,则调用第一响应者的 touchesBegin,并且不会立即执行 touchesEnded,而是调用之后顺着响应者链向后查找。如果在查找过程中,发现响应者链中有的视图添加了手势,则进入手势的代理方法中,如果代理方法返回可以响应这个事件,则将第一响应者的事件取消,并调用其 touchesCanceled方法,然后由手势来响应事件。

如果手势不能处理事件,则交给第一响应者来处理。如果第一响应者也不能响应事件,则顺着响应者链继续向后查找,直到找到能够处理事件的 UIResponder对象。如果找到 UIApplication还没有对象响应事件的话,则将这次事件丢弃。


标题:iOS学习笔记
作者:yuyedaidao
地址:http://mooncake.wang/articles/2018/11/09/1573699414710.html