I am wanting to show a simple loading dialog when certain things are happening in my app. I figured I would just create a new view, add a label to that, and then set that view to a subView of my current view.
When doing this, I don't see anything!
Here is how I am writing my method:
- (void)showLoading {
UIView *loading = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
loading.backgroundColor = [UIColor blackColor];
UILabel *txt = [[UILabel alloc] initWithFrame:CGRectMake(198, 9, 94, 27)];
txt.text = #"Loading...";
txt.textColor = [UIColor whiteColor];
[loading addSubview:txt];
[super.view addSubview:loading];
[super.view bringSubviewToFront:loading];
[loading release];
[txt release];
}
Am I doing this completely wrong?
EDIT:
I added it to the viewDidLoad method, and it works how I want:
loading = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 200, 200)];
loading.backgroundColor = [UIColor blackColor];
UILabel *txt = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 94, 27)];
txt.text = #"Loading...";
txt.textColor = [UIColor whiteColor];
[loading addSubview:txt];
[txt release];
[self.view addSubview:loading];
[self.view bringSubviewToFront:loading];
But when loading it from a method, it seems to lag, and not show up for a bit.
Although this doesn't directly answer your question, I'd recommend grabbing MBProgressHUD from GitHub and using that in place of a static label. Looks better, less code for you to directly maintain, etc. You can find it at http://github.com/matej/MBProgressHUD
The way I use it is by creating a subclass of UITableViewController and defining a handful of methods to show and hide the HUD view. From there, I call each relevant method when I'm loading or done loading.
Specifically, I have four methods: -hudView, -showLoadingUI, -showLoadingUIWithText:, and -hideLoadingUI.
-hudView creates a new MBProgressHUD object if one doesn't already exist, and adds it to the current view ([self.view addSubview:hudView]).
-showLoadingUI calls -showLoadingUIWithText: with a default title, -showLoadingUIWithText: just unhides the MBProgressHUD and sets a label value for it (self.hudView.labelText = #"foo";).
-hideLoadingUI hides the hudView ([self.hudView hide:YES]).
First, I don't think UIView has method called init. You may just call the super of it. The appropriate method you should call is - (id)initWithFrame:(CGRect)aRect . The frame is the position, the size of the View you want to display. More here
Another thing is why you call [super.view addSubView:], I think it should be self.view, isn't it?
Related
I'm having a strange issue when it comes to adding content to a UIScrollView.
Below are the results for the same method getting called. The one on the left is the result of the call from viewDidLoad. The one one the right is called from a custom method which fires when the label is touched.
The code is pretty straight forward:
CGRect scrollRect = CGRectMake(0, 64, 320, [[UIScreen mainScreen] bounds].size.height - 49);
_containerView = [[UIScrollView alloc] initWithFrame:scrollRect];
_containerView.backgroundColor = [UIColor clearColor];
UILabel *myLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 5, 300, 40)];
myLabel.text = #"my label";
myLabel.textColor = [super colorFromHexString:0x472C37];
myLabel.numberOfLines = 0;
[myLabel sizeToFit];
y_offset += myLabel.frame.size.height;
[_containerView addSubview:myLabel];
[self.view addSubView:_containerView];
I've checked the parent (self.view) and its coordinates are always 0,0. Really stumped by this...
In viewDidLoad your subViews components are not totally initialized yet, so if you are using the frame of some of them you will get an undesired result. viewDidLayoutSubviews is probably what you are looking for. This is the method where all the subviews frames are completly initialized.
Try to call your code inside this method and you should get the same result as the one when clicking in the button.
-(void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
[self setupView];
}
I have a UIModalTransitionStylePartialCurl which is acting funky. My views UILabel and UIButton animate as if the labels frame is being changed all the time.
In iOS 4 or 6 it works statically. I've made a video of the bug on youtube.
I found an answer to this problem, but I don't quite understand the implementation. I alloc and init all of my elements in viewDidLoad, so where exactly is [self layoutIfNeeded]; going to help?
My code, if relevant is as follows (refactored):
- (void)viewDidLoad
{
[super viewDidLoad];
// Label
textLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 120, 280, 40)];
textLabel.text = #"Change password";
[self.view addSubview: textLabel];
// old password
oldPassword = [[UITextField alloc] initWithFrame: CGRectMake(20, 180, 280, 40)];
oldPassword.secureTextEntry = YES;
oldPassword.placeholder = #"Current Password";
oldPassword.returnKeyType = UIReturnKeyNext;
oldPassword.autocapitalizationType = UITextAutocapitalizationTypeNone;
oldPassword.delegate = self;
[self.view addSubview: oldPassword];
// New password
CGRect chosenPasswordFrame = oldPassword.frame;
chosenPasswordFrame.origin.y += 40;
chosenPassword = [[CustomTextField alloc] initWithFrame: chosenPasswordFrame];
chosenPassword.secureTextEntry = YES;
chosenPassword.placeholder = #"New Password";
chosenPassword.returnKeyType = UIReturnKeyGo;
chosenPassword.autocapitalizationType = UITextAutocapitalizationTypeNone;
chosenPassword.delegate = self;
[self.view addSubview: chosenPassword];
// Submit button
submitButton = [[UIButton alloc] initWithFrame:CGRectMake(20, chosenPasswordFrame.origin.y + chosenPasswordFrame.size.height + 20, self.view.frame.size.width - 40, 45)];
[submitButton setTitle:#"Submit" forState:UIControlStateNormal];
[submitButton addTarget:self action:#selector(changePassword) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview: submitButton];
self.view.backgroundColor = [UIColor colorWithPatternImage:[[AppTheme sharedTheme] changePasswordBackgroundImage]];
}
It looks like the setting of your view's frames is getting caught in the CATransaction being created by the partial page curl animation and being animated. Since the frames should never have been CGRectZero at least in the code you posted, this does seem to be a bug in iOS 5. Especially based on the number of up-votes that the answer you linked has received. And that answer describes the problem well.
Essentially, if you force the new view to lay itself out immediately by calling [self layoutIfNeeded] it forces the view system to realize that these are the current frame values not the ones to be animated to. And then even if this bug still tries to animate it's a non-op. Animating from frame A to frame A is at the very worst imperceptible. And since the "buggy" animation would finish at the same time as the curl animation it really (in practice) doesn't matter to you. With the exception of an inexplicable call to layoutIfNeeded in viewDidLoad.
I have an application with navigation controller and some table view controller. In table view controller I have a two section header my definitions:
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
if (section == 0) {
UIView* customView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, tableView.bounds.size.width, 74)];
UIImageView *myImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"toolbarTopBack.png"]];
UILabel *headline = [[UILabel alloc] initWithFrame:CGRectMake(11, 14, 305, 21)];
headline.backgroundColor = [UIColor clearColor];
headline.textColor = [UIColor whiteColor];
headline.font = [UIFont fontWithName:#"Helvetica Neue" size:21];
headline.text = searchPosition;
UILabel *subHeadline = [[UILabel alloc] initWithFrame:CGRectMake(11, 36, 305, 21)];
subHeadline.backgroundColor = [UIColor clearColor];
subHeadline.textColor = [UIColor grayColor];
subHeadline.font = [UIFont fontWithName:#"Helvetica Neue" size:16];
subHeadline.text = searchRegion;
[customView addSubview:myImageView];
[customView addSubview:headline];
[customView addSubview:subHeadline];
return customView;
} else {
// create the parent view that will hold header Label
UIView *customView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, tableView.bounds.size.width, 44)];
customView.userInteractionEnabled = YES;
UIImageView *myImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"mainToolBar.png"]];
UIToolbar *topToolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, tableView.bounds.size.width, 44)];
topToolbar.barStyle = UIBarStyleDefault;
[topToolbar setBackgroundColor:[UIColor clearColor]];
static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{
NSMutableDictionary *appSettingsData = [[NSMutableDictionary alloc] initWithDictionary:[appDelegate getAppStrings]];
NSArray *segmentItems = [NSArray arrayWithObjects:[NSString stringWithFormat:#"%# (%d)", [appSettingsData valueForKey:#"segmentButton4"], listCountOffers], [NSString stringWithFormat:#"%# (%d)", [appSettingsData valueForKey:#"segmentButton5"], [[appDelegate comunication] getSimilarCount:[appDelegate getCurrentCI] idPosition:idPosition idRegion:idRegion]], nil];
segmentControl = [[UISegmentedControl alloc] initWithItems:segmentItems];
segmentControl.frame = CGRectMake(6, 8, 308, 29);
segmentControl.autoresizingMask = UIViewAutoresizingFlexibleWidth;
segmentControl.segmentedControlStyle = UISegmentedControlStyleBar;
[segmentControl setTintColor:[UIColor grayColor]];
[segmentControl addTarget:self action:#selector(segmentedControlIndexChanged:) forControlEvents:UIControlEventValueChanged];
segmentControl.momentary = NO;
segmentControl.selectedSegmentIndex = 0;
});
UIBarButtonItem *toolbarItem = [[UIBarButtonItem alloc] initWithCustomView:segmentControl];
[topToolbar addSubview:toolbarItem.customView];
[customView addSubview:myImageView];
[customView addSubview:topToolbar];
return customView;
}
}
I use "static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{", because I need create this header only first time (because when I scroll table, method is call and call ... and this is wrong) ...
Everything works fine, when I create table view controller it show a headers, when I scroll it, nothing is recreating (it is fine), but when I push back button a then reopen tableview controller headers are empty. Where is problem ? Is there any solution, how to fix it ? Thanks a lot
Well, to me it looks like it's a problem with your static dispatch.
When you push the Back button, chances are that your view holding the table view is released (I don't know your code, but I suppose it is like that), meaning all internal variables are gone - except your static dispatch, which won't be called the next time you instantiate the view. So, during the next instantiation your segmentItems will not be created, but because the view was released, they are empty. You should solve your 'only create once' problem differently, e.g. by remembering the created segmentItems in a dictionary and getting them from there if they do not exist yet.
You're using dispatch_once without really needing to. The block will only be executed once, even if you subsequently remove the view controller from memory and deallocate segmentControl.
Use lazy loading instead - create a property for your segmentControl view within your view controller, and in the accessor for that, if the backing ivar is nil, create it then:
Your synthesize statement:
#synthesize segmentControl = _segmentControl
Your accessor method:
-(UISegmentedControl*)segmentControl
{
if (_segmentControl)
return _segmentControl;
UISegmentedControl *segmentControl = //... create your control here
self.segmentControl = segmentControl
return segmentControl;
}
Then when you want to use the view, use self.segmentControl. The first time you call it, it will be created, the subsequent times, it will be re-used.
check it with breakpoint and see the process. it maybe the memory allocation problem. See this it may help you. http://www.icodeblog.com/2010/12/10/implementing-uitableview-sections-from-an-nsarray-of-nsdictionary-objects/
I have a 320x460 view with a number of buttons, depending on the button pressed, a 280x280 view pops up over the 320x460 view (similar to the behavior of the UIAlertView) using code like this:
UIView *overlayView = [[UIView alloc] initWithFrame:CGRectMake(20, 200, 280, 280)];
overlayView.backgroundColor = [UIColor whiteColor];
[overlayView autorelease];
[overlayView addSubview:label]; // label declared elsewhere
[overlayView addSubview:backgroundImage]; // backgroundImage declared elsewhere
//... Add a bunch of other controls
[label release];
[backgroundImage release];
//... Release a bunch of other controls
[self.view addSubview:overlayView];
Everything works fine displaying the overlayView and all its controls.
The question I have is, how do I get rid of the overlayView once it's displayed? I want to make it not only not visible but to remove it completely, since the user will be popping up the overlayView repeatedly during use.
You need access to overlayView to remove it, I'd suggest adding this to the create side:
overlayView.tag = 5; // Or some other non-zero number
Then later you can use it like this:
-(void)removeOverlayView
{
UIView *overlayView = [self.view viewWithTag:5];
[overlayView removeFromSuperview];
}
In a model UIViewController I have the following implementation of loadView (everything is created programmatically):
- (void)loadView {
// Add Basic View
UIView *myView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 540, 620)];
myView.backgroundColor = [UIColor clearColor];
self.view = myView;
[myView release];
// Add NavigationBar
// Add a BG image
// Add Table
UITableView *tbView = [[UITableView alloc] initWithFrame:CGRectMake(30, 80, 480, 250) style:UITableViewStyleGrouped];
tbView.dataSource = self;
tbView.delegate = self;
tbView.scrollEnabled = NO;
tbView.backgroundColor = [UIColor clearColor];
[tbView reloadData];
[self.view addSubview:tbView];
[tbView release];
// some more code
}
As you can see I set backgroundColor to clearColor, yet when I compile and run the code I always see a gray background behind the table:
I don't understand what I am doing wrong (sounds stupid, I know), I used to have the very same code and it worked perfectly fine. I am compiling with iOS SDK 4.2.1
You also need to set your UITableView's backgroundView property to nil on recent (since 3.2) versions of iOS.
As such, adding...
tbView.backgroundView = nil;
...should sort your problems.
That said, if you want to maintain compatibilty with pre-3.2 devices, you should check for the existence of this via the instancesRespondToSelector method before calling it.
Make sure you have the following 3 options set:
tbView.opaque = NO;
tbView.backgroundColor = [UIColor clearColor];
tbView.backgroundView = nil;
try
tbView.backgroundView = nil;
I tried to change from storyboard.
It works fine in
tbView.backgroundColor = .white