Custom UIButton that generates UIView in SuperView - ios

I'm experimenting a custom class button that display the UIView when touch start.
I have a UIButton class name it TapInButton. here're codes.
#import "TapInButton.h"
#import "TapInViewController.h"
#interface TapInButton()
#property (nonatomic,strong) TapInViewController * tapIn;
#end
#implementation TapInButton
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
self.tapIn = [[TapInViewController alloc] initWithNibName:#"TapIn" bundle:nil];
self.tapIn.view.frame = CGRectMake(0, 50, 300, 500);
self.tapIn.view.backgroundColor = [UIColor redColor];
[self.superview addSubview:self.tapIn.view];
}
As you can see, I import TapInViewController that generates xib file.
When the user click the tapin button that has a custom class TapInButton.
It Display the xib file. see image below
I successfully add the xib to the main ViewController but the problem is I cannot click the button inside the xib file. Is there something missing in my code? or Is this possible to generate a uiview inside a custom UIButton?
I know the other way to generate a xib file but not using custom button. I just want to clarify my mind if this is possible. Hoping for your advice or explanation. Thanks in advance

the problem is I connot click the button inside the xib file. Is there something missing in my code?
You'll have to obtain a reference to the button in code and set up the button-click action connection in code (by calling addTarget:action:forControlEvents:).

Related

Connecting a UIScrollView to a UIView class

I'm currently creating a "slide-show" of pictures that the user can scroll through. Following a guide, I made it so that the UIScrollView I am using shows the edges of the previous and next pictures as the user scrolls along. This comes with a side-effect of the user not being able to scroll if he touches on one of the edges of the pictures, because these edges are technically not within the border of the UIScrollView itself. In order to compensate for this, I am going to create a UIView in which I will embed the UIScrollView. The UIVew will be extend the entire width of the page so that the user can scroll when touching the edges of the pictures. To do this, I need to connect the UIScrollView to the code of the UIView through an IBOutlet. Usually this is simply accomplished by Ctrl-clicking on the UIScrollView and dragging to the code. However, this does not seem to work for me and I am stumped as to why.
Here is a screenshot of the environment I am dealing with when I try to ctrl-click on the UIScrollView and drag to the code to create an IBOutlet (it simply doesn't give the option to create anything).
Here is a screenshot of what running the simulator produces. If i try to click and drag where my mouse currently is, it doesn't scroll, which is the problem I am trying to correct.
It is because you should link your storyboard view to UIView class. You can choose your ScrollViewController class in custom class settings. I added the sample jpg
what you are looking for is not that 'easy' by just connecting the two.
There are two options:
1) In the future you should use a UICollectionView and implement the paging behaviour yourself, that is the cleanest code I think.
NEVER MIND THE SECOND OPTION - I DIDN'T SEE YOU ACTUALLY ALREADY USED THIS
2) To directly answer your question:
You have to subclass the UIView that contains the UIScrollView like this:
header:
#import <UIKit/UIKit.h>
#interface SCTouchForwardView : UIView
#property (nonatomic, weak) IBOutlet UIView* receiver;
#property (nonatomic, assign) BOOL force;
#end
Implementation:
#import "SCTouchForwardView.h"
#implementation SCTouchForwardView
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
UIView* result = [super hitTest:point withEvent:event];
if (![result isKindOfClass:[SCTouchForwardView class]]) {
return result;
}
if (result==self) {
UIView *result = [self.receiver hitTest:[self convertPoint:point toView:self.receiver] withEvent:event];
if (result) {
return result;
}else{
if (self.force) {
return self.receiver;
}
return nil;
}
}
return nil;
}
#end
When you want to use this, you just have to Right-Click-Drag from the container to the UIScrollview and select 'receiver' and what you tried to do will work!

Showing the same UIBarButtonItem on many views

