小编San*_*ari的帖子

如何使用BehaviorRelay作为RxSwift中Variable的替代?

从RxSwift4开始,Variable移动到Deprecated.swift标记Variable未来可能的弃用.建议的替代方案VariableBehaviorRelay.在发布这个问题时,由于我在网上找不到太多的教程,BehaviorRelay我在SO中发布了这样一个基本问题.

假设我正在进行webService调用,并且我收到一块JSONArray数据,在逐个解析JSON对象时我更新了我的Variable的value属性

这是我的变量声明

var myFilter = Variable<[MyFilterModel]>([MyFilterModel(data: "{:}")])
Run Code Online (Sandbox Code Playgroud)

每次我将变量更新为获取新元素时

myFilter.value.append(newModel)
Run Code Online (Sandbox Code Playgroud)

当Variable绑定到CollectionView时,collectionVie将立即使用新添加的对象更新其UI.

使用BehaviorRelay的问题

现在我的声明看起来像

var myFilter = BehaviorRelay<[MyFilterModel]>(value: [MyFilterModel(data: "{:}")])
Run Code Online (Sandbox Code Playgroud)

但最大的问题myFilter.valuereadOnly.很明显

myFilter.value.append(newModel) 
Run Code Online (Sandbox Code Playgroud)

不是解决方案.我发现我可以使用accept.

但是现在当我尝试解析响应中的每个元素并更新myFilter的值时

self?.expertsFilter.accept(newModel)
Run Code Online (Sandbox Code Playgroud)

上面的陈述给出了错误引用

无法将NewModel的值转换为预期的争论类型[NewModel]

显然,它期待一个数组而不是一个单独的元素.

解决方法:

解决方案1:

因此,一个解决方案是在临时数组中累积所有响应并且一旦完成触发 self?.expertsFilter.accept(temporary_array)

解决方案2:

如果我必须onNext在解析每个元素时向订阅者发送事件,我需要将self?.expertsFilter的值复制到new Array,将新解析的元素添加到它并返回新数组.

解决方案3:

摆脱BehaviorRelay并使用BehaviorSubject/PublishSubject

前两个声音令人沮丧,因为可能需要在解析每个元素时触发UI我不能等到解析整个响应.因此,解决方案1显然没有多大用处.

第二种解决方案更加可怕,因为它每次发送onNext事件时都会创建一个新数组(我知道它是临时的并且将被释放).

题:

因为BehaviorRelay被提议作为Variable进入两难的替代方案,我accept正确使用?有没有更好的方法来解决它?

请帮忙

rx-swift

48
推荐指数
4
解决办法
2万
查看次数

重建应用程序时文档目录路径更改

我从url下载视频文件并使用以下路径将其保存在文档目录中:

  let destination: DownloadRequest.DownloadFileDestination = { _, _ in
      let pathComponent = "pack\(self.packID)-\(selectRow + 1).mp4"
      let directoryURL: URL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
      let folderPath: URL = directoryURL.appendingPathComponent("Downloads", isDirectory: true)
      let fileURL: URL = folderPath.appendingPathComponent(pathComponent)
      return (fileURL, [.removePreviousFile, .createIntermediateDirectories])
    }
Run Code Online (Sandbox Code Playgroud)

我的视频已下载并成功播放.但是有一个问题,当我在Xcode中重建应用程序并尝试播放我下载的最后一个视频时,视频没有显示,当我下载新视频时,这个保存并成功播放.

我已经看过每个视频包路径,它们是不同的.

1 - file:/// Users/myMac/Library/Developer/CoreSimulator/Devices/EAC2F4CE-EA09-46C0-B403-1CE9E24B6822/data/Containers/Data/Application/1D2C1F7B-E627-4898-91C1-D0AF8D5E0F1E/Documents/Downloads /pack7-1.mp4

2 - file:/// Users/myMac/Library/Developer/CoreSimulator/Devices/EAC2F4CE-EA09-46C0-B403-1CE9E24B6822/data/Containers/Data/Application/F950E9A5-C9F3-4B8C-BCF5-647EEC233CEE/Documents/Downloads /pack7-3.mp4

现在,我的问题是,当我们从App Store更新应用程序时,是否意味着重新安装?这条路是否改变了?

怎么能解决这个问题?

filepath ios nsdocumentdirectory swift

11
推荐指数
2
解决办法
5905
查看次数

