self.customView.backgroundColor assignment causes leak? - ios

I'm working with creating my own custom view templates programmatically for the app I'm working on. To achieve this i have a custom view controller MyVC with a a custom view myView added on to it which is a property of MyVC. The class looks something like this:
MyVC.h
#import <UIKit/UIKit.h>
#interface MyVC : UIViewController{
MyCustomView *myView;
}
#property(nonatomic, retain) MyCustomView *myView
#end
In the implementation i want to assign a background color to 'myView' and i do something like this in the viewDidLoad (after synthesizing my property of corse)
-(void)viewDidLoad{
self.myView = [[MyCustomView alloc] initWithFrame:someFrame];
self.myView.backgroundColor = [UIColor clearColor];
}
Now when i analyze my code i get a 'potential leak of an object' message when i assign the color. Is it because myView or the background color or both are being retained?
In any case id like to know how this can be done correctly without potential leaks?

If you don't using ARC you should release over retained property:
-(void)viewDidLoad{
//allocate and initialize myView
self.myView = [[[MyCustomView alloc] initWithFrame:someFrame] autorelease];
self.myView.backgroundColor = [UIColor clearColor];
}

Related

Custom UIView doesnt show

I have very simple UIView that creating the box, but what is happen is the UIView does not show at all, here is my code on sharingButtons.m
-(void)createContainer{
winWidth = [UIScreen mainScreen].bounds.size.width;
buttonContainer = [[UIView alloc] initWithFrame:CGRectMake(0, 0, winWidth, 20)];
buttonContainer.backgroundColor = [UIColor redColor];
[self.view addSubview:buttonContainer];
}
-(void)createButton{
[self createContainer];
}
and here is my sharingButtons.h
#interface SocialSharing : UIViewController {
int winWidth;
}
- (void)createButton;
- (void)createContainer;
#pragma mark - Properties
#property(nonatomic, strong) UIView* buttonContainer;
#end
And createButton method is called from MyViewControler.m on viewDidLoad
Is any wrong with my code??
EDITED
Here is my code on MyViewControler.m
- (void)loadSocialSharingButton {
socialButtons = [[SocialSharing alloc] init];
[socialButtons createButton];
}
- (void)viewDidLoad {
[super viewDidLoad];
[self loadSocialSharingButton];
}
Sorry I just learn about obj c :)
Thanks a lot
The reason your buttonContainer is not visible is, it is not loaded in your view hierarchy.
To make it visible you should add it as subview. In MyViewController.m in viewDidLoad add the following line after [self loadSocialSharingButton];
[self.view addSubview:socialButtons.buttonContainer];
Hope this Helps!
Your SocialSharing is subclass of UIViewController.
And you add your buttonContainer view to this SocialSharing Controller,this controller is not on screen if you just call
socialButtons = [[SocialSharing alloc] init];
[socialButtons createButton];
So,you can not see anything.
In an iOS App, only one ViewController at a time is active. And as you are at MyViewController, so MyViewController is active, if you want to navigate to any other view controller than you need to present or push the instance of same. Doing so will make the other view controller as active.
In your case the problem is your SocialSharing is a subclass of UIViewController as it is created as SocialSharing : UIViewController and it's not active, so adding any view over it won't be visible as the instance of SocialSharing is not pushed/ presented. If you need to show the view from SocialSharing than either you subclass it from UIView or push/ present the instance of SocialSharing to make it's view active and visible.
You are currently # MyViewController and But you are loading your custom view # SocialSharing ViewController, Both ViewController are distinct and you can't just get your custom view at social sharing to MyViewController by initializing it.
You have change SocialSharing class as sub class of UIView and initialize this view and add to subview of MyViewController.
SocialSharing.h
#interface SocialSharing : UIView {
int winWidth;
}
- (instancetype)createButton;
#pragma mark - Properties
#property(nonatomic, strong) UIView* buttonContainer;
#end
SocialSharing.m
- (instancetype)createButton
{
winWidth = [UIScreen mainScreen].bounds.size.width;
self = [super initWithFrame:CGRectMake(0, 0, winWidth, 20)];
if (self) {
buttonContainer = [[UIView alloc] initWithFrame:];
buttonContainer.backgroundColor = [UIColor redColor];
[self addSubview:buttonContainer];
}
return self;
}
MyViewController.m
- (void)viewDidLoad {
[super viewDidLoad];
[self loadSocialSharingButton];
}
- (void)loadSocialSharingButton {
socialButtons = [SocialSharing alloc] createButton];
[self.view addSubView:socialButtons];
}