I have a problem in my iOS application that I'm looking for some help with. I'm relatively new to iOS programming to I'm sure that there is some relatively simple solution to my problem.
First, I'm going to explain the hierarchy of the application:
It uses a UITabBarController to show a couple of different screens.
It uses a SWRevealViewController to show a sidebar
The sidebar is accessed from a Bar button item that is present in the Navigation bar of the application.
That the application uses SWRevealViewController https://github.com/John-Lluch/SWRevealViewController doesn't directly affect the problem that I have. If you are not familiar with this code base, just think of a Simple Bar Button that is shown at all times.
Now to the problem:
The Bar button that I want to show is associated with a few lines of code. (A property declaration and some methods).
This code should be used on a major part of the different view controllers in the application.
Now in the normal case, I'd just subclass UIViewController and make it the superclass of all my views that should show this button. However, my application should also show other types of views, such as a UITableViewController, so subclassing doesn't solve the entire problem.
If Objective-C supported Multiple Inheritance, I would make a class containing this code and let my other classes extend any subclass of UIViewController and my ugly support class at the same time.
Notes:
For now, my app is based on Storyboards
The TabBarController points to a number of UINavigationControllers, and not to any views that doesn't have a Navigation Bar.
I have tried implementing this with Objective-c Category where I add a category to UIViewController that does setup of my UIViewController. But I got stuck on this solution when I needed to add a #Property for the button and linking it to the XIB/Storyboard. Got the idea from this post Add the same UIBarButtonItem to several UIViewControllers but it doesn't contain any details.
tl;dr: I want to show the very same UIBarButtonItem on many of my applications views. The UIBarButtonItem is associated with some code, that is also the same for all these views.
What would be a good way to achieve this?
If i understood you correctly.
You want to show button for all your UIViewControllers.
There are many ways to achieve this. Please try this one.
1. Create a subclass of UIView with its XIB. It contains your button. create Properties and IBAction.
2. Implement your action on this subclass.
3. On .m file write the below code
- (id)awakeAfterUsingCoder:(NSCoder *)aDecoder
{
if (![self.subviews count])
{
NSBundle *mainBundle = [NSBundle mainBundle];
NSArray *loadedViews = [mainBundle loadNibNamed:#"MyView" owner:nil options:nil];
return [loadedViews firstObject];
}
return self;
}
where, MyView is the name of your view.
4. Drag and drop a UIViewand place it on every `UIViewController XIB (or storyboard in your case) and set its custom class to "MyView" (or the name of your newly created class).
5. Run your project.
For reference: May i help you?
I have now solved this problem and I will post it here for reference:
This solves the problem with adding a sidebar button to several views in the project, but the code should be usable for any UIBarButton. The solution is the create a Category for UIViewController that specifies a setup method. This setup method is called from the different Views.
Category .h file:
#import <UIKit/UIKit.h>
#interface UIViewController (SidebarCompliance)
- (void)setupSidebar;
#end
Category .m file:
#import "UIViewController+SidebarCompliance.h"
#import "SWRevealViewController.h"
#implementation UIViewController (SidebarCompliance)
- (void)setupSidebar {
SWRevealViewController *revealViewController = self.revealViewController;
if (revealViewController) {
UIBarButtonItem *sidebarButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:#"menu.png"] landscapeImagePhone:[UIImage imageNamed:#"menu.png"] style:UIBarButtonItemStylePlain target:self.revealViewController action:#selector(revealToggle:)];
self.navigationItem.rightBarButtonItem = sidebarButton;
[self.view addGestureRecognizer:self.revealViewController.panGestureRecognizer];
}
}
#end
And then an example of one of my views:
View .h file:
#import <UIKit/UIKit.h>
#import "UIViewController+SidebarCompliance.h"
#interface NumeroUno : UIViewController
#end
View .m file:
#import "NumeroUno.h"
#implementation NumeroUno
- (void)viewDidLoad {
[super viewDidLoad];
[self setupSidebar];
}
#end

Create A New iOS Control

I am trying to create a new control for Xcode to implement into a new iOS app. The end idea is to display the formation of a football squad graphically. I realise that this could all be coded programmatically but I want to create a new control to represent a player and then load the formation accordingly as I may add other player information to the control in the future.
I have created a xib view file, in which is a label for displaying their name. I have tried the following but the label's text doesn't show up. Am I missing something obvious?
[I have included the correct headers and have connected the label up and set the xib to the new class]
header file for xib:
#interface playerObject : UIControl
#property (nonatomic, strong) NSString *playerNameLabel;
#end
implementation file for xib:
#import "playerObject.h"
#interface playerObject ()
#property (strong, nonatomic) IBOutlet UILabel *nameLabel;
#end
#implementation playerObject
- (void) setPlayerNameLabel:(NSString *)playerNameLabel
{
self.nameLabel.text = playerNameLabel;
}
View Controller Implementation File:
- (void)viewDidLoad
{
...
playerObject *newPlayer = [[playerObject alloc] initWithFrame:CGRectMake(10, 10, 100, 150)];
[newPlayer setPlayerNameLabel:#"TEST"];
[newPlayer setBackgroundColor:[UIColor redColor]];
[self.view addSubview:newPlayer];
}
Thanks in advance!
You may have created a xib file containing a label however you do not appear to be using it. You are creating a new instance of the playerObject class instead of loading one from a xib file. Take a look at the UINib class documentation instead.
You are instantiating your custom view without loading it from the .xib file.
In order to make it work, follow these steps:
Make your playerObject inherit from UIView instead of UIControl.
Open your .xib file.
Select the root view on the left pane.
On the right pane, switch to the Identity Inspector tab.
Type playerObject into the first text field "Class".
Make sure that you connected all your IBOutlets within Interface Builder.
Do the following to load your custom UIView from the .xib file:
playerObject *newPlayer = (playerObject *)[[[NSBundle mainBundle] loadNibNamed:#"MyXibFilename" owner:nil options:nil] firstObject];
newPlayer.playerNameLabel = #"Lionel Messi";
Note aside: I strongly recommend you to start using "namespaces" for your classes (it's just a two-letter prefix), such as XXPlayerObject, with XX being something else you consider describes your app / module. All other related custom classes should "share" this namespace. Look at what Apple does with its classes.
I hope this helps you!

Handling touches within UIScrollview

I have a view that contains a UIScrollView. The UIScrollView contains an UIImageView (only one for now but there will be more latter). I want to be able to drag the UIImageView out of the UIScrollView and into the superview.
I have reviewed every similar question and example I can find online and still cant get my head around how this works.
At first I couldn't get touches to register all whithin the scrollview. After a lot of searching I have found a way to get touchesbegan to register as follows:
First I created a new view based project and in the auto-created "ViewController.h"
I created an IBOutlet named slider.
Then in the auto-created "ViewController.m" I created the UIScrollview.
In IB I added a UIScrollView to the storyboard then connected it to the "slider" IBOutlet.
Next I added class file to the projects. This new class is a subclass os UIImageView. I named this class "DragableImage" In the
Then in IB I dropped an image into the UIScrollview clicked on it and changed the class to "DragableImage"
In the DragableImage.m I voided touches began and simply told it to become hidden if clicked.
This works and the touch registers and makes the image disappear but how do I now add the new image to the main view and have it follow my finger?
This is what I have in the way of code:
ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController {
IBOutlet UIScrollView *slider;
}
#end
ViewController.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[slider setScrollEnabled:YES];
[slider setContentSize:CGSizeMake(306, 1560)];
[slider setShowsVerticalScrollIndicator:NO];
slider.canCancelContentTouches = NO;
slider.delaysContentTouches = NO;
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation)interfaceOrientation
{
return YES;
}
#end
DragableImage.h
#import <UIKit/UIKit.h>
#interface DragableImage : UIImageView
#end
DragableImage.m
#implementation DragableImage
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
self.hidden = YES;
}
#end
How to make this work?
There is one obvious problem that can arise here. Namely, how to tell the difference between dragging to scroll and dragging an image. The way I would handle this is to setup a tap and hold gesture recognizer (http://developer.apple.com/library/ios/#documentation/EventHandling/Conceptual/EventHandlingiPhoneOS/GestureRecognizers/GestureRecognizers.html).
Once you detect a hold you could set it up so that further touches/gestures get routed to you drag and drop code. You can find a nice tutorial for that here:
http://www.ancientprogramming.com/2012/04/05/drag-and-drop-between-multiple-uiviews-in-ios/

Dynamically Add a UIView to another

I am new to IOS, Xcode and MVC. I am on a steep learning curve and am failing with what I assume is a most basic task.
I have a tabbed application with two tabs. Both tab views communicate with a web service and I want to add an image to each tab view, changing the image to indicate the connection state.
So, I created a third .xib file with a controller class (IconViewController). I am hoping to add and remove an instance of this icon view in each of the tab views.
Here is the pseudo code for my icon view:
#interface IconViewController : UIViewController
{
UIImageView *_icon;
}
#property (nonatomic) IBOutlet UIImageView *icon;
- (void)setForBusy;
- (void)setForOk;
- (void)setForFail;
And implementation:
#implementation IconViewController
#synthesize icon = _icon;
-(void)setForBusy
{
// Set Busy Icon Image
}
-(void)setForOk
{
// Set Ok Icon Image
}
-(void)setForFail
{
// Set Fail Icon Image
}
The icon IBOutlet is connected to an UIImageView on the accompanying xib file.
Here is one of the root tab controllers:
#import "IconViewController.h"
#interface TaboneViewController : UIViewController
{
IconViewController *_iconViewController;
}
#property (nonatomic) IBOutlet IconViewController *iconViewController;
and implementation:
#synthesize iconViewController = _iconViewController;
- (void)viewDidLoad
{
[super viewDidLoad];
self.iconViewController = [[IconViewController alloc]
initWithNibName:#"iconViewController"
bundle:nil];
[self.view addSubview:self.iconViewController.view];
}
In the tabView xib Interface Builder I added an Object and made it a class type IconViewController. I connected the Icon View Controller Object->Reference Outlet to the File Owner->iconViewController Outlet.
Running the project I get the error:
loaded the "iconViewController" nib but the view outlet was not set.
I have experimented with other connections but with no luck. It seems to me that my first connection should work but it doesn't.
Any idea what I am misunderstanding? Is the principle good (loading an instance of third view into two root views)? If so, what outlet needs connecting?
Many thanks, Polly
I see your issue. You want to have common stage of image for both tab. I think it is better to implement subclass of UIView (or UIImageView) and implement all methods like set (void)setForBusy and etc. The stage of image you should receive from parent ViewController, something like UINavigationView controller (if you have it). Otherwise you should save stage somewhere else. My personal opinion it is too expensive to create new controller just for your purpose.
Hope it helps.

Resources