Ios 如何计算调用所有类的次数

Ios 如何计算调用所有类的次数,ios,swift,userdefaults,Ios,Swift,Userdefaults,我希望用户能够知道他们访问每个类的次数。然后将每页的总数加在一起,形成一组总和。我想在两个视图控制器的日志文件中打印总和。所以只需要打印一个字符串 class oneV: UIViewController { override func viewDidLoad() { super.viewDidLoad() UserDefaults.standard.set(true, forKey: "VC1") } } class twoV: UIViewC

我希望用户能够知道他们访问每个类的次数。然后将每页的总数加在一起,形成一组总和。我想在两个视图控制器的日志文件中打印总和。所以只需要打印一个字符串

class oneV: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        UserDefaults.standard.set(true, forKey: "VC1")
    }
}

class twoV: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        UserDefaults.standard.set(true, forKey: "VC2")
    }
}

根据您的要求,我们将对应用程序使用情况进行分析。您可以通过两种方式实现

  • 通过屏幕访问将数据存储在本地数据库中,并在分析页面或汇总页面上显示
  • 用于在DB中存储屏幕详细信息的示例代码:

    ==>为屏幕捕获创建实体。 屏幕访问

    ==>使用屏幕名称存储数据

    let entity = NSEntityDescription.entity(forEntityName: "ScreenVisit", in: context)
    let newVisit = NSManagedObject(entity: entity!, insertInto: context)
    
    newVisit.setValue("HomeScreen", forKey: "screenname")
    newVisit.setValue("1", forKey: "visited")
    
    do {          
       try context.save()       
      } catch {       
       print("Failed saving")
    }
    
    ==>在需要的地方提取数据

        let request = NSFetchRequest<NSFetchRequestResult>(entityName: "ScreenVisit")
        //request.predicate = NSPredicate(format: <Your Filter Logic>)
        request.returnsObjectsAsFaults = false
        do {
            let result = try context.fetch(request)
            for data in result as! [NSManagedObject] {
               print(data.value(forKey: "screenname") as! String)
               print(data.value(forKey: "visited") as! String)
          }
    
        } catch {
    
            print("Failed")
        }
    
    let request=NSFetchRequest(entityName:“屏幕访问”)
    //request.predicate=NSPredicate(格式:)
    request.returnsObjectsAsFaults=false
    做{
    let result=try context.fetch(请求)
    对于结果中的数据![NSManagedObject]{
    打印(data.value(forKey:“屏幕名称”)为!字符串)
    打印(data.value(forKey:“已访问”)为!字符串)
    }
    }抓住{
    打印(“失败”)
    }
    
  • 您可以使用任何第三方库,如Google analytics、Crashlytics来跟踪您的用户操作
  • 参考链接:

    但根据我的经验,第二种方式更方便、更强大

    一切取决于你的要求


    希望这能帮助您捕获用户操作。

    如果您的意思是访问了每个视图控制器,当您说访问了每个类时。那么我建议您这样做
    viewdide

    class YourViewController: UIViewController {
    
        override func viewDidAppear(_ animated: Bool) {
            super.viewDidAppear(animated)
    
            let key = String(describing: type(of: self))
            let count = UserDefaults.standard.value(forKey: key) as? Int ?? 0
            UserDefaults.standard.set(value + 1, forKey: key)
        }
    
    }
    
    为了简化,可以在
    UIViewController
    上使用扩展

    extension UIViewController {
    
        func updateVisitCount() {
            let key = String(describing: type(of: self))
            let count = UserDefaults.standard.value(forKey: key) as? Int ?? 0
            UserDefaults.standard.set(count + 1, forKey: key)
        }
    
    }
    
    class BaseViewController: UIViewController {
    
        override func viewDidAppear(_ animated: Bool) {
            super.viewDidAppear(animated)
    
            updateVisitCount()
        }
    
    }
    
    或者,如果创建的每个视图控制器都需要此功能,则可以创建一个基本视图控制器,您可以在任何地方使用它,而不是
    UIViewController

    extension UIViewController {
    
        func updateVisitCount() {
            let key = String(describing: type(of: self))
            let count = UserDefaults.standard.value(forKey: key) as? Int ?? 0
            UserDefaults.standard.set(count + 1, forKey: key)
        }
    
    }
    
    class BaseViewController: UIViewController {
    
        override func viewDidAppear(_ animated: Bool) {
            super.viewDidAppear(animated)
    
            updateVisitCount()
        }
    
    }
    

    创建一个静态变量。静态变量是类的一种类型,而不是对象,因此在所有对象中都可能维护一个变量。我认为这个例子可以更好地解释它是如何工作的。单击ViewDidLoad方法中的

    调用此函数:

    func updateVisitingCounter() {
    
        var counter = UserDefaults.standard.integer(forKey: "firstPageCounter")
        counter += 1
        UserDefaults.standard.set(counter, forKey: "firstPageCounter")
    
    }
    

    最自动的解决方案是在
    viewDidLoad
    中插入记帐调用,而不替换原始的
    viewDidLoad

    在这里,我创建了一个示例游乐场

    import UIKit
    import PlaygroundSupport
    
    extension UIViewController {
        @objc dynamic func substitutedViewDidAppear() {
            print("This is injected code in view did appear")
            substitutedViewDidAppear() // it may look like recursive, but it isn't, actually it calls the original `viewDidAppear` method.
        }
        
        class func swizzle() {
            let originalMethod = class_getInstanceMethod(UIViewController.self, #selector(viewDidAppear(_:)))
            let substitutedMethod = class_getInstanceMethod(UIViewController.self, #selector(substitutedViewDidAppear))
            
            if  let originalMethod = originalMethod,
                let substitutedMethod = substitutedMethod {
                print("swizzled")
                method_exchangeImplementations(originalMethod, substitutedMethod)
            } else {
                print("not swizzled")
            }
        }
    }
    
    class MyViewController : UIViewController {
        override func loadView() {
            let view = UIView()
            view.backgroundColor = .white
    
            let label = UILabel()
            label.frame = CGRect(x: 150, y: 200, width: 200, height: 20)
            label.text = "Hello World!"
            label.textColor = .black
            
            view.addSubview(label)
            self.view = view
            print("view loaded")
        }
    }
    
    // Swizzle
    UIViewController.swizzle() // call this in @top of didFinishLaunchingWithOptions
    
    // Present the view controller in the Live View window
    PlaygroundPage.current.liveView = MyViewController()
    
    输出:

    视图加载

    这是视图中出现的注入代码


    现在,在
    substitutedViewDidAppear
    上部,按照@Rakesha Shastri的建议注入计数代码,调用
    substitutedViewDidAppear
    中的
    updateVisitCount
    方法并放置
    UIViewController.swizzle()
    在创建根窗口之前,请在
    ApplicationIDFinishLaunchingWithOptions
    中进行操作。

    您可以将项目范围内的声明变量设置为“类外”


    您还可以在公共位置声明这些变量

    在我看来,这太过分了。一旦应用程序关闭,你就会丢失信息。是的,当应用程序关闭时,你会丢失这些信息,但这是一个非常常见的问题。为了持久化,可以使用数据库层。谢谢。这本书读得很好。有趣的NSUserDefaults似乎是存储应用程序相关信息的好方法。如果您认为这是一个好的解决方案,请点击我的帖子:)它不适用于此用例。很抱歉这就是我在第一篇评论中试图表达的。当视图已经加载,而您在没有加载的情况下一次又一次地访问它时,会发生什么?这仍然需要计算。因此,您应该使用viewWillAppearSecond选项(更简单的选项)更有希望,因为如果自定义视图控制器重写了
    ViewDidAppear
    方法,则扩展的重写方法将不会被调用。@RatulSharker Yes。必须有意识地使用扩展,就像代码的第一个狙击手一样。我只是通过不让OP为每个视图控制器编写它来缩短它。最后一个是最小的,OP甚至不需要调用该方法,而是使用子类创建一个视图控制器。OP必须在项目中的每个视图控制器中调用该扩展方法。在objective-c world中还有另一个选项,比如方法swizzling,它就像黑魔法一样,用计数逻辑替换现有的
    UIViewController
    viewDidLoad
    ,并用
    viewDidLoad
    的原始实现注册另一个方法。要使用调用保持生命周期的一致性,请在新的
    viewDidLoad
    实现中使用新注册的方法。这有点复杂,但OP不必在现有的ViewController中手动插入任何代码。