How to create a proxy protocol like UIAppearance - iphone

I know how to create a protocol already but I'm wondering what would be the best practice to create a proxy protocol like Apple did for the UIAppearance protocol and the implementation on certain UI classes.
Why I want to do it this way? Because I already have a lot of UI classes and I would like to centralize the implementation of the code for changing color.
Maybe an odd question but my curiosity drove me to this point.
Thanks

Just make the proxy a static object and access it through class-level methods, the same way you'd implement a singleton, e.g.
#implementation MyClass
+ (MyProxyObject *)proxy
{
static MyProxyObject *sharedProxy = nil;
if (sharedProxy == nil)
{
sharedProxy = [[MyProxyObject alloc] init];
}
return sharedProxy;
}
#end
Then for any property of your class, e.g. textColor, just have your class use the value in [[self class] proxy].textColor instead of storing its own value. E.g.
#interface MyClass : UIView
#property (nonatomic, strong) textColor
#end
#implementation MyClass
- (UIColor *)textColor
{
return textColor ?: [[self class] proxy].textColor
}
#end
If you need a way to refresh your onscreen views immediately whenever a property on the proxy is changed, you could do that by having the proxy broadcast an NSNotification in its textColor setter method, and have all the instances observe that notification and call setNeedsDisplay on themselves when they receive it.

Related

Swift alternative to this Obj-C pattern using #dynamic?

In Obj-C, I sometimes used the dynamic keyword in controllers to make working with their custom views more convenient. In this example, I wouldn't need to typecast self.view every time I wanted to access a property or call a function:
// MyServiceController.m
#dynamic view;
-(void)loadView
{
self.view = MyServiceView()
self.view.delegate = self;
}
-(void)someFunc
{
[self.view doSomething];
}
// MyServiceView.h
#property(nonatomic, strong)id<MyServiceViewDelegate> delegate;
-(void)doSomething;
Is there a way to achieve this with pure swift?

How can I create a custom property in theos/logos?

Would it be possible to create a custom property in a hooked method using theos/logos?
example:
//define my custom property
#interface SBAwayController : NSObject {
UIView *myCustomView;
}
#property (nonatomic, retain) UIView *myCustomView;
#end
%hook SBAwayController
- (void)activate {
//call original method
%orig;
//use my custom property
if (tweakEnabled)
[self.awayView addSubview:myCustomView];
}
%end
I've tried it as exampled above, but no success.
An alternative is to create a singleton class that will hold your object/context. Take this example from this Introspy hook class. tracerStorage is a variable defined outside the class and all hooks access it.
To apply it to your case, you can have an external variable NSMutableDictionary with the current SBAwayController as key and the property myCustomView as value.

ARC: Will setting self as a class member's delegate stop self from ever being freed?

Here's a pseudo class to demonstrate:
myView : UIView
- (void) init {
UIScrollView * scroller = [[UIScrollView alloc] init];
scroller.delegate = self;
[myView addSubview:scroller];
return self;
}
Under ARC, do I need to do anything else for memory to be freed correctly when all other references to myView have been removed? Will the reference between the two objects keep them sticking around forever without any intervention?
Does this change depending on whether or not scroller is a class property, or just a local variable declared in the function?
Just trying to find out why I've got multiple instances of some classes sticking around that shouldn't be there - semi related question, is there an easy way to find out why an object stays in memory (eg see all references to this object)?
iOS classes (like UIScrollView and UIWebView) already handle this correctly.
However, if you have your own delegate protocols and delegate properties, you need to make sure they are set to assign and not retain. To do this, wherever you declare a delegate (or whatever kind of protocol) you need to add the __unsafe_unretained tag thing:
#protocol FooBarDelegate {
//...
}
#interface Foo : Bar {
__unsafe_unretained id <FooBarDelegate> delegate;
}
#property (nonatomic, assign) id <FooBarDelegate> delegate;
Does this change depending on whether or not scroller is a class
property, or just a local variable declared in the function?
It doesn't. However keep in mind that adding something as a subview, the parent view will retain it automatically, regardless if you have a property or not.

