直播项目笔记(二)

毛玻璃 + 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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,902评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,037评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,978评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,867评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,763评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,104评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,565评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,236评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,379评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,313评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,363评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,034评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,637评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,719评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,952评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,371评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,948评论 2 341

推荐阅读更多精彩内容

  • 动态编译的需求:如在写一个表格组件时,我们可能需要表格的某一列是可定制化的,比如这一列可实现点击响应一个事件,要实...
    Nicholasway阅读 3,260评论 0 2
  • 太过聪明的女子,往往过早看透了生命的真相,拥有一双洞察世事的眼睛,和内心对虚浮繁华本能的疏离。但张爱玲是个彻底的矛...
    o十二o阅读 3,372评论 4 15
  • 文/唐妈 清远是天地孕育出的仙体,生而为仙,万年难见。天帝本欲对他委以重任,奈何清远实在是和他名字一般,油盐不进,...
    唐妈阅读 2,913评论 6 24