美文网首页
直播项目笔记(二)

直播项目笔记(二)

作者: Closer3 | 来源:发表于2017-11-30 19:53 被阅读0次

毛玻璃 + runtime全局pop + 面向协议编程 + 粒子动画

组合第一天封装CLOPageView和瀑布流布局

  • UIVisualEffectView视图实现毛玻璃效果
// 添加待模糊的图片视图
let imageView = UIImageView(image: UIImage(named: "timg"))
imageView.frame = view.frame
imageView.contentMode = .scaleAspectFill
imageView.clipsToBounds = true
view.addSubview(imageView)
  
// 生成特定样式的模糊效果
let blur = UIBlurEffect(style: .light)
  
// 根据模糊效果生成模糊视图
let blurView = UIVisualEffectView(effect: blur)
  
// 设置模糊区域大小
blurView.frame = view.frame
  
view.addSubview(blurView)
  • UIStackView 实现并列布局, 可做工具栏。 UIStackView的核心便是方便垂直或水平排布多个 subview

// 给 5 个 button 设置不同的 tag 同时连线下面的方法
@IBAction func menuClick(_ sender: UIButton) {
    switch sender.tag {
        case 0:
            print("点击了功能1")
        case 1:
            print("点击了功能2")
        case 2:
            print("点击了功能3")
        case 3:
            print("点击了功能4")
        case 4:
            print("点击了功能5")
        default:
            fatalError("未处理按钮")
        }
    }
  • autoresizingUIView的属性,一直存在,使用也比较简单,但是没有autolayout那样强大。如果你的界面比较简单,要求的细节没有那么高,那么你完全可以使用autoresizing去进行自动布局
/// 属性说明
//不会随父视图的改变而改变
    UIViewAutoresizingNone                 = 0,
//自动调整view与父视图左边距,以保证右边距不变
    UIViewAutoresizingFlexibleLeftMargin   = 1 << 0,
//自动调整view的宽度,保证左边距和右边距不变
    UIViewAutoresizingFlexibleWidth        = 1 << 1,
//自动调整view与父视图右边距,以保证左边距不变
    UIViewAutoresizingFlexibleRightMargin  = 1 << 2,
//自动调整view与父视图上边距,以保证下边距不变
    UIViewAutoresizingFlexibleTopMargin    = 1 << 3,
//自动调整view的高度,以保证上边距和下边距不变
    UIViewAutoresizingFlexibleHeight       = 1 << 4,
//自动调整view与父视图的下边距,以保证上边距不变
    UIViewAutoresizingFlexibleBottomMargin = 1 << 5

  • swift中数组常用的两个方法

map函数能够被数组调用,它接受一个闭包作为参数,作用于数组中的每个元素。闭包返回一个变换后的元素,接着将所有这些变换后的元素组成一个新的数组

// 可以看到我们甚至可以不再定义可变的数组直接用不可变的就可以
let numbers = [1,2,3]
let sumNumbers = numbers.map { (number: Int) -> Int in
    return number + number
}
// 最终简化写法
let sumNumbers3 = numbers.map { $0 + $0 } 
// [2,4,6]

filter可以取出数组中符合条件的元素 重新组成一个新的数组

let numbers = [1,2,3,4,5,6]
let evens = numbers.filter { $0 % 2 == 0 }
// [2,4,6]
  • swift 4.x中字典转模型问题,要在属性前面加@objc

  • swift常用的第三方框架

Alamofire相当于OCAFNetworking
Kingfisher 相当于OCSDWebImage

runtime实现全局pop

runtime的方法打印interactivePopGestureRecognizer隐藏属性 找出添加手势所需的targetaction

var count:UInt32 = 0
let ivars = class_copyIvarList(UIGestureRecognizer.self, &count)!
for i in 0..<count {
  //拿到ivar指针
  let nameP = ivar_getName(ivars[Int(i)])
  //根据指针找到对应的属性的字符串
  let name = String(cString: nameP!)
  print(name)
}
   
//        _gestureFlags
//        _targets
//        _delayedTouches
//        _delayedPresses
//        _view
   
guard let targets = interactivePopGestureRecognizer?.value(forKey: "_targets") as? [NSObject] else { return }
print(targets)
   
//        Optional([(action=handleNavigationTransition:, target=<_UINavigationInteractiveTransition 0x7ff117701e10>)])
   
let targetObjc = targets[0]
let target = targetObjc.value(forKey: "target")
let action = Selector(("handleNavigationTransition:"))
   
let panGes = UIPanGestureRecognizer(target: target, action: action)
view.addGestureRecognizer(panGes)

面向协议编程

面向对象or面向协议?

  • 传统的面向对象思维方式:

有一只狗,有自己的名字, 可以跑
有一只猫,有自己的名字, 可以跑
有一个人,有自己的名字, 可以跑
抽象出一个动物类, 之后, 将跑的行为放入动物类中
如果需要一个吃的行为, 也可以抽象在动物类中

  • 面向对象开发弊端

如果有一个机器人(一辆车), 也有跑的行为, 这个时候如何抽象呢, 显然该抽象方式并不是特别合理

  • 真实开发中的场景

对UIViewController/UITableViewController/UICollectionViewController抽象相同的方法

  • 面向对象开发核心是: 封装-继承-(多态)

面向协议示例

  • Swift 标准库中有 50 多个复杂不一的协议,几乎所有的实际类型都是满足若干协议的

  • 面向协议开发核心是: 模块化(组件化)

  • 面向协议开发应用: 将功能抽取在单独的协议中, 如果有控制器需要, 实现我的协议即可

/* 命名一般以 able 结尾
 swift 可以在协议中实现方法 */

// MARK: - 方法声明
protocol NibLoadable {
    
}

// MARK: - 方法实现