面向协议的编程是否带来了与继承主要解决的代码重复相同的旧问题?

概观

我试图了解Swift的面向协议编程范例.根据Apple的WWDC 2015视频https://developer.apple.com/videos/play/wwdc2015/408/协议可以实现继承所能实现的一切,并且还解决了继承的根本问题.

虽然协议通过将每个功能(功能)捕获为协议并允许类/结构确认多个协议来解决多重继承的问题,但我认为协议永远不能替代继承,原因如下.

让我们假设我正在实施学院/学校自动化软件,并且有两个实体,工作人员和校长,我们假设他们都上课但是校长以及课程控制员工.

所以我创建了一个协议,它将模拟正在上课的常用功能.所以让我们创建一个协议.

protocol staffProtocol {
    var classHour : Int { get set}
    var numberOfClass : Int? { get set }

    mutating func doesWork()
}

extension staffProtocol {
    mutating func doesWork(){
        classHour = 9
        numberOfClass = 4
        print("Takes calss")
    }
}
Run Code Online (Sandbox Code Playgroud)

由于Take class是工作人员和校长的共同任务所以我提供了一个默认扩展,它提供了一个实现,doesWork()并说类需要.

现在让我们编写一个Staff结构,它将向staffProtocol确认,

struct Staff : staffProtocol {
        var classHour: Int = 0
        var numberOfClass: Int? = 0
    }
Run Code Online (Sandbox Code Playgroud)

现在,如果我创建一个staff对象

var staff = Staff()
staff.doesWork()
Run Code Online (Sandbox Code Playgroud)

一切都运行得很好,现在让我们创建一个Principal结构,它也将扩展staffProtocol,

struct Principal : staffProtocol {
    var …
Run Code Online (Sandbox Code Playgroud)

inheritance protocols ios swift

7
推荐指数
1
解决办法
487
查看次数

在swift3中将一个对象的属性分配给另一个对象(尝试实现复制功能)的最佳方法

我正在尝试深度复制Swift类实例.由于copymutableCopy函数仅适用于NSObject类后代,我需要为Swift类对象实现我自己的copy函数.

这是我做的,

protocol Copying {
    init(original: Self)
}

extension Copying {
    func copy() -> Self {
        return Self.init(original: self)
    }
}

class A : Copying {
    var name : String? = nil
    var age : Int? = nil
    var address : String? = nil

    init(name : String) {
        self.name = name
    }

