adding CAlayer with frame displays at wrong position - ios

I'm trying to add a rectangle view to my camera preview layer. I tried in 2 ways by UIView and by CALayer. In both cases the frame value is same, but they both end up at different positions .
The one black border is CALayer (featureLayer) and light background is the UIView (_cardHolder).
In viewWillAppear:
CALayer *featureLayer = [[CALayer alloc]init];
featureLayer.borderWidth=3;
featureLayer.backgroundColor=[[UIColor orangeColor]CGColor];
featureLayer.opacity = 0.5;
featureLayer.position = CGPointMake(0, 0);
[featureLayer setFrame:self.cardHolder.frame];
[self.videoPreviewLayer addSublayer:featureLayer];
(lldb) po featureLayer <CALayer:0x1c4423b20; position = CGPoint (160 283.5); bounds = CGRect (0 0; 288 181); allowsGroupOpacity = YES; opacity =
0.5; backgroundColor = <CGColor 0x1c40b1d00> [<CGColorSpace 0x1c00bb120> (kCGColorSpaceICCBased; kCGColorSpaceModelRGB; sRGB IEC61966-2.1; extended range)] ( 1 0.5 0 1 ); borderWidth = 3>
(lldb) po featureLayer.frame
(origin = (x = 16, y = 193), size = (width = 288, height = 181))
(lldb) po self.cardHolder <UIView: 0x123dcbc50; frame = (16 193; 288 181); autoresize = RM+BM; layer = <CALayer: 0x1c043eb40>>
(lldb) po self.videoPreviewLayer <AVCaptureVideoPreviewLayer:0x1c0623ae0; position = CGPoint (187.5
333.5); bounds = CGRect (0 0; 375 667); sublayers = (<CALayer: 0x1c0623800>, <CALayer: 0x1c4423b20>); masksToBounds = YES; allowsGroupOpacity = YES; inheritsTiming = NO; >
Am I missing something ?

The problem with placing code in a method other than viewDidAppear/viewDidLayoutSubviews is that the real frame is not yet rendered , so it should be like this but keep in mind to wrap it inside an once bool as this method is called multiple times
-(void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
if(once)
{
once = No;
CALayer *featureLayer = [[CALayer alloc]init];
featureLayer.borderWidth=3;
featureLayer.backgroundColor=[[UIColor orangeColor]CGColor];
featureLayer.opacity = 0.5;
featureLayer.position = CGPointMake(0, 0);
[featureLayer setFrame:self.cardHolder.frame];
[self.videoPreviewLayer addSublayer:featureLayer]
}
}

Related

How to get rid of `UIStackView` magnificationFilter iPad warning?

I have very simple UIStackView with several buttons. Every time I run the app on an iPad I get this warning:
<CATransformLayer: 0x147563bc0> - changing property magnificationFilter in transform-only layer, will have no effect
The CATransformLayer in question
(lldb) po 0x147563bc0
<CATransformLayer:0x147563bc0; position = CGPoint (358 160); bounds = CGRect (0 0; 100 316); delegate = <eyeq.RightOverlayButtonStack: 0x147528390; baseClass = UIStackView; frame = (308 2; 100 316); layer = <CATransformLayer: 0x147563bc0>>; sublayers = (<CALayer: 0x147527de0>, <CALayer: 0x14753cbc0>, <CALayer: 0x147544500>, <CALayer: 0x147546870>, <CALayer: 0x147548a70>); allowsGroupOpacity = YES; opacity = 1; magnificationFilter = nearest>
belongs to the UIStackView
(lldb) po 0x147528390
<xxx.RightOverlayButtonStack: 0x147528390; baseClass = UIStackView; frame = (308 2; 100 316); layer = <CATransformLayer: 0x147563bc0>>
How to get rid of this warning? BTW, I use Xcode 8 and Swift 3.

why when I taped on third tabbaritem, third tabbaritem and fourth item exchange their position?

