Snapkit: Constrain multiple to margins - swift

I'm using Snapkit to simplify my autolayout code, however one scenario seems to popup very regularly, which i'm wondering if there's a way which involves less code.
So let's say that I need to pin the edges of a UIView to it's superview margins, we might do something like this:
subView.snp.makeConstraints { make in
make.top.equalTo(parentView.snp.topMargin)
make.bottom.equalTo(parentView.snp.bottomMargin)
make.left.equalTo(parentView.snp.leftMargin)
make.right.equalTo(parentView.snp.rightMargin)
}
This essentially results in the subview filling the parent view, except for a small amount of padding as defined by the parent views layout margins.I'm sure some variation of this is pretty common.
This seems overly verbose for this library. It has some really nice helper methods such as these
make.edges.equalToSuperview()
make.top.left.right.equalToSuperview()
What I haven't managed to find in their documentation however is how to do the two above helper methods, in relation to the margins.
What i'm looking for (if it exists) is something akin to:
make.edges.equalToSuperview().withMargins()
make.top.left.right.equalToSuperview().withMargins()
make.top.left.right.equalTo(someview).withMargins()
So, is there a way of doing this other than the very verbose way? Am I missing something in the documentation or maybe this could be added by extension?

did you try something like this?
subView.snp.makeConstraints { make in
make.edges.equalTo(view.snp.margins)
}
Edit after comment:
When you only want to constrain certain edges to the superview margin, you can do something like this.
subView.snp.makeConstraints { make in
make.top.leading.equalTo(view).inset(view.layoutMargins)
}
or
subView.snp.makeConstraints { make in
make.top.leading.equalTo(view.layoutMarginsGuide)
or
subView.snp.makeConstraints { make in
make.top.leading.equalTo(view.safeAreaLayoutGuide)

One nice way to do this is to use UIView.layoutMarginsGuide:
childView.snp.makeConstraints { make in
make.top.leading.bottom.equalTo(parentView.layoutMarginsGuide)
make.trailing.equalTo(otherView.snp.leading).offset(-8.0)
}

Related

Is there a reliable way of overriding CellClass in classes derived from NSControl?

This question seems to have been asked several times, but I have yet to find an definitive answer. I'm totally aware of the fact that NSCell is "being gradually phased out". This is great (and long overdue!), but it doesn't help in the here and now. Suppose I want to create a subclass of NSImageView which (e.g.) clips an image with an arbitraily shaped mask. I might define it like this:
class MaskedImageView : NSImageView {
public override class var cellClass: AnyClass? {
get { MaskedImageCell.self }
set {}
}
MaskedImageCell, of course, inherits from NSImageCell. This code compiles just fine under Swift 5.x, but the cell class is never changed. Adding the statement super.cellClass = newValue to the above property setter likewise makes no difference. (In fact, this isn't how the underlying AppKit machinery establishes the cell class. If I add a print statement inside the property getter, I can see that AppKit is interrogating the cell class, as I'd expect, but it never uses it.)
Like I said, I'm aware that NSCell is on the way out. But there are surely multiple use cases where it would be useful to change the cellclass to add specifics required by a particular application. If this isn't possible NOW, then is one supposed to try and replicate the entire functionality of (eg) NSImageCell. I surely wouldn't want to do that!
All constructive comments gratefully received. And please do bear in mind that I'm not actually interested in adding weird-shaped masks to NSImageViews. 😄 What I'm after is a definitive solution to the problem of introducing one's own cell class into the mix. We were told 7 years ago that NSCell was being deprecated, but while it's still with us, we should have a mechanism for introducing custom cell classes.

Is it possible to reference constants in code from storyboard in Swift?

I have constants in my code, for example:
let cellHeight = 44
I don't know how to reference those constants from code in the storyboard. For example, in the storyboard, there are multiple section headers of a tableview:
I would like to control all of their heights with a constant, so if I decide to change the height, I don't have to change every storyboard value. I would like to replace those numbers with constant names.
I did some research, and couldn't find anything. I don't know if this is possible, but is it?
P.S. I know that I can just connect the UI to the code, and set the height in viewDidLoad(), but I want to use this way.
There is no simple way, because a storyboard is not code — there is nothing there that can "see" your variable cellHeight.
However, what you are asking to do is something you should not want to do. If you have sizes that need to be adjusted depending on the screen size, or views that need to be adjusted when some other view changes, that is what auto layout is for.
Otherwise, you will just have to write code that changes all the things you want changed when you want them changed.

Destroy UIView in init if condition isn't met

I'm trying to make a custom alert view that checks to see if a condition is true, and if so it builds itself and attaches itself to the window. However, if this condition is not true, I just want the view to deallocate itself, preferably in the init method. What is the best way to accomplish this?
Well it is better to follow SOLID principles in coding.
Singularity is an important thing.One function is supposed to do a single thing not many dependencies.
So Keep the view just to show the custom alert.And the check for showing must be done outside such that
//Please note this is the algorithm not the exact code in Obj-C.
if(condition==True)
{
//Display customView
}
else
{
//Do nothing
}

iPhone scrollView add elements dynamically with id

I want to populate a scrollView with quite a few different UI elements.
Therefore I thought I would write a method that remembers the current Position in the scrollView and just adds the element to the scrollView at the current Position.
Something like:
- (void)addUIElement:(id)element withWidth:(CGFloat)width andHeight:(CGFloat)height andYGap:(CGFloat)YGap {
element.frame = CGRectMake(currentScrollPos.x, (currentScrollPos.y + YGap), width, height);
[scrolly addSubview:element];
//And then set the current scroll position here
}
Unfortunately when I try to do access element.frame = ..., I get request for member in something not a structure or union. When I try to do [element frame] = ... Lvalue required as left operand of assignment.
Now, first of all I am not sure what's the best way to dynamically add objects to a scrollview. Maybe anyone has a better or easier approach.
Then on the other hand, I don't get why the above does not work?! Would I have to cast my element to the actual class? I thought I would not have to do so... Also then my method would not make that much sense anymore. Or at least would require some more steps...
This should work I think:
[element setFrame:...];
However if you work with different UI elements in your method may be you can make your elements parameter UIView* instead of id? This way your code will work for all UIView subclasses (which is what you actually need I suppose)
The difference is that "id" doesn't have any kind of reference to a frame. It could be anything. You want to instead do (UIView *)element in the method declaration, or alternatively in the call to element.frame, you would do ((UIView *)element).frame.
(And yeah, all things that you put on the screen are inheriting from UIView -- UIButton, UIImageView, etc.)

need multiple inheritance in Objective C

I want to implement a movable UIView class (view moves when you touch on it and move your finger), e.g.:
#interface MovableView : UIView {
some members;
}
-touchesBegan;
-touchesMoved;
#end
How can I apply this code to UILabel, UIButton etc without multiple inheritance? In C++, I'd do it like this (with UIView as a virtual base to MovableView):
struct MovableLabel : UILabel, MovableView {};
Categories are offered as an alternative to multiple inheritance but I definitely don't want to extent UIView using categories because that would apply to all views in my application. I only want some of my views to be movable.
My current strategy to avoid code duplication is putting MovableView code in a header file and including it everytime I need some class to use it. Besides that I have to add members of MovableView to whatever class I am writing. It is pure code ugliness but better than copy/pasting code all over my project.
Does anyone have any other ideas to get around this Objective C limitation [of not having multiple inheritance]?
Thanks,
Altan
Objective-C won't let you do this mixin inheritance thing, except by adding the same category to each of the classes you care to augment. And then, you won't get extra instance variables.
For your specific problem, I might approach it by designing MovableView as a container class that was just an object that has a child view (UILabel, UIButton, etc) that you want to move as its subview.
Categories would not help anyway because replacing the real touchesBegan method on UIButton would be pretty bad... you can't call [super] from a category.
Another solution would be to inject a method into those class definitions with something like:
Method origMethod = class_getClassMethod([UIButton class], #selector(touchesBegan));
Method newMethod = class_getClassMethod([TemplateClass class], #selector(replacementTouchesBegan));
method_exchangeImplementations(origMethod, newMethod);
But that's pretty fiddly. Although if it's really where you want to go, it's worth looking into...
What I would do is make a MovableView class that inherits from UIView, and simply add whatever you want movable as a subview of that view (which I think might be slightly different than what quixoto was saying, my apologies if not). It gets to respond to touches first and passes along whatever it doesn't need to the next responder... no need to build up a special class with a single subview. Then in IB you can just place these movable views wherever and put things inside of them.
In general compositional techniques like this are very handy across UIKit rather than modifying core classes.