UIView drawRect Method with options

I want to create an UIView Class that you can initialise with several options.
I think the problem is the drawRect() method. Is it possible to initialise the class with a certain option like
[[MyUIView alloc]initWithColor:[UIColor blueColor]]
I read that I should never call the drawRect() method without initialising an object.
So how can I realize the statement above without calling it manually?
What I have tried so far:
I thought that I could just initialize the View and then call Method
[MyView changeColorTo:green]
which tries to redraw the View however I couldn't get that to work.
Maybe it's important that I draw with coreGraphics (with a certain color, which should be selectable) a rounded rectangle in the drawRect() method.
How can I implement my desired behaviour?
call
[self setNeedsDisplayInRect:aCGRect];
that calls drawRect: for you.
Edit on the color property:
#interface MyView: UIView
#property (nonatomic, strong) UIColor *drawColor;
#end
#implementation MyView
#synthesize drawColor;
- (id)initWithWhatever
{
self.drawColor = [UIColor infraRedColor];
[self setNeedsDisplayInRect:aRect];
}
- (void)drawRect:(CGRect)r
{
// use self.drawColor
}
#end

Difference between using properties and not for accessing ivars

Specific performance and behaviour difference using properties or accessing the ivars directly.
For Global variables, What is the difference between using this:
#interface myClass (){
UIImageView *myView;
}
-(void)loadView{
[super loadView];
myView = [[UIImageView alloc] initWithFrame:CGrectMake(0,0,100,100)];
}
And doing this:
#interface myClass (){
}
#property (nonatomic, strong) UIImageView *myView;
#synthesize myView = _myView;
-(void)loadView{
[super loadView];
myView = [[UIImageView alloc] initWithFrame:CGrectMake(0,0,100,100)];
}
What benefits can we have with every approach?
What are the reasons to recommend to always uses properties?
In the first case, your instance variable (or ivar) myView is private to the class and cannot be accessed by another class.
In the second case, you have provided a property that allows other classes to access your ivar via synthesized accessors. The alternative to declared properties is to write your own accessor methods. The #synthesize notation does that for you.
See Apple documentation on declared properties
ALWAYS create a #property for every data member and use self.name to access it throughout your class implementation.
NEVER access your own data members directly.
Here are some of the reasons to use Properties:
Properties enforce access restrictions (such as readonly)
Properties enforce memory management policy (retain, assign)
Properties are (rarely) used as part of a thread safety strategy (atomic)
Properties provide the opportunity to transparently implement custom setters and getters.
Having a single way to access instance variables increases code readability.
You can also check out: The Code Commandments: Best Practices for Objective-C Coding
Synthesize makes you getter and setter methods which are called automatically depending on whether you try read or write the value. For the myView property:
myView = newView1; // using direct ivar access
myobject.myView = newvew1; // eq [myobject setMyView:newvew1]; where setMyView: is generated for you automatically with respect to assign/retain, the same for reading:
newvew1 = myobject.myView; // newvew1 = [myobject myView:newvew1];
the generated getter/setter names are customizable with setter=/getter=, if you don't need setter use readonly.
There's no way you can forbid other classes to use synthesized getter and setter, the ivars are #protected by default and if you want to provide other classes an access to the ivars, you can declare them under #public:
#interface myClass (){
UIImageView *myView; // this is protected
#public
UIImageView *myPublicView; // this is public
}
In your first example you access your ivar directly and changing its content. In your second example (the property) an ivar has been created automatically to back the property and all your calls to set and get the property are sent as messages (like: [self setMyView:[[UIImageView alloc] initWithFrame:CGrectMake(0,0,100,100)]];). The accessor methods are also created automatically. This means that you are now following KVC/KVO protocols. For more on the benefits of this design see here