/* 方法实现只能写在 extension 中
   用协议封装 加载 xib 的方法
   用 where 给协议方法增加条件约束 只有 UIView 才能调用
   协议方法只能用 static 修饰  */
extension NibLoadable where Self: UIView {
    static func loadFromNib(_ nibName: String? = nil) -> Self {
        let loadName = nibName == nil ? "\(self)" : nibName!
        return Bundle.main.loadNibNamed(loadName, owner: nil, options: nil)?.first as! Self
    }
}

TestView中遵循并实现协议 TestView.loadFromNib()

粒子动画

func emitterAnimationStart(_ point: CGPoint) {
    
    // 1.创建发射器
    let emitter = CAEmitterLayer()
    
    // 2.设置发射器的位置
    emitter.position = point
    
    // 3.开启三维效果
    emitter.preservesDepth = true
    
    // 4.创建粒子,并且设置粒子相关属性
    // 4.1 创建粒子 cell
    let cell = CAEmitterCell()
    
    // 4.2 设置粒子速度
    cell.velocity = 150
    cell.velocity = 100
    
    // 4.3 设置粒子的大小
    cell.scale = 0.7
    cell.scaleRange = 0.3
    
    // 4.4 设置粒子方向
    cell.emissionLongitude = CGFloat(-Double.pi / 2)
    cell.emissionRange = CGFloat(Double.pi / 4)
    
    // 4.5 设置粒子存活时间
    cell.lifetime = 6
    cell.lifetimeRange = 1.5
    
    // 4.6 设置粒子旋转
    cell.spin = CGFloat(Double.pi / 2)
    cell.spinRange = CGFloat(Double.pi / 4)
    
    // 4.7 设置粒子每秒弹出的个数
    cell.birthRate = 20
    
    // 4.8 设置粒子展示图片
    cell.contents = UIImage(named: "good2_30x30_")?.cgImage
    
    // 5.将粒子加入到发射器中
    emitter.emitterCells = [cell]
    
    // 6.将发射的 layer 添加到父 layer 中
    view.layer.addSublayer(emitter)
}

func stop() {
    /*
     for layer in view.layer.sublayers! {
         if layer.isKind(of: CAEmitterLayer.self) {
             layer.removeFromSuperlayer()
         }
     }
     */
    view.layer.sublayers?.filter({ $0.isKind(of: CAEmitterLayer.self)}).first?.removeFromSuperlayer()
}

坐标转换

// 将像素point由point所在视图转换到目标视图view中,返回在目标视图view中的像素值
- (CGPoint)convertPoint:(CGPoint)point toView:(UIView *)view;
// 将像素point从view中转换到当前视图中,返回在当前视图中的像素值
- (CGPoint)convertPoint:(CGPoint)point fromView:(UIView *)view;

// 将rect由rect所在视图转换到目标视图view中,返回在目标视图view中的rect
- (CGRect)convertRect:(CGRect)rect toView:(UIView *)view;
// 将rect从view中转换到当前视图中,返回在当前视图中的rect
- (CGRect)convertRect:(CGRect)rect fromView:(UIView *)view;

//例把UITableViewCell中的subview(btn)的frame转换到 controllerA中

// controllerA 中有一个UITableView, UITableView里有多行UITableVieCell,cell上放有一个button
// 在controllerA中实现:
CGRect rc = [cell convertRect:cell.btn.frame toView:self.view];
或
CGRect rc = [self.view convertRect:cell.btn.frame fromView:cell];
// 此rc为btn在controllerA中的rect

//或当已知btn时:
CGRect rc = [btn.superview convertRect:btn.frame toView:self.view];
或
CGRect rc = [self.view convertRect:btn.frame fromView:btn.superview];

通过按钮的点击实现一个功能的开启和关闭

button.isSelected = !sender.isSelected
button.isSelected ? emitterAnimationStart(point!) : stopEmitterAnimation()

CLOPageView 拓展

主要思路:对中间的 collectionView自定义layout

相关文章

  • 直播项目笔记(二)

    毛玻璃 + runtime全局pop + 面向协议编程 + 粒子动画 组合第一天封装CLOPageView和瀑布流...

  • 直播项目笔记(一)

    颜色封装 + ClOPageView + 瀑布流 搭建主题框架 导航栏布局 改变导航栏的颜色 改变状态栏的颜色 设...

  • 直播项目笔记(六)

    FFmpeg + 流媒体协议 FFmpeg FFmpeg简介 FFmpeg是一个非常强大的音视频处理库,包括视频采...

  • 直播项目笔记(三)

    IM编程 整合工具栏 UITextField设置leftView和rightView 使用闭包传值 监听键盘的高度...

  • 直播项目笔记(五)

    GIF + 视频采集 + GPUImage + 视频编码 播放 Gif 图 需要使用ImageIO框架 思路:1....

  • 直播项目笔记(四)

    心跳包 + 图文混排 + Core Graphics Socket 服务器加入心跳包 Timer 和 Runloo...

  • 直播技术简单介绍(非原创)

    文章大纲 一、视频直播原理介绍二、视频直播代码演示(Android)三、项目源码下载四、参考文章 一、视频直播原理...

  • NO.3 --- IDEA 创建 Java 项目

    笔记内容:一、IDEA 创建 Java 项目。二、删除 Java 项目。 一、IDEA 创建 Java 项目。 1...

  • 8.5-8.8

    守直播, 记笔记, 公基, 准备考试,公告还不出 二合一,充实

  • 涂鸦笔记技巧

    2017-6-29 泡泡老师直播第二次微课 《涂鸦笔记》的技巧

网友评论

      本文标题:直播项目笔记(二)

      本文链接:https://www.haomeiwen.com/subject/zkdbbxtx.html