Creating sub system and category for Cocoa Lumberjack os logging - cocoalumberjack

Apple documentation says it provides a way to define a category under a subsystem for filtering logs specific to that category (https://developer.apple.com/documentation/os/1643744-os_log_create?language=objc). I looked up the Cocoa Lumberjack library but there doesn't seem to be a way to create sub categories. Are there any alternatives we could use with Cocoa Lumberjack library to achieve the same?

It is possible to add the category and a subsytem used in os_log for Cocoa Lumberjack. You can add a subsystem and a category like in this example:
/// Initialization
for category in LoggerCategory.allCases {
let logger = DDOSLogger.init(subsystem: "com.yourname", category: category.rawValue)
logger.logFormatter = CustomLoggingFormatter(category: category)
DDLog.add(logger)
}
enum LoggerCategory: String, CaseIterable {
case test
var index: Int {
return Self.allCases.firstIndex(of: self)!
}
}
/// Custom logging formatter that filters messages by the category that is provided in the context
class CustomLoggingFormatter: NSObject, DDLogFormatter {
let category: LoggerCategory
/// Intializer for custom logger that filters out messages with the provided category
/// - Parameter category: Category that will be filtered (shown for provided category)
init(category: LoggerCategory) {
self.category = category
}
func format(message logMessage: DDLogMessage) -> String? {
guard logMessage.context == category.index else { return nil }
return "\(logMessage.message)"
}
}
// Usage:
DDLogWarn("Your message", context: 1) // context for filter
// Output in console
2020-12-16 16:44:17.899062+0100 App[1234:1234] [test] Your message
Source, see merge request and discussion

Related

Is it possible to get all the struct that conform to a given protocol?

Question
Is it possible to get all the struct that conform to a given protocol?
If so, what are the possible methods?
Details
I want to get all struct that are compliant with PreviewProvider.
And we want to access those _allPreviews.
For example, to get the class that are compliant with an arbitrary protocol, you can use the following method.
import Foundation
class Runtime {
public static func allClasses() -> [AnyClass] {
let numberOfClasses = Int(objc_getClassList(nil, 0))
if numberOfClasses > 0 {
let classesPtr = UnsafeMutablePointer<AnyClass>.allocate(capacity: numberOfClasses)
let autoreleasingClasses = AutoreleasingUnsafeMutablePointer<AnyClass>(classesPtr)
let count = objc_getClassList(autoreleasingClasses, Int32(numberOfClasses))
assert(numberOfClasses == count)
defer { classesPtr.deallocate() }
let classes = (0 ..< numberOfClasses).map { classesPtr[$0] }
return classes
}
return []
}
public static func classes<T>(conformTo: T.Type) -> [AnyClass] {
return self.allClasses().filter { $0 is T }
}
}
[Swift] To retrieve classes at runtime which conforms to a protocol or to retrieve subclasses of a given class
I'm trying to find something that corresponds to the struct of this.
I'm not sure if it's possible at first, but for example Sourcery (Sourcery is a code generator for Swift language, It extends the language abstractions to allow you to generate boilerplate code automatically.) seems to be achieved by writing the following.
{% for type in types.based.PreviewProvider %}
So I think it's possible.
If you have any advice, I would appreciate your comments.

Binding Protocols with Associated Objects - Protocol Oriented Programming with Swift

i'm an iOS dev with a couple of years of experience with swift, but rarely i've used PAT's...
This time, I was trying to move some code from an app that i've developed to a shared library that I use in a couple of projects. The case is about a Factory that uses various Builders (that are decorators of my business resources) via an Abstract Builder protocol, to obtain Items (in the real case, ViewControllers).
The Builder relays upon some variables that the Factory passes to him, but those are at the application level, so, to extract this logic and put it into my library, i need to use a generic reference, and because I want to work in a Protocol Oriented Programming manner, it is an AssociatedType.
// The item that i want to receive from my factory
protocol Item {
var content: String { get }
}
// This is the Builder interface that the Factory consumes
protocol Builder {
// The Abstract Parameters that the Application should define
associatedtype Parameters
func build(_ parameters: Parameters) -> Item?
}
// The BusinessResource of my library
protocol BusinessResource { }
// The Factory that consumes the Builders
protocol Factory {
associatedtype FactoryBuilder: Builder
var parameters: FactoryBuilder.Parameters { get }
func make(from businessResource: BusinessResource) -> Item?
}
// The generic implementation of my Factory
extension Factory {
func make(from businessResource: BusinessResource) -> Item? {
guard let builder = businessResource as? FactoryBuilder else {
return nil
}
return builder.build(self.parameters)
}
}
At this point everything looks good.
I have two protocols and those are binded together, sharing a common type who is generic (the Builder Parameters).
So, on the application layer, now i could introduce my concrete Parameters (i'll call them ConcreteParameters XD)
// The concrete parameters of the Application Factory
struct ConcreteParameters {
let string: String
}
// The Builder interface restricting Parameters to ConcreteParameters
protocol BindedBuilder: Builder where Parameters == ConcreteParameters {
}
// The Factory interface restricting Parameters to ConcreteParameters
protocol BindedFactory: AbstractFactory where FactoryParameters: ConcreteParameters {
}
So far, so good. Everything looks in place and I'm start thinking that this could work, so now i try to implement a concrete Factory on the application to try if this really works.
// The concrete output of my Builder
struct ConcreteItem: Item {
var content: String
}
// The concrete BusinessResource that i get from my library
struct ConcreteObject: BusinessResource {
let string: String
}
// The decoration extension that makes ConcreteObject compliant with Builder
extension ConcreteObject: Builder {
typealias Parameters = ConcreteParameters
func build(_ parameters: ConcreteParameters) -> Item? {
return ConcreteItem(content: parameters.string + self.string)
}
}
// The real Factory inside my app
class ConcreteFactory: BindedFactory {
typealias FactoryBuilder = BindedBuilder
var parameters: ConcreteParameters {
return ConcreteParameters(string: "Hello ")
}
}
let item = ConcreteFactory().make(from: ConcreteObject(string: "world!"))
print(item ?? "NOT WORKING")
At this point something breaks... I get this error:
[EDIT: Error came from a previous version of the snippet, AbstractFactori is current Factory]
It is a Bug??
I really don't know how to solve this...
I think in this case you need to use a concrete type to alias FactoryBuilder instead of BindedBuilder, as protocols do not conform to themselves.
This code effectively compiles, would something like that match your requirements?
class ConcreteFactory: BindedFactory {
typealias FactoryBuilder = ConcreteObject
var parameters: ConcreteParameters {
return ConcreteParameters(string: "Hello ")
}
}
Otherwise you can also try type erasing BindedBuilder and create AnyBindedBuilder, as suggested in the same link.

Building composable objects in Swift with protocols

I'm trying to create a way to build compassable objects in Swift. I feel like I'm almost there with what I have but it's still not 100% correct.
What I'm aiming for is to have a FlowController object that can create our UIViewControllers and then give them any of the dependencies that they need.
What I'd also like to do is make this work as loosely as possible.
I have a small example here that works but is not ideal. I'll explain...
Here are two objects that can be used as components... Wallet and User.
class Wallet {
func topUp(amount: Int) {
print("Top up wallet with £\(amount)")
}
}
class User {
func sayHello() {
Print("Hello, world!")
}
}
We then define a Component enum that has cases for each of these...
enum Component {
case Wallet
case User
}
... And a protocol that defines a method requiresComponents that returns an array of Components.
This is where the problem arises. In order for the "factory object" to put the components into a Composable object we need to define the user and wallet properties in the protocol also.
protocol Composable {
var user: User? {get set}
var wallet: Wallet? {get set}
func requiresComponents() -> [Component]
}
In an attempt to make these properties "optional" (not Optional) I have defined an extension to the Composable protocol that defines these vars as nil.
extension Composable {
var user: User? {
get {return nil}
set {}
}
var wallet: Wallet? {
get {return nil}
set {}
}
}
Now I declare the class that I want to make Composable. As you can see it requires the User component and declares the variable.
class SomeComposableClass: Composable {
var user: User?
func requiresComponents() -> [Component] {
return [.User]
}
}
Now the FlowController that will create these and add the components to them. You can see here that I have had to take the object, create a local var version of it and then return the updated object. I think this is because it doesn't know the type of objects that will be conforming to the protocol so the parameter can't be mutated.
class FlowController {
func addComponents<T: Composable>(toComposableObject object: T) -> T {
var localObject = object
for component in object.requiresComponents() {
switch component {
case .Wallet:
localObject.wallet = Wallet()
print("Wallet")
case .User:
localObject.user = User()
print("User")
}
}
return localObject
}
}
Here I create the objects.
let flowController = FlowController()
let composable = SomeComposableClass()
And here I add the components. In production this would be done all inside the FlowController.
flowController.addComponents(toComposableObject: composable) // prints "User" when adding the user component
compassable.user?.sayHello() // prints "Hello, world!"
As you can see, it works here. The user object is added.
However, as you can also see. Because I have declared the vars in the protocol the composable object also has a reference to a wallet component (although it will always be nil).
composable.wallet // nil
I feel like I'm about 95% of the way there with this but what I'd like to be able to do is improve how the properties are declared. What I'd like is for that last line... composable.wallet to be a compile error.
I could do this by moving the declaration of the properties out of the protocol but then I have the problem of not being able to add the properties to any object that conforms to the Composable protocol.
What would be awesome is for the factory object to be able to add the properties without relying on the declaration. Or even have some sort of guard that says "if this object has a property call user then add the user component to it". Or something like that.
If anyone knows how I could get the other 5% of this working it would be awesome. Like I said, this works, just not in an ideal way.
Thanks :D
Hacky Edit
Hmm... As a quick tacky, horrible, "no-one-should-do-this" edit. I have changed my protocol extension to be like this...
extension Composable {
var user: User? {
get {fatalError("Access user")}
set {fatalError("Set user")}
}
var wallet: Wallet? {
get {fatalError("Access wallet")}
set {fatalError("Set waller")}
}
}
Now at least the program will crash if I try to access a variable I have not defined. But it's still not ideal.
Edit after reading Daniel's blog
OK, I think I've done what I wanted. Just not sure that it's exactly Swifty. Although, I also think it might be. Looking for a second opinion :)
So, my components and protocols have become this...
// these are unchanged
class Wallet {
func topUp(amount: Int) {
print("Top up wallet with £\(amount)")
}
}
// each component gets a protocol
protocol WalletComposing {
var wallet: Wallet? {get set}
}
class User {
func sayHello() {
print("Hello, world!")
}
}
protocol UserComposing {
var user: User? {get set}
}
Now the factory method has changed...
// this is the bit I'm unsure about.
// I now have to check for conformance to each protocol
// and add the components accordingly.
// does this look OK?
func addComponents(toComposableObject object: AnyObject) {
if var localObject = object as? UserComposing {
localObject.user = User()
print("User")
}
if var localObject = object as? WalletComposing {
localObject.wallet = Wallet()
print("Wallet")
}
}
This allows me to do this...
class SomeComposableClass: UserComposing {
var user: User?
}
class OtherClass: UserComposing, WalletComposing {
var user: User?
var wallet: Wallet?
}
let flowController = FlowController()
let composable = SomeComposableClass()
flowController.addComponents(toComposableObject: composable)
composable.user?.sayHello()
composable.wallet?.topUp(amount: 20) // this is now a compile time error which is what I wanted :D
let other = OtherClass()
flowController.addComponents(toComposableObject: other)
other.user?.sayHello()
other.wallet?.topUp(amount: 10)
This seems like a good case for applying the Interface Segregation Principle
Specifically, rather than having a master Composable protocol, have many smaller protocols like UserComposing and WalletComposing. Then your concrete types that wish to compose those various traits, would just list their "requiredComponents" as protocols they conform to, i.e:
class FlowController : UserComposing, WalletComposing
I actually wrote a blog post that talks about this more extensively and gives more detailed examples at http://www.danielhall.io/a-swift-y-approach-to-dependency-injection
UPDATE:
Looking at the updated question and sample code, I would only suggest the following refinement:
Going back to your original design, it might make sense to define a base Composing protocol that requires any conforming class to create storage for composed traits as a dictionary. Something like this:
protocol Composing : class {
var traitDictionary:[String:Any] { get, set }
}
Then, use protocol extensions to add the actual composable trait as a computed property, which reduces the boilerplate of having to create those properties in every conforming class. This way any class can conform to any number of trait protocols without having to declare a specific var for each. Here's a more complete example implementation:
class FlowController {
static func userFor(instance:UserComposing) -> User {
return User()
}
static func walletFor(instance:WalletComposing) -> Wallet {
return Wallet()
}
}
protocol Composing : class {
var traitDictionary:[String:Any] { get, set }
}
protocol UserComposing : Composing {}
extension UserComposing {
var user:User {
get {
if let user = traitDictionary["user"] as? User {
return user
}
else {
let user = FlowController.userFor(self)
traitDictionary["user"] = user
return user
}
}
}
}
protocol WalletComposing {}
extension WalletComposing {
var wallet:Wallet {
get {
if let wallet = traitDictionary["wallet"] as? Wallet {
return wallet
}
else {
let wallet = FlowController.walletFor(self)
traitDictionary["wallet"] = wallet
return wallet
}
}
}
}
class AbstractComposing {
var traitDictionary = [String:Any]()
}
Not only does this get rid of those pesky optionals you have to unwrap everywhere, but it makes the injection of user and wallet implicit and automatic. That means that your classes will already have the right values for those traits even inside their own initializers, no need to explicitly pass each new instance to an instance of FlowController every time.
For example, your last code snippet would now become simply:
class SomeComposableClass: AbstractComposing, UserComposing {} // no need to declare var anymore
class OtherClass: AbstractComposing, UserComposing, WalletComposing {} //no vars here either!
let composable = SomeComposableClass() // No need to instantiate FlowController and pass in this instance
composable.user.sayHello() // No unwrapping the optional, this is guaranteed
composable.wallet.topUp(amount: 20) // this is still a compile time error which is what you wanted :D
let other = OtherClass() // No need to instantiate FlowController and pass in this instance
other.user.sayHello()
other.wallet.topUp(amount: 10) // It all "just works" ;)

How can I allow my function to accepts two different objects in swift?

I have a function which takes one argument. I wanted my function to accept two object types. How can I do it? Here is the example below:
func accept(user: Customer) {
...
}
It should accept Customer and Employee object reference.
accept(objRefCustomer)
accept(objRefEmployee)
Please help me in this case.
Alternative to super-classing: use protocols
You needn't necessarily use a superclass for this case (if Customer and Employee are struct value types; superclass option is not possible), but can rather use the more generic approach of protocols.
Define a protocol Users which blueprints properties and methods for your Customer and Employee instances (if we let Customer and Employee conform to Users, then we promise that instances of these two structures will have accessible the blueprinted properties and methods):
protocol Users {
var name: String { get }
func printTypeOfUser()
}
Define the Customer and Employee structures, and their conformance to the protocol Users:
struct Customer : Users {
let name: String
init(name: String) { self.name = name }
func printTypeOfUser() {
print("Is a Customer!")
}
}
struct Employee : Users {
let name: String
let id: Int
init(name: String, id: Int) { self.name = name; self.id = id }
func printTypeOfUser() {
print("Is an Employee!")
}
}
Now you can define a generic function where its generic, say T, is type constrained to types conforming to the protocol Users, which in this case is equivalent to the Customer or Employee types
func accept<T: Users>(user: T) {
print("Name of user: \(user.name) [\(user.dynamicType)]")
user.printTypeOfUser()
// do something additional employee-specific if user is an employee?
if let employee = user as? Employee {
print("User is an employee with id: \(employee.id)")
}
}
Example usage of this function for Employee as well as Customer instances:
let employee = Employee(name: "John", id: 1)
let customer = Customer(name: "Sarah")
accept(employee) /* Name of user: John [Employee]
Is an Employee!
User is an employee with id: 1 */
accept(customer) /* Name of user: Sarah [Customer]
Is a Customer! */
Instead of changing your Class structure and code base, you can use AnyObject. It will also be easier for you if, for example, in future you have to make this function accept parameters of class WaterMelon. Making all these classes inherit from a common parent class would be unnecessary overhead, not to mention hectic.
AnyObject is swift equivalent of objective c id. AnyObject is a protocol that can represent an instance of any class type.
It also has a more general counterpart, Any, which can represent any type at all (including structs and enums).
Following code will accept any class type parameter you pass:
func accept(sender : AnyObject) { //Or AnyObject? if you want to handle nil as well
...
}
To access properties of the classes you pass as AnyObject, you can use type casting.
For example below code will check sender type and typecast it for you:
if let customerRef = sender as? Customer {
// ...
// Sender is of customer class type. Use it with customerRef that we created
let customerName = customerRef.dynamicType.sampleNameProperty //Access a property of class Customer
customerRef.funcOfCustomerClass() //Call a method of class Customer
}
else{
//Sender is not of customer class type.
//Then it must be Employee??? Handle cases for employee here.
}
create a protocol, and use it as argument type. protocol can be also empty, it will work anyway. Works with struct and class as well;
ex:
protocol SomeFakeProtocol {}
class SomeClass: SomeFakeProtocol { //code here }
struct SomeStruct: SomeFakeProtocol { //code here }
func someFunction(arg: SomeFakeProtocol) { //code here }
Benefits - you can allow to use only types you want to. And, sure, you can do things like this:
extension String: SomeFakeProtocol {}
You can create a super class called People of Cutomer and Employee.
Then set user as type of People:
func accept(user: People) {
...
}
You don't need a super class, you can just pass an object of type AnyObject and in your function check the type of the object passed:
func accept(user: AnyObject) {
if let usr = user as? Person {
...
}
}
But if you have many types you want to pass you may want to make a protocol or a super class.

A static field inherited from the base class or protocol - how?

I want to be able to have the classes which have a static property (field) which is either inherited from the base class or "mixed" from a protocol. And every class should have it's own implementation of that property. Is it possible? Preferably, it to be immutable.
class C1 {
static let stProperty = "my prorepty1"
}
class C2 {
static let stProperty = "my prorepty2"
}
It's possible, but it's really hard to make this useful in Swift. How do you plan to refer to this property? Let's start with a super-simple implementation:
protocol SomeProtocol {
static var prop: String { get }
}
class C1: SomeProtocol {
static let prop = "This is One"
}
Great. So now I want a function that uses this:
func useProp(x: SomeProtocol) -> String {
return x.prop
// 'SomeProtocol' does not have a member named 'prop'
}
That doesn't work. x is an instance, but I want the type.
// Accessing members of protocol type value 'SomeProtocol.Type' is unimplemented
func useProp(x: SomeProtocol.Type) -> String {
return x.prop
}
This is probably how it will work some day given the word "unimplemented." But it doesn't work today.
func useProp(x: SomeProtocol) -> String {
// Accessing members of protocol type value 'SomeProtocol.Type' is unimplemented
return x.dynamicType.prop
}
Same thing.
Today, you really have to hang this on the object itself and not use static or class:
protocol SomeProtocol {
var prop: String { get }
}
class C1: SomeProtocol {
let prop = "This is One"
}
func useProp(x: SomeProtocol) -> String {
return x.prop
}
That's not so terrible in many cases, since the value for the class is probably also the value for any given instance of the class. And it's really all we can do today.
Of course your problem might be that you don't have an instance yet and you need this information to build an instance. That's really hard today and you should probably rethink your design. You'll generally have to use some other pattern like a Builder. See Generic Types Collection for more.
Now you also said:
or "mixed" from a protocol
I wouldn't say "mixed" here. If you really mean this like a Ruby "mixin", there is no such thing in Swift today. Swift folks often refer to this feature as "default implementation," and it's not currently possible (though I do expect it to come eventually). The only thing you can do in the protocol is say that the implementor has to provide this method somehow. You can't provide it for them.
Sure you can do that with a protocol:
protocol SomeProtocol {
static var foo: String { get }
}
class One: SomeProtocol {
class var foo: String {
get {
return "This is One"
}
}
}
Btw I agree with Rob Napier below that this is a bit off a oddball feature. I do think there are probably use-cases for it, but I also think those can be better implemented with other language features
protocol P {
class var stProperty: String { get }
}
class C1 {
class var stProperty: String {
return = "my property1"
}
}
class C2 {
class var stProperty: String {
return = "my property2"
}
}
Usage:
C2.prop //"my property2"
If you try:
C2.prop = "new value" //"cannot assign to the result of this expression"

Resources