I'm having a problem with trying to change the colour of my navigation controller inside my popoverController.
I'm trying to do something like this:
if (self.popoverController == nil) {
ArtistsViewController *artistsViewController =
[[ArtistsViewController alloc]
initWithNibName:#"ArtistsViewController"
bundle:[NSBundle mainBundle]];
artistsViewController.navigationItem.title = #"Artists";
UINavigationController *navController =
[[UINavigationController alloc]
initWithRootViewController:artistsViewController];
UIPopoverController *popover =
[[UIPopoverController alloc]
initWithContentViewController:artistsViewController.navigationController];
artistsViewController.navigationController.navigationBar.tintColor=[UIColor greenColor];
popover.delegate = self;
[artistsViewController release];
[navController release];
self.popoverController = popover;
[popover release];
}
[self.popoverController
presentPopoverFromBarButtonItem:sender
permittedArrowDirections:UIPopoverArrowDirectionAny
animated:YES];
but it doesn't work. any suggestions?
////////////////////////////////////////
////////////**SOLUTION**////////
////////////////////////////////////////
I'm gonna edit this post because i solved my problem and I think could be helpful share my solution here:
first of all, follow this sample:
http://mobiforge.com/designing/story/using-popoverview-ipad-app-development
When It is done go to step two.
The second step will be add a new popoverBackgroundViewClass:
Add new file in your project Objective class and call it 'CustomPopoverBackgroundView'
///////////////////////////////////////////////
////// CustomPopoverBackgroundView.h /////////
///////////////////////////////////////////////
#import < UIKit/UIKit.h >
#import < UIKit/UIPopoverBackgroundView.h >
#interface CustomPopoverBackgroundView : UIPopoverBackgroundView{
UIPopoverArrowDirection direction;
CGFloat offset;
}
#end
//////////////////////////////////////////////
////// CustomPopoverBackgroundView.m /////////
//////////////////////////////////////////////
#import "CustomPopoverBackgroundView.h"
#implementation CustomPopoverBackgroundView
- (void)layoutSubviews {
[super layoutSubviews];
CGFloat fullHeight = self.frame.size.height;
CGFloat fullWidth = self.frame.size.width;
CGFloat startingLeft = 0.0;
CGFloat startingTop = 0.0;
CGFloat arrowCoord = 0.0;
UIImage *arrow;
UIImageView *arrowView;
switch (self.arrowDirection) {
case UIPopoverArrowDirectionUp:
startingTop += 13.0;
fullHeight -= 13.0;
//the image line.png will be the corner
arrow = [UIImage imageNamed:#"line.png"];
arrowCoord = (self.frame.size.width / 2) - self.arrowOffset;
arrowView = [[[UIImageView alloc] initWithFrame:CGRectMake(arrowCoord, 0, 13.0, 13.0)] autorelease];
break;
case UIPopoverArrowDirectionDown:
fullHeight -= 13.0;
arrow = [UIImage imageNamed:#"line.png"];
arrowCoord = (self.frame.size.width / 2) - self.arrowOffset;
arrowView = [[[UIImageView alloc] initWithFrame:CGRectMake(arrowCoord, fullHeight, 13.0, 13.0)] autorelease];
break;
case UIPopoverArrowDirectionLeft:
startingLeft += 13.0;
fullWidth -= 13.0;
arrow = [UIImage imageNamed:#"line.png"];
arrowCoord = (self.frame.size.height / 2) - self.arrowOffset;
arrowView = [[[UIImageView alloc] initWithFrame:CGRectMake(0, arrowCoord, 13.0, 13.0)] autorelease];
break;
case UIPopoverArrowDirectionRight:
fullWidth -= 13.0;
arrow = [UIImage imageNamed:#"line.png"];
arrowCoord = (self.frame.size.height / 2) - self.arrowOffset;
arrowView = [[[UIImageView alloc] initWithFrame:CGRectMake(self.frame.size.width-13.0, arrowCoord, 13.0, 13.0)] autorelease];
break;
}
//this image will be your background
UIImage *bg = [[UIImage imageNamed:#"lineBack.png"] resizableImageWithCapInsets:UIEdgeInsetsMake(8.0, 8.0, 8.0, 8.0)];
UIImageView *imageView = [[[UIImageView alloc] initWithFrame:CGRectMake(startingLeft, startingTop, fullWidth, fullHeight)] autorelease];
[imageView setImage:bg];
[arrowView setImage:arrow];
[self addSubview:imageView];
[self addSubview:arrowView];
}
- (CGFloat) arrowOffset {
return offset;
}
- (void) setArrowOffset:(CGFloat)arrowOffset {
offset = arrowOffset;
[self setNeedsLayout];
}
- (UIPopoverArrowDirection)arrowDirection {
return direction;
}
- (void)setArrowDirection:(UIPopoverArrowDirection)arrowDirection {
direction = arrowDirection;
[self setNeedsLayout];
}
+ (CGFloat)arrowHeight {
return 30.0;
}
+ (CGFloat)arrowBase {
return 30.0;
}
+ (UIEdgeInsets)contentViewInsets {
return UIEdgeInsetsMake(30.0, 30.0, 30.0, 30.0);
}
#end
Third step:
When It is done add this line in 'PopOverExample1ViewController.m':
import the new class:
#import " CustomPopoverBackgroundView.h "
-(IBAction) showMovies:(id) sender {
if (self.popoverController == nil) {
MoviesViewController *movies =
[[MoviesViewController alloc]
initWithNibName:#"MoviesViewController"
bundle:[NSBundle mainBundle]];
UIPopoverController *popover =
[[UIPopoverController alloc] initWithContentViewController:movies];
popover.delegate = self;
[movies release];
//THIS IS THE LINE THAT YOU HAVE TO ADD
popover.popoverBackgroundViewClass=[CustomPopoverBackgroundView class];
self.popoverController = popover;
[popover release];
}
[self.popoverController
presentPopoverFromBarButtonItem:sender
permittedArrowDirections:UIPopoverArrowDirectionAny
animated:YES];
}
-(IBAction) btnShowMovies:(id) sender {
if (self.popoverController == nil) {
MoviesViewController *movies =
[[MoviesViewController alloc]
initWithNibName:#"MoviesViewController"
bundle:[NSBundle mainBundle]];
UIPopoverController *popover =
[[UIPopoverController alloc] initWithContentViewController:movies];
popover.delegate = self;
[movies release];
//THIS IS THE LINE THAT YOU HAVE TO ADD
popover.popoverBackgroundViewClass=[CustomPopoverBackgroundView class];
self.popoverController = popover;
[popover release];
}
CGRect popoverRect = [self.view convertRect:[btn frame]
fromView:[btn superview]];
popoverRect.size.width = MIN(popoverRect.size.width, 100);
[self.popoverController
presentPopoverFromRect:popoverRect
inView:self.view
permittedArrowDirections:UIPopoverArrowDirectionAny
animated:YES];
}
Alright!!! Thats all! If someOne needs help just let me know.
Best wishes!
override func viewDidAppear(_animated: Bool){
let navigationBar = self.navigationController?.navigationBar
navigationBar?.tintColor = UIColor(colorLiteralRed: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
the color of the button bar
navigationBar?.barStyle = UIBarStyle.black
the style bar
navigationBar?.barTintColor = UIColor(colorLiteralRed: 0.89, green: 0.55, blue: 0.69, alpha: 1.0)
the color of the bar
let imageView(frame: CGRect(x: 0, y: 0, width: 250, height: 80))
imageView.contentMode = .scaleAspectFit
}
image bar
all the code
override func viewDidAppear(_animated: Bool) {
let navigationBar = self.navigationController?.navigationBar
navigationBar?.tintColor = UIColor(colorLiteralRed: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
navigationBar?.barStyle = UIBarStyle.black
navigationBar?.barTintColor = UIColor(colorLiteralRed: 0.89, green: 0.55, blue: 0.69, alpha: 1.0)
let imageView(frame: CGRect(x: 0, y: 0, width: 250, height: 80))
imageView.contentMode = .scaleAspectFit
}
Related
Here is the image slider works fine when dragging manually the image changes with page control indicator change but I want to add the timer to the following code and move the images and indicator automatically. Please help me to apply NS timer in this code and also want to move from the last image to 1st image and so on.
#implementation DashboardViewController {
NSArray * animationArray;
}
#synthesize scroller = scroller;
#synthesize pageControl = pageControl;
-(void) viewDidLoad {
[super viewDidLoad];
scroller.pagingEnabled = YES;
scroller.showsHorizontalScrollIndicator = NO;
scroller.delegate = self;
animationArray = [NSArray arrayWithObjects: [UIImage imageNamed: # "image1.jpg"],
[UIImage imageNamed: # "image2.jpg"],
[UIImage imageNamed: # "image3.jpg"],
[UIImage imageNamed: # "image4.png"],
[UIImage imageNamed: # "image5.jpg"],
nil
];
CGRect scrollFrame = CGRectMake(0, 0, self.view.frame.size.width, self.scroller.frame.size.height);
scroller.frame = scrollFrame;
self.scroller.contentSize = CGSizeMake(self.scroller.frame.size.width * animationArray.count, self.scroller.frame.size.height);
for (int i = 0; i < animationArray.count; i++) {
CGRect frame;
frame.origin.x = self.scroller.frame.size.width * i;
frame.origin.y = 0;
frame.size = self.scroller.frame.size;
UIImageView * imgView = [
[UIImageView alloc] initWithFrame: CGRectMake(self.scroller.frame.size.width * i, 0, self.scroller.frame.size.width, self.scroller.frame.size.height)
];
imgView.image = [animationArray objectAtIndex: i];
imgView.frame = frame;
[self.scroller addSubview: imgView];
}
self.pageControl.currentPage = 0;
}
-(void) scrollViewDidScroll: (UIScrollView * ) sender {
if (!pageControlBeingUsed) {
// Switch the indicator when more than 50% of the previous/next page is visible
CGFloat pageWidth = self.scroller.frame.size.width;
int page = floor((self.scroller.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
self.pageControl.currentPage = page;
}
}
-(void) scrollViewWillBeginDragging: (UIScrollView * ) scrollView {
pageControlBeingUsed = NO;
}
-(void) scrollViewDidEndDecelerating: (UIScrollView * ) scrollView {
[self setIndiactorForCurrentPage];
}
-(void) setIndiactorForCurrentPage {
uint page = scroller.contentOffset.x / scroller.frame.size.width;
[pageControl setCurrentPage: page];
}
- (IBAction) changePage {
// Update the scroll view to the appropriate page
CGRect frame;
pageControl.currentPage = animationArray.count;
frame.origin.x = self.scroller.frame.size.width * self.pageControl.currentPage;
frame.origin.y = 0;
frame.size = self.scroller.frame.size;
[self.scroller scrollRectToVisible: frame animated: YES];
pageControlBeingUsed = YES;
}
- (void) didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
self.scroller = nil;
self.pageControl = nil;
}
Please try this code for NSTimer (i use collectionView for easy use)
var timer : Timer?
var currentFeaturedCouponIndex = 0
//MARK: - NSTimer -
func setupTimer(){
timer = Timer.scheduledTimer(timeInterval: 5.0, target: self, selector: #selector(self.scrollFeatured), userInfo: nil, repeats: true);
}
func scrollFeatured(){
if self.arrFeaturedCoupon.count > 0 {
//Becauese we scroll coupon if total is > 1
if self.arrFeaturedCoupon.count > 1 {
if self.currentFeaturedCouponIndex < self.arrFeaturedCoupon.count - 1 {
self.currentFeaturedCouponIndex = self.currentFeaturedCouponIndex + 1
}
else {
self.currentFeaturedCouponIndex = 0
}
self.pageControl.currentPage = currentFeaturedCouponIndex
//When currentFeaturedCouponIndex == 0 we make animated: false
if self.currentFeaturedCouponIndex == 0 {
self.featuredCouponColView.scrollToItem(at: self.featuredCouponCurrentIndexPath, at: UICollectionViewScrollPosition.left, animated: false)
}
else {
self.featuredCouponColView.scrollToItem(at: self.featuredCouponCurrentIndexPath, at: UICollectionViewScrollPosition.left, animated: true)
}
}
}
}
To invalidate timer when and where you want
func invalidateTimer(){
if timer != nil {
self.timer!.invalidate()
self.timer = nil
}
}
In my case cluster custome image is white background and I need to change color of text and make it more smaller
- (void)configureMap {
// Set up the cluster manager with a supplied icon generator and renderer.
id<GMUClusterAlgorithm> algorithm = [[GMUNonHierarchicalDistanceBasedAlgorithm alloc] init];
id<GMUClusterIconGenerator> iconGenerator = [self iconGeneratorWithImages];
id<GMUClusterRenderer> renderer = [[GMUDefaultClusterRenderer alloc] initWithMapView:_mapView clusterIconGenerator:iconGenerator];
_clusterManager = [[GMUClusterManager alloc] initWithMap:_mapView
algorithm:algorithm
renderer:renderer];
}
- (id<GMUClusterIconGenerator>)iconGeneratorWithImages {
UIImage *clusterImage = [UIImage imageNamed:#"customClusterImage"];
return [[GMUDefaultClusterIconGenerator alloc] initWithBuckets:#[#10, #50, #100, #200, #1000]
backgroundImages:#[clusterImage, clusterImage, clusterImage, clusterImage, clusterImage]
];
}
UPD: no answers here: https://github.com/googlemaps/google-maps-ios-utils/issues/127
- (void)configureMapView {
// ....
id<GMUClusterAlgorithm> algorithm = [[GMUNonHierarchicalDistanceBasedAlgorithm alloc] init];
id<GMUClusterIconGenerator> iconGenerator = [[GMUDefaultClusterIconGenerator alloc] init];
GMUDefaultClusterRenderer *renderer = [[GMUDefaultClusterRenderer alloc] initWithMapView:_mapView clusterIconGenerator:iconGenerator];
renderer.delegate = self; // <---- 1. set delegate
_clusterManager = [[GMUClusterManager alloc] initWithMap:_mapView
algorithm:algorithm
renderer:renderer];
}
#pragma mark - <GMUClusterRendererDelegate>
- (void)renderer:(id<GMUClusterRenderer>)renderer willRenderMarker:(GMSMarker *)marker {
if ([marker.userData isKindOfClass:[MyMarker class]]) {
marker.icon = [UIImage imageNamed:#"markerNormal"] // <----- 2.1 icon for ordinary marker
} else if ([marker.userData conformsToProtocol:#protocol(GMUCluster)]) {
// <------ 2.2 icon for cluster marker (draw title on image)
id<GMUCluster> userData = marker.userData;
marker.icon = [self drawFront:[UIImage imageNamed:#"markerGroup"] text:[NSString stringWithFormat:#"%#", #(userData.count)]];
}
}
#pragma mark -
- (UIImage *)drawFront:(UIImage *)image text:(NSString *)text {
// draw image first
UIGraphicsBeginImageContextWithOptions(image.size, false, [UIScreen mainScreen].scale);
[image drawInRect:CGRectMake(0, 0, image.size.width, image.size.height)];
// text attributes
NSMutableParagraphStyle *style = [[NSMutableParagraphStyle alloc] init];
[style setAlignment:NSTextAlignmentCenter];
NSDictionary *attr = #{NSParagraphStyleAttributeName : style,
NSFontAttributeName : [UIFont systemFontOfSize:17. weight:UIFontWeightRegular], // set text font
NSForegroundColorAttributeName : [UIColor redColor] // set text color
};
const CGFloat paddingTop = 8.;
const CGRect rect = CGRectMake(0, paddingTop, image.size.width., image.size.height);
[text drawInRect:rect withAttributes:attr];
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
func renderer(_ renderer: GMUClusterRenderer, willRenderMarker marker: GMSMarker) {
if let m = (marker.userData as? POIItem) {
let vehicle = m.vehicle
if m.isPlate {
let label = UILabel(frame: CGRect(x: 0, y: 0, width: 0, height: 2))
label.backgroundColor = .white
label.textColor = .black
label.text = " \(vehicle.plate) "
label.layer.borderColor = UIColor.gray.cgColor
label.layer.borderWidth = 1
label.layer.cornerRadius = 4
label.alpha = 0.9
label.textAlignment = .center
label.sizeToFit()
marker.groundAnchor = CGPoint(x: 0.5, y: 0.1)
marker.iconView = label
} else {
var icon = "\(vehicle.icon)"
if icon == "1" {
icon = "green/\(vehicle.angle)"
}
marker.icon = UIImage(named: icon)
}
}
else {
if let x = marker.userData as? GMUStaticCluster {
let lbl = UILabel(frame: CGRect(x: 0, y: 0, width: 48, height: 48))
lbl.text = "\(x.count)"
lbl.textColor = .white
lbl.textAlignment = .center
lbl.backgroundColor = .red
lbl.layer.cornerRadius = 24
lbl.layer.masksToBounds = true
marker.iconView = lbl
}
}
}
I am using the popular HMSegmentedControl to present segments in my project. But I am facing a disastrous problem now that I am unable to tie my segments to a scroll view. As the example is in objective C. Its becoming difficult to do so in Swift. The code goes like this -
self.segmentedControl4 = [[HMSegmentedControl alloc] initWithFrame:CGRectMake(0, 260, viewWidth, 50)];
self.segmentedControl4.sectionTitles = #[#"Worldwide", #"Local", #"Headlines"];
self.segmentedControl4.selectedSegmentIndex = 1;
self.segmentedControl4.backgroundColor = [UIColor colorWithRed:0.7 green:0.7 blue:0.7 alpha:1];
self.segmentedControl4.titleTextAttributes = #{NSForegroundColorAttributeName : [UIColor whiteColor]};
self.segmentedControl4.selectedTitleTextAttributes = #{NSForegroundColorAttributeName : [UIColor colorWithRed:0.1 green:0.1 blue:0.1 alpha:1]};
self.segmentedControl4.selectionIndicatorColor = [UIColor colorWithRed:0.3 green:0.3 blue:0.3 alpha:1];
self.segmentedControl4.selectionStyle = HMSegmentedControlSelectionStyleBox;
self.segmentedControl4.selectionIndicatorLocation = HMSegmentedControlSelectionIndicatorLocationUp;
self.segmentedControl4.tag = 3;
__weak typeof(self) weakSelf = self;
[self.segmentedControl4 setIndexChangeBlock:^(NSInteger index)
{
[weakSelf.scrollView scrollRectToVisible:CGRectMake(viewWidth * index, 0, viewWidth, 200) animated:YES];
}];
[self.view addSubview:self.segmentedControl4];
self.scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 310, viewWidth, 210)];
self.scrollView.backgroundColor = [UIColor colorWithRed:0.7 green:0.7 blue:0.7 alpha:1];
self.scrollView.pagingEnabled = YES;
self.scrollView.showsHorizontalScrollIndicator = NO;
self.scrollView.contentSize = CGSizeMake(viewWidth * 3, 200);
self.scrollView.delegate = self;
[self.scrollView scrollRectToVisible:CGRectMake(viewWidth, 0, viewWidth, 200) animated:NO];
[self.view addSubview:self.scrollView];
Can anyone who has worked on this third party give me some solutions?
Here is the code for scrolling a segmented control. You can also download the source from here.
import UIKit
import HSegmentControl
class ViewController: UIViewController, HSegmentControlDataSource {
#IBOutlet weak var segmentControl: HSegmentControl!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
segmentControl.dataSource = self
segmentControl.numberOfDisplayedSegments = 3
segmentControl.segmentIndicatorViewContentMode = UIViewContentMode.bottom
// segmentControl.selectedTitleFont = UIFont.boldSystemFont(ofSize: 17)
segmentControl.selectedTitleColor = UIColor.white
// segmentControl.unselectedTitleFont = UIFont.systemFont(ofSize: 17)
// segmentControl.unselectedTitleColor = UIColor.darkGray
// segmentControl.segmentIndicatorImage = UIImage(named: "ind_img")
segmentControl.segmentIndicatorView.backgroundColor = UIColor(red: 31.0/255.0, green: 48.0/255.0, blue: 93.0/255.0, alpha: 1.0)
segmentControl.selectedIndex = 2
}
// MARK: - HSegmentControlDataSource protocol
func numberOfSegments(_ segmentControl: HSegmentControl) -> Int {
return 5
}
func segmentControl(_ segmentControl: HSegmentControl, titleOfIndex index: Int) -> String {
return ["Kavin","Sitharth", "Raj", "Selva", "Rajesh"][index]
}
func segmentControl(_ segmentControl: HSegmentControl, segmentBackgroundViewOfIndex index: Int) -> UIView {
let view = UIView()
// view.backgroundColor = UIColor(red: CGFloat(drand48()), green: CGFloat(drand48()), blue: CGFloat(drand48()), alpha: 1)
return view
}
#IBAction func valueChanged(_ sender: AnyObject) {
print("value did change to \((sender as! HSegmentControl).selectedIndex)")
}
}
Just set up the segmented control normally and set the indexChangeBlock to scroll the scroll view:
segmentedControl4.indexChangeBlock = {
let frame = CGRectMake(viewWidth * index, 0, viewWidth, 200)
scrollView.scrollRectToVisible(frame, animated:true)
}
This will scroll the scroll view every time the segmented control's index changes.
I want to create an animated popover bubble like the one below. With the same expanding/contracting bounce animation. Does anyone know how to go about this? Is is just a UIView with animation? What animation effect is this? Any pointers on how to go about this would be really appreciated. Thanks!
You can use the
Obj-C:
animateWithDuration:delay:usingSpringWithDamping:initialSpringVelocity:options:animations:animations completion: method like this:
UIView *animationView = [[UIView alloc] initWithFrame:CGRectMake(50, 90, 100, 50)];
animationView.backgroundColor = [UIColor redColor];
animationView.transform = CGAffineTransformMakeScale(0, 0);
[self.view addSubview:animationView];
[UIView animateWithDuration:0.3
delay:0
usingSpringWithDamping:0.5
initialSpringVelocity:5
options:UIViewAnimationOptionCurveEaseInOut
animations:^{
animationView.transform = CGAffineTransformIdentity;
}
completion:nil];
Swift:
var animationView: UIView = UIView(frame: CGRectMake(50, 90, 100, 50))
animationView.backgroundColor = UIColor.redColor()
animationView.transform = CGAffineTransformMakeScale(0, 0)
self.view!.addSubview(animationView)
UIView.animateWithDuration(0.3, delay: 0, usingSpringWithDamping: 0.5, initialSpringVelocity: 5, options: .CurveEaseInOut, animations: {() -> Void in
animationView.transform = CGAffineTransformIdentity
}, completion: { _ in })
i think it is UIPopoverPresentationController.
sample:
-(void)showPopover:(UIBarButtonItem*)sender{
if(!_btnController){
_btnController = [[ButtonsViewController alloc] init];
_btnController.delegate = self;
}
if (_popover == nil) {
_btnController.modalPresentationStyle = UIModalPresentationPopover;
UIPopoverPresentationController *pc = [ _btnController popoverPresentationController];
pc.barButtonItem = sender;
pc.permittedArrowDirections = UIPopoverArrowDirectionAny;
pc.delegate = self;
[self presentViewController: _btnController animated:YES completion:nil];
} else {
//The color picker popover is showing. Hide it.
[_popover dismissPopoverAnimated:YES];
_popover = nil;
}}
I have a messenger, so I want to show UIMenuController on cell long tap.
I need image view to catch long press, because I have text and media messages. But I get a crash becomeFirstResponder call after I received long press gesture on iOS 8(iOS 7 works well):
*** Terminating app due to uncaught exception 'UIViewControllerHierarchyInconsistency', reason: 'child view controller:<UICompatibilityInputViewController: 0x13fd75b90> should have parent view controller:<FriendPlay.WLDialogViewController: 0x13fd54d10> but requested parent is:<UIInputWindowController: 0x140815000>'
This is the part of code:
override func handleLongPress(longPress: UILongPressGestureRecognizer!) {
let alpha: CGFloat = 0.6
let point = longPress.locationInView(tableView)
let indexPath = tableView.indexPathForRowAtPoint(point)
if indexPath != nil {
let cell = tableView.cellForRowAtIndexPath(indexPath!) as MessageCell
let convertedPoint = longPress.locationInView(cell.balloonImageView)
if CGRectContainsPoint(cell.balloonImageView.frame, convertedPoint) {
var myView = cell.balloonImageView
if cell.message.type == MessageType.Text {
cell.balloonImageView.alpha = alpha
}
else {
myView = cell.mediaImageView
cell.mediaImageView.alpha = alpha
}
if longPress.state == UIGestureRecognizerState.Began {
showMenuAtPoint(convertedPoint, myView: myView)
}
}
}
}
private func showMenuAtPoint(point: CGPoint, myView: MessageImageView) {
myView.becomeFirstResponder()// <--- that crashes
let rect = CGRectMake(point.x, point.y, 0, 0)
let mc = UIMenuController.sharedMenuController()
mc.setTargetRect(rect, inView: myView)
let sendItem = UIMenuItem(title: "Send", action: "sendAgain:")
mc.menuItems = [sendItem]
mc.setMenuVisible(true, animated: true)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "menuDidHide:", name: UIMenuControllerDidHideMenuNotification, object: nil)
}
func sendAgain(sender: AnyObject) {
println("Send!")
}
For class MessageImageView (inherited from UIImageView) I redefine becomeFirstResponder to return always true.
I initialize my cell in - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier messageMaxWidth:(CGFloat)messageMaxWidth
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier messageMaxWidth:(CGFloat)messageMaxWidth
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
self.messageMaxWidth = messageMaxWidth;
self.backgroundColor = [UIColor clearColor];
self.panGesture = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(handlePan:)];
self.panGesture.delegate = self;
[self addGestureRecognizer:self.panGesture];
[self setInitialSizes];
[[NSNotificationCenter defaultCenter] removeObserver:self];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(handleOrientationWillChandeNote:) name:UIApplicationWillChangeStatusBarFrameNotification object:nil];
}
return self;
}
- (void)setInitialSizes
{
if (self.containerView) {
[self.containerView removeFromSuperview];
}
if (self.timeLabel) {
[self.timeLabel removeFromSuperview];
}
self.userImageView = [[UIImageView alloc] init];
self.userImageView.autoresizingMask = UIViewAutoresizingFlexibleTopMargin;
self.textView = [[UITextView alloc] initWithFrame:CGRectMake(0, 0, self.messageMaxWidth, 0)];
self.timeLabel = [[UILabel alloc] init];
self.mediaImageView = [[SOmessageImageView alloc] init];
self.mediaOverlayView = [[UIView alloc] init];
self.balloonImageView = [[SOmessageImageView alloc] init];
self.balloonImageView.userInteractionEnabled = YES;
if (!CGSizeEqualToSize(self.userImageViewSize, CGSizeZero)) {
CGRect frame = self.userImageView.frame;
frame.size = self.userImageViewSize;
self.userImageView.frame = frame;
}
self.userImageView.contentMode = UIViewContentModeScaleAspectFill;
self.userImageView.clipsToBounds = YES;
self.userImageView.backgroundColor = [UIColor clearColor];
self.userImageView.layer.cornerRadius = 5;
if (!CGSizeEqualToSize(self.mediaImageViewSize, CGSizeZero)) {
CGRect frame = self.mediaImageView.frame;
frame.size = self.mediaImageViewSize;
self.mediaImageView.frame = frame;
}
self.mediaImageView.contentMode = UIViewContentModeScaleAspectFill;
self.mediaImageView.clipsToBounds = YES;
self.mediaImageView.backgroundColor = [UIColor clearColor];
self.mediaImageView.userInteractionEnabled = YES;
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleMediaTapped:)];
[self.mediaImageView addGestureRecognizer:tap];
self.mediaOverlayView.backgroundColor = [UIColor clearColor];
[self.mediaImageView addSubview:self.mediaOverlayView];
self.textView.textColor = [UIColor whiteColor];
self.textView.backgroundColor = [UIColor clearColor];
[self.textView setTextContainerInset:UIEdgeInsetsZero];
self.textView.textContainer.lineFragmentPadding = 0;
[self hideSubViews];
self.containerView = [[UIView alloc] initWithFrame:self.contentView.bounds];
self.containerView.autoresizingMask = UIViewAutoresizingFlexibleTopMargin;
[self.contentView addSubview:self.containerView];
[self.containerView addSubview:self.balloonImageView];
[self.containerView addSubview:self.textView];
[self.containerView addSubview:self.mediaImageView];
[self.containerView addSubview:self.userImageView];
self.contentView.clipsToBounds = NO;
self.clipsToBounds = NO;
self.timeLabel.font = [UIFont fontWithName:#"AvenirNextCyr-Light" size:11];
self.timeLabel.textColor = [UIColor grayColor];
self.timeLabel.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin;
UIImage *backgroundImage = [UIImage imageNamed:#"messagesDateBackground"];
if (backgroundImage) {
self.timeLabel.textColor = [UIColor whiteColor];
if (self.backgroundImageView) {
[self.backgroundImageView removeFromSuperview];
}
self.backgroundImageView = [[UIImageView alloc] initWithImage:[backgroundImage resizableImageWithCapInsets:UIEdgeInsetsMake(20, 20, 20, 20)]];
self.backgroundImageView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin;
[self.contentView addSubview:self.backgroundImageView];
}
[self.contentView addSubview:self.timeLabel];
}
Please give me some suggestions, how to fix this strange bug.
Your view controller probably has a property named inputView that is merely a subview, not an inputView as UIResponder interface expects it to be.
Starting with iOS 8 they check that UIResponder's inputView has no parent.