    required init(original: A) {
        //one way
        self.name = original.name
        self.age = original.age
        self.address = original.address

        //second way
        let originalReflect = Mirror(reflecting: original) …
Run Code Online (Sandbox Code Playgroud)

mirror swift3

6
推荐指数
0
解决办法
788
查看次数

RealTime Reload UITableview没有"Index out of Range"swift

我正试图每秒重新加载我的tableview.我现在重新加载tableview对象,但由于我Order在重新加载之前清除数组,因为索引超出范围而崩溃.

这是我目前的代码

 var orders = [Order]()

 override func viewDidLoad() {
    super.viewDidLoad()

    // table stuff
    tableview.dataSource = self
    tableview.delegate = self

    // update orders
    var timer = Timer.scheduledTimer(timeInterval: 4, target: self, selector: "GetOrders", userInfo: nil, repeats: true)

    GetOrders()

}

 func numberOfSections(in tableView: UITableView) -> Int {
    if orders.count > 0 {
        self.tableview.backgroundView = nil
        self.tableview.separatorStyle = .singleLine
        return 1
    }

    let rect = CGRect(x: 0,
                      y: 0,
                      width: self.tableview.bounds.size.width,
                      height: self.tableview.bounds.size.height)
    let noDataLabel: UILabel = UILabel(frame: rect)

    noDataLabel.text = …
Run Code Online (Sandbox Code Playgroud)

real-time uitableview ios swift swift3

5
推荐指数
3
解决办法
2687
查看次数

如何在VIPER设计模式中将ViewController参考传递给路由器?

PS: 这不是一个自以为是的问题。在VIPER中连接各种模块是一个合理的疑问。这是一个理论问题,因此没有附加任何代码。我只需要知道在这种特定情况下如何连接View-Presenter-Router,而不会违反VIPER

我是第一次尝试与VIPER接触。这是我对VIPER的基本了解。

视图:应该显示UI控件并捕获IBActions并调用其演示者的委托方法来处理事件

演示者:将处理所有与UI相关的数据,并准备进行渲染的数据并将其移交给View。每当需要屏幕转换时,它将调用其路由器并要求路由器执行转换

PS: Presenter中将没有任何UIComponent。因此import UIKit,主持人中没有任何发言。

路由器:负责执行屏幕转换,通常在线框的帮助下进行(可选,但最好在应用中使用此类)

Interactor:包含所有业务逻辑。只要需要基于业务逻辑进行处理,Presenter就会调用Interactor。

实体: POJO类(简单的Swift对象或Core数据实体)。

现在出现问题:

如果我的假设是正确的,那么Presenter应该是没有UIKit访问权限的普通Swift类。

如果为true,则假设我按了自己的按钮,ViewControllerA并且需要ViewControllerB在其顶部按另一个按钮,显然ViewControllerA会与之交谈PresenterA并告知该按钮已被轻按,现在PresenterA应该RouterA与之交谈并告诉其按入ViewControllerB

因为Router可以访问,UIKit所以我可以ViewControllerB使用Storyboard实例或通过xib 轻松创建一个新实例,但是为了推送该实例,我需要ViewControllerA的实例。

但是PresenterA不能包含对函数的引用ViewControllerA或将其作为参数传递给PresenterAin函数,因为UIViewController属于UIKit和Presenters不应具有UI语句。

我可能想到的解决方案:

解决方案1:

在创建Router实例时,将相应的ViewController实例作为其init(依赖注入阶段)的一部分传递,以这种方式,Router将始终引用其所属的ViewController

解决方案2:

让Router声明其协议并在ViewController中实现它,并且每当需要引用ViewController时,都使用Router的委托。但这与VIPER的规则矛盾,即路由器不应与View对话。

我在想什么吗 我的假设对吗?如果是,解决此问题的正确方法是什么,请提出建议

viper ios swift

5
推荐指数
1
解决办法
896
查看次数

UICollectionViewListCell 的自定义子类中的自调整大小在 iOS 14 中不起作用

背景:

iOS14 引入了一种新的方式来注册和配置 collectionViewCell 和在CollectionView 中的列表中WWDC 视频苹果开发人员表示默认情况下会自动调整大小UICollectionViewListCell,我们不必明确指定单元格的高度。如果我在各种配置中使用系统列表单元格,这很有效,但是当我将它与UICollectionViewListCell

我尝试了什么?

iOS 14 引入了一种配置单元格的新方法,我们不直接访问单元格组件来设置我们使用的各种 UI 属性评估器content configuration以及background configuration更新/配置单元格。当我们使用自定义单元格时,这变得有点棘手。

CustomSkillListCollectionViewCell

class CustomSkillListCollectionViewCell: UICollectionViewListCell {
    var skillLavel: String? {
        didSet {
            setNeedsUpdateConfiguration()
        }
    }
    
    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }

    override func updateConfiguration(using state: UICellConfigurationState) {
        backgroundConfiguration = SkillListViewBackgroundConfiguration.getBackgroundConfiguration(for: state)
        var content = SkillListViewContentConfiguration().updated(for: state)
        content.label = skillLavel
        contentConfiguration = content
    }
}
Run Code Online (Sandbox Code Playgroud)

技能列表视图背景配置

struct SkillListViewBackgroundConfiguration {
    @available(iOS 14.0, *)
    static func getBackgroundConfiguration(for …
Run Code Online (Sandbox Code Playgroud)

ios swift

5
推荐指数
1
解决办法
527
查看次数

关闭和函数之间的差异作为swift中的参数

我有近4年的Objective C经验和快速新手.我试图从Objective C的角度理解swift的概念.所以,如果我错了,请指导我:)

在目标c中,我们有块(可以在以后异步执行的代码块),这绝对是完美的意义.但是现在我们可以将一个函数作为参数传递给另一个函数,这个函数可以在以后执行,然后我们也可以关闭它.

根据Apple "功能是特殊情况的条款."

根据O'Reilly的 说法,"当函数作为值传递时,它会携带对外部变量的内部引用.这就是使函数成为闭包的原因."

所以我试了一下就明白了:)

这是我的关闭

override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a ni

        let tempNumber : Int = 5

        let numbers = [1,2,3,4,5]
        print (numbers.map({ $0 - tempNumber}))
}
Run Code Online (Sandbox Code Playgroud)

变量tempNumber甚至在声明闭包之前就被声明,但是闭包可以访问变量.现在而不是地图,我尝试使用自定义类传递闭包作为参数并尝试执行相同的代码:)虽然现在关闭在不同的范围内执行,但它仍然可以访问tempNumber.

我得出结论:闭包可以访问变量和方法,这些变量和方法在与自己封闭相同的范围内声明,尽管它在不同的范围内被执行.

现在而不是将关闭作为参数传递,尝试将函数作为参数传递,

class test {
    func testFunctionAsParameter(testMethod : (Int) -> Int){
        let seconds = 4.0
        let delay = seconds * Double(NSEC_PER_SEC)  // nanoseconds per seconds
        let dispatchTime = dispatch_time(DISPATCH_TIME_NOW, Int64(delay))

        dispatch_after(dispatchTime, dispatch_get_main_queue(), { …
Run Code Online (Sandbox Code Playgroud)

closures function ios swift

4
推荐指数
2
解决办法
3308
查看次数

从ProgressBarStyleHorizo​​ntal将其样式更改为progressBarStyleInverse时,Android进度条始终不确定

我正在尝试放置一个循环进度条,最初以不确定模式启动它,一旦下载开始并且进度可用,就将其转换为确定模式并设置其进度.使用样式progressBarStyleHorizo​​ntal时,代码工作正常,一旦我将其更改为progressBarStyleInverse设置,进度无效.进度条开始不确定并持续不变.

让我感到惊讶的是设置android:xml中的indeterminate = false也没有效果.

这是xml中进度条的声明

<ProgressBar
                    style="?android:attr/progressBarStyleHorizontal"
                    android:indeterminate="false"
                    android:layout_gravity = "center"
                    android:layout_height="wrap_content"
                    android:layout_width="wrap_content"/>
Run Code Online (Sandbox Code Playgroud)

这是我更新进度条进度的方法.显然我有一个id我已经在xml粘贴中删除了它.我有使用findViewById的进度条的参考.(如果您认为这是问题,参考进度条不是问题)

holder.progressbar.setIndeterminate(false);
holder.progressbar.invalidate();
holder.progressbar.setProgress(/*value */);
Run Code Online (Sandbox Code Playgroud)

我犯了什么错误?请帮忙.我在这个问题上浪费了近5个小时.请帮忙.

提前致谢.

xml android

2
推荐指数
1
解决办法
5490
查看次数

apns-collapse-id不合并多个通知iOS 10

我正在尝试折叠/合并属于我应用程序中同一事件的多个通知。iOS 10在有效负载中引入了键名apns-collapse-id。文档说具有相同的多个远程通知apns-collapse-id将合并并显示为单个通知。

因此,我们的通知有效负载中包含apns-collapse-idthread-id。不幸的是,由于在线上没有太多内容解释这些键的实际工作方式,因此为了安全起见,我们为apns-collapse-id和使用了相同的唯一值thread-id

我们期望与之apns-collapse-id合并的多个远程通知。这没有发生。

很少有人认为APNS崩溃不是免费的,我必须UNNotificationContentExtension手动实施和处理通知。我知道我可以添加和删除已经发布的本地通知,但是不确定如何更新已经发布的远程通知。

这是我们的有效载荷的样子

payload {
    "aps": {
        "alert": {
            "title": "Some title : ",
            "body": "Some body text"
        },
        "sound": "default",
        "payload": {
            "target": {
                "some key" : "Some value"
            },
            "thread_id": "Some_string_155863",
        },
        "apns-collapse-id": "Some_string_155863",
        "mutable-content": 1,
        "thread-id": "Some_string_155863",
        "badge": 33
    },
    "thread-id": "Some_string_155863",
    "apns-collapse-id": "Some_string_155863",
    "mutable-content": 1
}
Run Code Online (Sandbox Code Playgroud)

如您所见,apns-collapse-id和thread-id在JSON中重复了多次,因为我们不确定在哪里准确放置它们

我们尚未使用HTTPS / 2,但我相信iOS 10通知仍支持旧版HTTPS。我不是一个真正的网络人,所以我不太了解这些东西。忽略我对Https和Http2的傲慢态度

是否有人设法使apns-collapse-id起作用?请帮忙。

apple-push-notifications ios ios10

2
推荐指数
1
解决办法
1895
查看次数