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")
}
}
根据您的要求,我们将对应用程序使用情况进行分析。您可以通过两种方式实现
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:“已访问”)为!字符串)
}
}抓住{
打印(“失败”)
}
希望这能帮助您捕获用户操作。如果您的意思是访问了每个视图控制器,当您说访问了每个类时。那么我建议您这样做
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中手动插入任何代码。