I customed a UITabBar. Add a button to center of UITabBar. tabbar have 4 tabbaritems and a button. But when I tap on the third tabbaritem, its position changed to the fourth item's position. Third tabbaritem and fourth item exchange their position.
I set a breakpoint debugging. I found when I taped on third babbaritem tabBar called layoutSubviews(), but when I tap on the other three tabbaritems, tabbar didn't call layoutSubviews(). I don't konw why. Anybody can help me?
I upload the code. add tag to every UITabBarButton. then use tag multiply width. But it has a new problem. the third item become the first item.
Here is the fixed custom UITarbar.
class YNNJTTabBar: UITabBar {
override func awakeFromNib() {
super.awakeFromNib()
self.addSubview(askQuestionButton)
addTagToUITarBarButton()
}
func addTagToUITarBarButton() {
var index = 0
for view in self.subviews {
if view is UIControl && !(view is UIButton) {
view.tag = index
index += (index == 1) ? 2 : 1
}
}
}
override func layoutSubviews() {
super.layoutSubviews()
let width = self.bounds.width / CGFloat(buttonCount)
let height = self.bounds.height
let frame = CGRect(x: 0, y: 0, width: width, height: height)
//set askQuestionButton's frame
let buttonFrame = CGRect(x: 0, y: 0, width: width - 12, height: height - 12)
askQuestionButton.frame = buttonFrame
askQuestionButton.center = CGPoint(x: self.bounds.width * 0.5, y: self.bounds.height * 0.5)
//set 4 item's frame
for view in self.subviews {
if view is UIControl && !(view is UIButton) {
print(view.tag)
view.frame = CGRectOffset(frame, width * CGFloat(view.tag), 0)
}
}
print(self.subviews as NSArray)
}
private let buttonCount = 5
let askQuestionButton: UIButton = {
let tempView = UIButton()
tempView.setBackgroundImage(UIImage(named: "askQuestionbtn"), forState: .Normal)
tempView.setTitle("问", forState: .Normal)
tempView.titleLabel?.font = UIFont.systemFontOfSize(22)
return tempView
}()
}
Here is print information, when app launched
0
1
3
4
(
"<_UITabBarBackgroundView: 0x7fe47bc0d580; frame = (0 0; 320 49); autoresize = W; userInteractionEnabled = NO; layer = <CALayer: 0x7fe47bc02740>>",
"<UITabBarButton: 0x7fe47bccb060; frame = (0 0; 64 49); opaque = NO; layer = <CALayer: 0x7fe47bca51f0>>",
"<UITabBarButton: 0x7fe47bccc9e0; frame = (64 0; 64 49); opaque = NO; tag = 1; layer = <CALayer: 0x7fe47bcccf80>>",
"<UITabBarButton: 0x7fe47bccea80; frame = (192 0; 64 49); opaque = NO; tag = 3; layer = <CALayer: 0x7fe47bccf020>>",
"<UITabBarButton: 0x7fe47bcd0ad0; frame = (256 0; 64 49); opaque = NO; tag = 4; layer = <CALayer: 0x7fe47bcd1050>>",
"<UIButton: 0x7fe47bcca690; frame = (134 6; 52 37); opaque = NO; layer = <CALayer: 0x7fe47bca3980>>",
"<UIImageView: 0x7fe47bc22b80; frame = (0 -0.5; 320 0.5); autoresize = W; userInteractionEnabled = NO; layer = <CALayer: 0x7fe47bc07b80>>"
)
when I tap on third item
0
1
4
0
(
"<_UITabBarBackgroundView: 0x7fe47bc0d580; frame = (0 0; 320 49); autoresize = W; userInteractionEnabled = NO; layer = <CALayer: 0x7fe47bc02740>>",
"<UITabBarButton: 0x7fe47bccb060; frame = (0 0; 64 49); opaque = NO; layer = <CALayer: 0x7fe47bca51f0>>",
"<UITabBarButton: 0x7fe47bccc9e0; frame = (64 0; 64 49); opaque = NO; tag = 1; layer = <CALayer: 0x7fe47bcccf80>>",
"<UITabBarButton: 0x7fe47bcd0ad0; frame = (256 0; 64 49); opaque = NO; tag = 4; layer = <CALayer: 0x7fe47bcd1050>>",
"<UIButton: 0x7fe47bcca690; frame = (134 6; 52 37); opaque = NO; layer = <CALayer: 0x7fe47bca3980>>",
"<UIImageView: 0x7fe47bc22b80; frame = (0 -0.5; 320 0.5); autoresize = W; userInteractionEnabled = NO; layer = <CALayer: 0x7fe47bc07b80>>",
"<UITabBarButton: 0x7fe47bcd0150; frame = (0 0; 64 49); opaque = NO; layer = <CALayer: 0x7fe47bcb8f10>>"
)
If 'self.subviews' returning items not in correct order,
Set tag for each tab item.
The tag values will be 0(for search), 1 (for contact), 3 and 4 (for settings)
And inside the for loop change like:
if view is UIControl && !(view is UIButton) {
view.frame = CGRectOffset(frame, view.tag * width, 0)
}
I think your code here basically won't cause the problem, so I guess the cause comes from other code, so checkout other code or show us more code to help you. just like:
button creation code
button click action code
and so on