Initialize custom UIView before drawRect gets called

I need to customize a UIView by calling its drawRect method, so I subclass UIView and name it MyView. The drawing will depend on some variable(myString in this example), so I need to initialize the variable before drawRect starts. My MyView.h looks like
#interface MyView : UIView
#property (strong, nonatomic) NSString *myString;
#end
In the viewController.m, if I do the following
MyView *myView = [MyView alloc] initWithFrame:someRect];
[myView setMyString:#"string value"];
[self.view addSubview:myView];
everything works as expected, the myString is set before drawRect get called.
The problem I am trying to solve is if I want to add the MyView to the view controller by using Interface Builder(drag and drop an UIView to the view controller's view and change its class to MyView), where is the point that I can set myString before drawRect gets called?
set it in your view controller
-(void) viewDidLoad {
MyView *myView = self.view;
[myView setMyString:#"string value"];
]

Is it okay to store a casted reference (to my subclass of UIView) in my UIViewController?

Are there any dangers in storing a casted reference to MyView in my subclass of UIViewController? I am trying to avoid casting self.view every time I want to use an instance variable/method because it looks ugly. For example, let's avoid:
[((MyView *)self.view) instancedView]
castedView is defined at the same time as self.view
castedView.instancedView is a subview of castedView stored as an instance variable (a UIButton that I want to attach a tap event listener to, for example)
MyViewController.h
#interface MyViewController : UIViewController
#property MyView *castedView;
#end
MyViewController.m
#implementation MyViewController
#synthesize castedView;
- (void)viewDidLoad {
[super viewDidLoad];
castedView = [[MyView alloc] init];
self.view = castedView;
// ... create gestureRecognizer named "onTap" that calls "whenTapped" ...
[castedView.instancedView addGestureRecognizer:onTap];
}
- (IBAction)whenTapped {
castedView.instancedView.backgroundColor = [UIColor whiteColor];
}
#end
Any help is appreciated.

iOS5 adding and manipulting a UIView class

I have create a UIVeiw class and a .xib. Within this .xib view I have its set to freeform with the dimensions of 400x200 and I have assigned it to my custom class with the same name:
Storyboard: blogView
Class Files: blogView.h & blogView.m
Within in the .xib i have added a label and a text field and linked them up to variable within the .h files etc (See code below).
blogCont.h
#import <UIKit/UIKit.h>
#interface blogCont : UIView
#property (strong, nonatomic) IBOutlet UILabel *lbBlogDate;
#property (strong, nonatomic) IBOutlet UITextView *txtBlogTitle;
#end
blogCont.m
#import "newsStoryView.h"
#implementation blogCont
#synthesize lbBlogDate;
#synthesize txtBlogTitle;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code place a log to see if it loads
NSLog(#"View Loaded");
}
return self;
}
#end
Now with in my main viewController.m file i have added the following code to init this view class, and I have added a background colour to see if this loads in.
viewController.m
UIView *blogCont = [[blogView alloc] init];
blogCont.backgroundColor = [UIColor purpleColor];
[subview addSubview:blogCont];
Now when I run this it all works well but as I do not see the purple background it looks as if the view does not load, but within the log I do see the NSLog message I have within this view NSLog(#"View Loaded"); so it seems it initiating this, but I cannot for the life of me get this to display?
Now if I change the code slightly to my main View Controller.m fiel to:
CGRect blogFrame;
blogFrame.origin.x = 20;
blogFrame.origin.y = 20;
blogFrame.size = CGRectMake(400,200);;
newsStoryView *blogCont = [[blogView alloc] blogFrame];
blogCont.backgroundColor = [UIColor purpleColor];
[subview addSubview:blogCont];
Then I get my view display a nice purple box, so this shows up when I set a frame size and the init the view with it 'blogFrame', bu tI thought that all this would be set within the .xib settings so no need to do this?
SO how can I create this external view class and assign it into another view and then manipulate its data, as accessing the label in the .xib using blogCont.lbBlogDate.text does not seem to work that is it probably does but as I cannot view it i cannot confirm it.
What am i doing wrong?
Thanks
Seems I nearly answered my own question then did:
I was not setting the size within my separate class view I was asking for a size when init it:
- (id)initWithFrame:(CGRect)frame
this is asking for a size
so I could do the following to the above:
- (id)init
{
self = [super initWithFrame:CGRectMake(0, 0, 478, 220)];
.... rest of code
Setting the size within the view load.
But I could also set it when I init it in my main view controller as below:
newsStoryView *blogCont = [[blogView alloc] initWithFrame:CGRectMake(0, 0, 400, 200)];
This is better as I can control the position of each one. Hope this helps anyone

Send a Delegate message from UIPopover to Main UIViewController

I'm trying to use a Button in my UIPopover to create a UITextView in my Main UIViewController the code I have looks something like this (PopoverView.h file):
#protocol PopoverDelegate <NSObject>
- (void)buttonAPressed;
#end
#interface PopoverView : UIViewController <UITextViewDelegate> { //<UITextViewDelegate>
id <PopoverDelegate> delegate;
BOOL sendDelegateMessages;
}
#property (nonatomic, retain) id delegate;
#property (nonatomic) BOOL sendDelegateMessages;
#end
Then in my PopoverView.m file:
- (void)viewDidLoad
{
[super viewDidLoad];
UIButton * addTB1 = [UIButton buttonWithType:UIButtonTypeRoundedRect];
addTB1.frame = CGRectMake(0, 0, 100, 50);
[addTB1 setTitle:#"Textbox One" forState:UIControlStateNormal];
[self.view addSubview:addTB1]; // Do any additional setup after loading the view from its nib.
[addTB1 addTarget:self action:#selector(buttonAPressed)
forControlEvents:UIControlEventTouchUpInside];
}
- (void)buttonAPressed
{
NSLog(#"tapped button one");
if (sendDelegateMessages)
[delegate buttonAPressed];
}
And also in my MainViewController.m :
- (void)buttonAPressed {
NSLog(#"Button Pressed");
UITextView *textfield = [[UITextView alloc] init];
textfield.frame = CGRectMake(50, 30, 100, 100);
textfield.backgroundColor = [UIColor blueColor];
[self.view addSubview:textfield];
}
I'm using a delegate protocol to link the popover and the ViewController but I'm stuck on how I get my BOOL statement to link the -(void)buttonAPressed in the PopoverView and MainViewController so that when I press the button in the Popover a textview appears in the Main VC. How would I go about doing this?
In MainViewController, where you create PopoverView, be sure to set its delegate property otherwise sending messages to delegate in PopoverView will do nothing.
For example, in MainViewController.m:
PopoverView *pov = [[PopoverView alloc] initWithNibName:nil bundle:nil];
pov.delegate = self; // <-- must set this
thePopoverController = [[UIPopoverController alloc] initWithContent...
I am not sure why you need the sendDelegateMessages variable. Even with that bool, you must set the delegate property so PopoverView has an actual object reference to send the messages to.
If you want to make sure the delegate object has implemented the method you're about to call, you can do this instead:
if ([delegate respondsToSelector:#selector(buttonAPressed)])
[delegate buttonAPressed];
Also, the delegate property should be declared using assign (or weak if using ARC) instead of retain (see Why use weak pointer for delegation? for an explanation):
#property (nonatomic, assign) id<PopoverDelegate> delegate;
Another thing is if you're not using ARC, you need to add [textfield release]; at the end of the buttonAPressed method in MainViewController to avoid a memory leak.

Resources