What is this firstObject of my custom UIScrollview?

I have a custom UIScrollView, and I add 5 imageView as its subviews.However, after I log its subviews array , it has 6 children!! I use storyboard to add the scrollview add drag its IBOutlet. I have no idea where the firstObject come from?
- (void)configViews {
NSInteger launchImageCount = 5;
CGFloat screenWidth = CGRectGetWidth([UIScreen mainScreen].bounds);
CGFloat screenHeight = CGRectGetHeight([UIScreen mainScreen].bounds);
self.scrollView.contentSize = CGSizeMake(screenWidth * launchImageCount, screenHeight);
self.scrollView.clipsToBounds =YES;
self.scrollView.pagingEnabled = YES;
self.scrollView.delegate = self;
self.scrollView.showsHorizontalScrollIndicator = NO;
for(int i = 0; i < launchImageCount; i++) {
NSString *imageName = [NSString stringWithFormat:#"B0%lu.jpg",(long)(i+1)];
CGRect rect = CGRectMake(screenWidth*i, 0, screenWidth, screenHeight);
UIImageView *imageView = [[UIImageView alloc] initWithFrame:rect];
imageView.image = [UIImage imageNamed:imageName];
[self.scrollView addSubview:imageView];
}
NSLog(#"subviews :%#",self.scrollView.subviews);
self.pageControl.numberOfPages = launchImageCount;
}
Log:
2015-09-26 17:24:29.626 CustomTableView[60621:7911319] subviews :(
"<UIImageView: 0x7f9680f30760; frame = (234.5 118; 2.5 7); alpha = 0; opaque = NO; autoresize = LM; userInteractionEnabled = NO; layer = <CALayer: 0x7f9680f2f6c0>>",
"<UIImageView: 0x7f9680e25a30; frame = (0 0; 375 667); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x7f9680e19290>>",
"<UIImageView: 0x7f9680d5ab30; frame = (375 0; 375 667); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x7f9680d5a7b0>>",
"<UIImageView: 0x7f9680e26af0; frame = (750 0; 375 667); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x7f9680e26280>>",
"<UIImageView: 0x7f9680e2a450; frame = (1125 0; 375 667); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x7f9680e2a1b0>>",
"<UIImageView: 0x7f9680e2e1b0; frame = (1500 0; 375 667); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x7f9680e2df90>>"
)
The UIScrollView has two default UIImageView to show you your scroll bars.
You probably enabled a horizontal/vertical scroll indicator, and that is the reason you see this extra UIImageView child.

CALayer: archiving then unarchiving data does not match original object

I have a UIButton with a UITextView as it's subview. The UITextView has 1 layer which the border is colored and has a width of 1. When I archive the UIButton then unarchive it, the border color and the border width becomes nil. If I set the layer background color, it will stay the same when archived then unarchived, which makes this bug very confusing.
UIButton textButton = ...
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:textButton];
UIButton *textButton2 = [NSKeyedUnarchiver unarchiveObjectWithData:data];
The lldb debug output shows that the border color disappears
(lldb) po [[[textButton subviews] firstObject] layer] <CALayer:0x13445780; position = CGPoint (150 50); bounds = CGRect (0 0; 300 100); delegate = <UITextView: 0xdb20000; frame = (0 0; 300 100); text = ''; clipsToBounds = YES; autoresize = RM+BM; userInteractionEnabled = NO; gestureRecognizers = <NSArray: 0x13446430>; layer = <CALayer: 0x13445780>; contentOffset: {0, 0}>; sublayers = (<_UITextTiledLayer: 0x13448e80>, <CALayer: 0x13445d90>); masksToBounds = YES; allowsGroupOpacity = YES; borderColor = <CGColor 0xc09b6d0> [<CGColorSpace 0xbf28210> (kCGColorSpaceDeviceRGB)] ( 0.378437 0.5 0.13035 1 ); backgroundColor = <CGColor 0xbed1e10> [<CGColorSpace 0xbe65e70> (kCGColorSpaceDeviceGray)] ( 0 0 ); borderWidth = 1>
(lldb) po [[[textButton2 subviews] firstObject] layer] <CALayer:0x13443fe0; position = CGPoint (150 50); bounds = CGRect (0 0; 300 100); delegate = <UITextView: 0xdb2aa00; frame = (0 0; 300 100); text = ''; clipsToBounds = YES; autoresize = RM+BM; userInteractionEnabled = NO; gestureRecognizers = <NSArray: 0x13432ed0>; layer = <CALayer: 0x13443fe0>; contentOffset: {0, 0}>; sublayers = (<_UITextTiledLayer: 0x134447f0>, <CALayer: 0x13434740>); masksToBounds = YES; allowsGroupOpacity = YES; backgroundColor = <CGColor 0xbed1e10> [<CGColorSpace 0xbe65e70> (kCGColorSpaceDeviceGray)] ( 0 0 )>
Is there something special about the border color? Or is this really a bug?

isKindOfClass grab tag

I just want to grab the button tag 1~ 5 in ScrollView, other data do not need to grasp
(void)layoutScrollImages
{
UIImageView *view = nil;
NSArray *subviews = [weekscroll subviews];
CGFloat curXLoc = 0;
for (view in subviews)
{
if ([view isKindOfClass:[UIImageView class]] && view.tag > 0)
{
NSLog(#"%d",view.tag);
CGRect frame = view.frame;
frame.origin = CGPointMake(curXLoc, 0);
view.frame = frame;
curXLoc += (wScrollObjWidth);
}
}
NSLog(#"subviews = %#",subviews);
[weekscroll setContentSize:CGSizeMake((wNumImages * wScrollObjWidth), [weekscroll bounds].size.height)];
}
subviews = (
"<UIImageView: 0x1ba330; frame = (313 61; 7 5); alpha = 0; opaque = NO; autoresize = TM; userInteractionEnabled = NO; layer = <CALayer: 0x1bac00>>",
"<UIImageView: 0x1bc900; frame = (315 59; 5 7); alpha = 0; opaque = NO; autoresize = LM; userInteractionEnabled = NO; layer = <CALayer: 0x1bdde0>>",
"<UIButton: 0x1bd380; frame = (0 1; 50 66); opaque = NO; layer = <CALayer: 0x1bd410>>",
"<UIButton: 0x1bd690; frame = (50 0; 50 66); opaque = NO; layer = <CALayer: 0x1bd720>>",
"<UIButton: 0x1bd9a0; frame = (100 0; 50 66); opaque = NO; layer = <CALayer: 0x1bda30>>",
"<UIButton: 0x1bc570; frame = (150 0; 50 66); opaque = NO; layer = <CALayer: 0x1bc600>>",
"<UIButton: 0x1beaa0; frame = (300 0; 50 66); opaque = NO; tag = 1; layer = <CALayer: 0x1beb30>>",
"<UIButton: 0x1bff40; frame = (350 0; 50 66); opaque = NO; tag = 2; layer = <CALayer: 0x1c0920>>",
"<UIButton: 0x1c0e60; frame = (400 0; 50 66); opaque = NO; tag = 3; layer = <CALayer: 0x1c0ef0>>",
"<UIButton: 0x1c1430; frame = (450 0; 50 66); opaque = NO; tag = 4; layer = <CALayer: 0x1c14c0>>",
"<UIButton: 0x1c1a00; frame = (500 0; 50 66); opaque = NO; tag = 5; layer = <CALayer: 0x1c1a90>>",
"<UIButton: 0x1cb340; frame = (1800 0; 50 66); opaque = NO; layer = <CALayer: 0x1cb3d0>>",
"
)UIImageView: 0x1ba330; frame = (313 61; 7 5); alpha = 0; opaque = NO; autoresize = TM; userInteractionEnabled = NO; layer =
As per printed log, only UIButtons are having tags and in sample code you are working on UIImageView, so use given code as per your requirement.
I have modified your code as below, just check it out.
for (id objView in subviews)
{
if ([objView isKindOfClass:[UIImageView class]])
{
UIImageView *imgView = (UIImageView*) objView;
if (imgView.tag > 0)
{
NSLog(#"%d",imgView.tag);
CGRect frame = imgView.frame;
frame.origin = CGPointMake(curXLoc, 0);
imgView.frame = frame;
curXLoc += (wScrollObjWidth);
}
}
}
Or if you want to grab only UIButtons,
for (UIButton *btnView in subviews)
{
if ([btnView isKindOfClass:[UIButton class]] && btnView.tag > 0)
{
NSLog(#"%d",btnView.tag);
CGRect frame = btnView.frame;
frame.origin = CGPointMake(curXLoc, 0);
btnView.frame = frame;
curXLoc += (wScrollObjWidth);
}
}
You want the button with tags greater than 0 right.. then why are you checking for [UIImageView class].. ?
your condition to find Buttons with tag greater than 0 should be :
if ([aView isKindOfClass:[UIButton class] && (aView.tag > 0)]) {
}

Resources