NSAttributedString with image attachment and NSTextTab, text not aligned - ios

I'm trying to have a UIlabel with an image and title on the left and a list of descriptions with bullets on the right.
To do that I'm using NSAttributedString like this :
NSMutableParagraphStyle *pStyle = [[NSMutableParagraphStyle alloc] init];
pStyle.tabStops =
#[ [[NSTextTab alloc] initWithTextAlignment:NSTextAlignmentLeft location:tabLocation options:[NSDictionary dictionary]] ];
NSMutableAttributedString *attString = [[NSMutableAttributedString alloc] init];
NSTextAttachment *textAttachment = [[NSTextAttachment alloc] init];
textAttachment.image = [UIImage imageNamed:#"test_image"];
textAttachment.bounds = CGRectMake(0, -3, 15, 15);//resize the image
attString = [NSAttributedString attributedStringWithAttachment:textAttachment].mutableCopy;
[attString appendAttributedString:[[NSAttributedString alloc]
initWithString:[NSString stringWithFormat:#"title\t\u2022 %#",
[#[ #"description1", #"description2" ]
componentsJoinedByString:#"\n\t\u2022 "]]
attributes:#{NSParagraphStyleAttributeName : pStyle}]];
label.attributedText = attString;
I expect the list on the right to be left aligned but that's not the case, here is the result I get:
What I expect is the list to be aligned like this:

The issue is with location parameter in NSTextTab
According to description, location parameter helps to position text from left margin. So this is what we needed, just replace below lines
pStyle.tabStops = #[ [[NSTextTab alloc] initWithTextAlignment:NSTextAlignmentLeft location:tabLocation options:[NSDictionary dictionary]] ];
with
pStyle.tabStops = #[[[NSTextTab alloc] initWithTextAlignment:NSTextAlignmentLeft location:[self getTextLocationFor:#"test"] options:[NSDictionary dictionary]] ];
Add getTextLocationFor: method to calculate location as follows
-(CGFloat)getTextLocationFor:(NSString *)inputStr{
CGSize maximuminputStringWidth = CGSizeMake(FLT_MAX, 30);
CGRect textRect = [inputStr boundingRectWithSize:maximuminputStringWidth
options:NSStringDrawingUsesLineFragmentOrigin
attributes:#{NSFontAttributeName:[UIFont systemFontOfSize:15]}
context:nil];
UIImageView * testImage = [[UIImageView alloc]initWithImage:[UIImage imageNamed:#"close_red"]];//Change image name with yours
return textRect.size.width + testImage.frame.size.width +2;
}
That's it we are ready to go run your project now everything will be fine.
RESULT:

if I understand you correctly then try these code:
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 460, 460)];
label.numberOfLines = 0;
[self.view addSubview:label];
NSMutableParagraphStyle *pStyle = [[NSMutableParagraphStyle alloc] init];
pStyle.tabStops = #[ [[NSTextTab alloc] initWithTextAlignment:NSTextAlignmentLeft location:40 options:#{}] ];
NSTextAttachment *textAttachment = [[NSTextAttachment alloc] init];
textAttachment.image = [UIImage imageNamed:#"img"];
textAttachment.bounds = CGRectMake(0, -3, 30, 30);
NSString *string = [NSString stringWithFormat:#"title\n\r\u2022 %#", [#[ #"description1", #"description2" ] componentsJoinedByString:#"\n\r\u2022 "]];
NSMutableAttributedString *attributedString = [[NSMutableAttributedString attributedStringWithAttachment:textAttachment] mutableCopy];
[attributedString appendAttributedString:[[NSMutableAttributedString alloc] initWithString:string attributes:#{NSParagraphStyleAttributeName : pStyle}]];
label.attributedText = attributedString;
Here is result
UPDATE
You can only achieve this using TextKit (NSTextLayoutManager) and specify area which should be use to draw text, or use simple solution and subclass from UIView.
Here is solution with view
ListView.h
#interface ListView : UIView
#property(nonatomic,strong) UIImage *image;
#property(nonatomic,strong) NSString *title;
#property(nonatomic,strong) NSArray *list;
#end
ListView.m
static const CGFloat ImageWidth = 13.f;
#interface ListView()
#property (nonatomic,weak) UIImageView *imageView;
#property (nonatomic,weak) UILabel *titleLabel;
#property (nonatomic,weak) UILabel *listLabel;
#end
#implementation ListView
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
[self setup];
return self;
}
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
[self setup];
return self;
}
- (void)awakeFromNib {
[super awakeFromNib];
[self setup];
}
- (void)setup {
UIImageView *imageView = [[UIImageView alloc] init];
imageView.translatesAutoresizingMaskIntoConstraints = NO;
[self addSubview:imageView];
self.imageView = imageView;
UILabel *titleLabel = [[UILabel alloc] init];
titleLabel.translatesAutoresizingMaskIntoConstraints = NO;
titleLabel.numberOfLines = 0;
[titleLabel setContentCompressionResistancePriority:UILayoutPriorityDefaultHigh forAxis:UILayoutConstraintAxisHorizontal];
[titleLabel setContentHuggingPriority:UILayoutPriorityDefaultHigh forAxis:UILayoutConstraintAxisHorizontal];
[self addSubview:titleLabel];
self.titleLabel = titleLabel;
UILabel *listLabel = [[UILabel alloc] init];
listLabel.translatesAutoresizingMaskIntoConstraints = NO;
listLabel.numberOfLines = 0;
[listLabel setContentCompressionResistancePriority:UILayoutPriorityDefaultLow forAxis:UILayoutConstraintAxisHorizontal];
[listLabel setContentHuggingPriority:UILayoutPriorityDefaultLow forAxis:UILayoutConstraintAxisHorizontal];
[self addSubview:listLabel];
self.listLabel = listLabel;
NSDictionary *views = NSDictionaryOfVariableBindings(imageView,titleLabel,listLabel);
NSDictionary *metrics = #{ #"ImageHeight" : #(ImageWidth) };
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-0-[imageView(ImageHeight)]-0-[titleLabel]-0-[listLabel]-0-|" options:0 metrics:metrics views:views]];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-0-[imageView(ImageHeight)]" options:NSLayoutFormatAlignAllTop metrics:metrics views:views]];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-0-[titleLabel]" options:NSLayoutFormatAlignAllTop metrics:metrics views:views]];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:|-0-[listLabel]-0-|" options:NSLayoutFormatAlignAllTop metrics:metrics views:views]];
}
- (void)setImage:(UIImage *)image {
_image = image;
self.imageView.image = image;
[self setNeedsLayout];
}
- (void)setTitle:(NSString *)title {
_title = title;
self.titleLabel.text = title;
[self setNeedsLayout];
}
- (void)setList:(NSArray *)list {
_list = list;
NSMutableParagraphStyle *pStyle = [[NSMutableParagraphStyle alloc] init];
pStyle.tabStops = #[ [[NSTextTab alloc] initWithTextAlignment:NSTextAlignmentLeft location:40 options:#{}] ];
NSString *string = [NSString stringWithFormat:#"\u2022 %#", [list componentsJoinedByString:#"\n\u2022 "]];
self.listLabel.attributedText = [[NSAttributedString alloc] initWithString:string attributes:#{NSParagraphStyleAttributeName : pStyle}];
[self setNeedsLayout];
}
#end

Related

Images on horizontal scroll view according to clicked image

I have four images on a Viewcontroller A .On the click of those images Viewcontroller B having UIScrollView presents that has image view and it shows all those four imgaes....Image1 ,image 2,image 3,image 4.
I want that when image 2 is clicked then image 2 appeas as the first image on Viewcontroller B ,then image 3,then image 4...Also,when user moves left then it shows previous images including image1 too.
I have searched a lot but couldn't find solution to this problem Kindly.help
The code I have used are as follows:
- (void)viewDidLoad {
[super viewDidLoad];
width = [UIScreen mainScreen].bounds.size.width;
height = [UIScreen mainScreen].bounds.size.height;
_scroller = [[UIScrollView alloc]initWithFrame:
CGRectMake(0,64,width,height)];
_scroller.contentSize=CGSizeMake(pageCount*_scroller.bounds.size.width,_scroller.bounds.size.height);
_scroller.pagingEnabled=YES;
_scroller.showsHorizontalScrollIndicator=YES;
CGRect ViewSize=_scroller.bounds;
NSArray *imgArray = [self.tripDetails valueForKey:#"Flightimageurl"];
for(int i=0;i<[imgArray count];i++)
{
UIImageView *imgView1=[[UIImageView alloc]initWithFrame:ViewSize];
NSString *ImageURL = [imgArray objectAtIndex:i];
NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:ImageURL]];
imgView1.image=[UIImage imageWithData:imageData];
[_scroller addSubview:imgView1];
[self.view addSubview:_scroller];
ViewSize =CGRectOffset(ViewSize,_scroller.bounds.size.width,0);
}
}
Use This Code It will be helpful to you
-(void)singleTapping:(UIGestureRecognizer *)recognizer {
int imageTag = (int) recognizer.view.tag;
NSDictionary *dictCurrentWish = [arrLatestScrollData objectAtIndex:pageNumberSaved];
scrollimagePostView = [[UIScrollView alloc] initWithFrame:CGRectMake(0,0, kSCREEN_WIDTH, kSCREEN_HEIGHT)];
scrollimagePostView.pagingEnabled=YES;
scrollimagePostView.delegate=self;
UITapGestureRecognizer *gr = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleGesture:)];
[scrollimagePostView addGestureRecognizer:gr];
NSMutableArray *arrTotalImages = [[NSMutableArray alloc]initWithCapacity:0];
[arrTotalImages addObject:[dictCurrentWish objectForKey:#"pic1"]];
[arrTotalImages addObject:[dictCurrentWish objectForKey:#"pic2"]];
[arrTotalImages addObject:[dictCurrentWish objectForKey:#"pic3"]];
[arrTotalImages addObject:[dictCurrentWish objectForKey:#"pic4"]];
int x=0;
CGRect innerScrollFrame = scrollimagePostView.bounds;
for (int i=0; i<arrTotalImages.count; i++) {
imgViewPost=[[UIImageView alloc]initWithFrame:CGRectMake(x, 60, kSCREEN_WIDTH,kSCREEN_HEIGHT-90)];
NSString *strImage =[NSString stringWithFormat:#"%#", [arrTotalImages objectAtIndex:i]];
NSString *strURL=[strImage stringByReplacingOccurrencesOfString:#" " withString:#"%20"];
NSURL* urlAddress1 = [[NSURL alloc] initWithString:strURL];
[imgViewPost sd_setImageWithURL:urlAddress1 placeholderImage:wishPlaceHolderImage];
imgViewPost.contentMode = UIViewContentModeScaleAspectFit;
imgViewPost.tag = VIEW_FOR_ZOOM_TAG;
UIScrollView *pageScrollView = [[UIScrollView alloc]
initWithFrame:innerScrollFrame];
pageScrollView.minimumZoomScale = 1.0f;
pageScrollView.maximumZoomScale = 6.0f;
pageScrollView.zoomScale = 1.0f;
pageScrollView.contentSize = imgViewPost.bounds.size;
pageScrollView.delegate = self;
pageScrollView.showsHorizontalScrollIndicator = NO;
pageScrollView.showsVerticalScrollIndicator = NO;
[pageScrollView addSubview:imgViewPost];
[scrollimagePostView addSubview:imgViewPost];
x=x+kSCREEN_WIDTH;
if (i < 2) {
innerScrollFrame.origin.x += innerScrollFrame.size.width;
}
}
scrollimagePostView.contentSize = CGSizeMake(x, scrollimagePostView.frame.size.height );
scrollimagePostView.backgroundColor = [UIColor blackColor];
[self.view addSubview:scrollimagePostView];
[scrollimagePostView setContentOffset:CGPointMake(scrollimagePostView.frame.size.width*(imageTag-1), 0.0f) animated:NO];
btnCloseFullIMageView = [[UIButton alloc]initWithFrame:CGRectMake(kSCREEN_WIDTH-80, 25, 70, 25)];
[btnCloseFullIMageView setTitle:#"Close" forState:UIControlStateNormal];
[btnCloseFullIMageView setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
btnCloseFullIMageView.backgroundColor = [UIColor blackColor];
btnCloseFullIMageView.layer.borderColor = [UIColor whiteColor].CGColor;
btnCloseFullIMageView.layer.borderWidth = 0.5;
btnCloseFullIMageView.layer.cornerRadius = 3.0;
btnCloseFullIMageView.clipsToBounds = TRUE;
[btnCloseFullIMageView addTarget:self action:#selector(closeFullImageView:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btnCloseFullIMageView];
}

iOS Today Extension keeps crashing on iPhone, not in simulator

I'm trying to build an iOS Today Extension that shows three images with some text. In the simulator it runs fine, but when I run it on my iPhone, it flashes three times and then displays Unable to Load. What am I doing wrong?
TodayViewController.m
#import "TodayViewController.h"
#import <NotificationCenter/NotificationCenter.h>
#import "UIImageView+WebCache.h"
#import "SDImageCache.h"
#interface TodayViewController () <NCWidgetProviding>
#property (strong, nonatomic) UILabel *descriptionLabel;
#property (strong, nonatomic) UIImageView *firstImage;
#property (strong, nonatomic) UIImageView *secondImage;
#property (strong, nonatomic) UIImageView *thirdImage;
#property (strong, nonatomic) UILabel *firstImageLabel;
#property (strong, nonatomic) UILabel *secondImageLabel;
#property (strong, nonatomic) UILabel *thirdImageLabel;
#property (strong, nonatomic) UILabel *firstImageOwnerLabel;
#property (strong, nonatomic) UILabel *secondImageOwnerLabel;
#property (strong, nonatomic) UILabel *thirdImageOwnerLabel;
#property (strong, nonatomic) NSDictionary *dataOne;
#property (strong, nonatomic) NSDictionary *dataTwo;
#property (strong, nonatomic) NSDictionary *dataThree;
#property (nonatomic) NSInteger quarterSize;
#property (nonatomic) NSInteger eightSize;
#end
#implementation TodayViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
self.preferredContentSize = CGSizeMake(self.view.frame.size.width, 320);
[self updateNumberLabelText];
if ([self.dataOne count] == 0) {
UILabel *noContent = [[UILabel alloc] initWithFrame:CGRectMake((self.view.frame.size.width/2)-150, 93, 300, 44)];
noContent.text = #"You haven't opened the app yet.";
[self.view addSubview:noContent];
} else {
NSString *deviceType = [UIDevice currentDevice].model;
if([deviceType isEqualToString:#"iPhone"] || [deviceType isEqualToString:#"iPhone Simulator"])
{
self.quarterSize = self.view.frame.size.width/4;
self.eightSize = self.quarterSize/4;
} else if([deviceType isEqualToString:#"iPad"] || [deviceType isEqualToString:#"iPad Simulator"])
{
self.quarterSize = self.view.frame.size.width/5;
self.eightSize = self.quarterSize/4;
}
self.descriptionLabel = [[UILabel alloc] initWithFrame:CGRectMake(self.eightSize, 15, self.view.frame.size.width-self.quarterSize, 20)];
self.descriptionLabel.text = #"Some new images just for you!";
self.descriptionLabel.textColor = [UIColor whiteColor];
[self.view addSubview:self.descriptionLabel];
UIView *firstView = [[UIView alloc] initWithFrame:CGRectMake(self.eightSize, 45, self.quarterSize, self.quarterSize*2)];
UITapGestureRecognizer *singleFingerTap =
[[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(openFirstImage:)];
[firstView addGestureRecognizer:singleFingerTap];
if ([[self.dataOne objectForKey:#"imageurl"] isEqualToString:#"empty"]) {
UIView *noImageOne = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.quarterSize, self.quarterSize*1.25)];
noImageOne.backgroundColor = [self paperColorLightBlue500];
[firstView addSubview:noImageOne];
} else {
self.firstImage = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, self.quarterSize, self.quarterSize*1.25)];
__block UIActivityIndicatorView *activityIndicator;
__weak UIImageView *weakImageView = self.firstImage;
[self.firstImage sd_setImageWithURL: [NSURL URLWithString:[self.dataOne objectForKey:#"imageurl"]]
placeholderImage:[UIImage imageNamed:#"placeholder.png"]
options:SDWebImageProgressiveDownload
progress:^(NSInteger receivedSize, NSInteger expectedSize) {
if (!activityIndicator) {
[weakImageView addSubview:activityIndicator = [UIActivityIndicatorView.alloc initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray]];
activityIndicator.center = weakImageView.center;
[activityIndicator startAnimating];
}
}
completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
[activityIndicator removeFromSuperview];
activityIndicator = nil;
}];
self.firstImage.contentMode = UIViewContentModeScaleAspectFill;
[self.firstImage setClipsToBounds:YES];
[firstView addSubview:self.firstImage];
}
UIView *secondView = [[UIView alloc] initWithFrame:CGRectMake(firstView.frame.origin.x + firstView.frame.size.width + self.eightSize, 45, self.quarterSize, self.quarterSize*2)];
UITapGestureRecognizer *secondFingerTap =
[[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(openSecondImage:)];
[secondView addGestureRecognizer:secondFingerTap];
if ([[self.dataTwo objectForKey:#"imageurl"] isEqualToString:#"empty"]) {
UIView *noImageTwo = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.quarterSize, self.quarterSize*1.25)];
noImageTwo.backgroundColor = [self paperColorLightBlue500];
[secondView addSubview:noImageTwo];
} else {
self.secondImage = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, self.quarterSize, self.quarterSize*1.25)];
__block UIActivityIndicatorView *activityIndicator;
__weak UIImageView *weakImageView = self.secondImage;
[self.secondImage sd_setImageWithURL: [NSURL URLWithString:[self.dataTwo objectForKey:#"imageurl"]]
placeholderImage:[UIImage imageNamed:#"placeholder.png"]
options:SDWebImageProgressiveDownload
progress:^(NSInteger receivedSize, NSInteger expectedSize) {
if (!activityIndicator) {
[weakImageView addSubview:activityIndicator = [UIActivityIndicatorView.alloc initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray]];
activityIndicator.center = weakImageView.center;
[activityIndicator startAnimating];
}
}
completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
[activityIndicator removeFromSuperview];
activityIndicator = nil;
}];
self.secondImage.contentMode = UIViewContentModeScaleAspectFill;
[self.secondImage setClipsToBounds:YES];
[secondView addSubview:self.secondImage];
}
UIView *thirdView = [[UIView alloc] initWithFrame:CGRectMake(secondView.frame.origin.x + secondView.frame.size.width + self.eightSize, 45, self.quarterSize, self.quarterSize*2)];
UITapGestureRecognizer *thirdFingerTap =
[[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(openThirdImage:)];
[thirdView addGestureRecognizer:thirdFingerTap];
if ([[self.dataThree objectForKey:#"imageurl"] isEqualToString:#"empty"]) {
UIView *noImageThird = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.quarterSize, self.quarterSize*1.25)];
noImageThird.backgroundColor = [self paperColorLightBlue500];
[thirdView addSubview:noImageThird];
} else {
self.thirdImage = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, self.quarterSize, self.quarterSize*1.25)];
__block UIActivityIndicatorView *activityIndicator;
__weak UIImageView *weakImageView = self.thirdImage;
[self.thirdImage sd_setImageWithURL: [NSURL URLWithString:[self.dataThree objectForKey:#"imageurl"]]
placeholderImage:[UIImage imageNamed:#"placeholder.png"]
options:SDWebImageProgressiveDownload
progress:^(NSInteger receivedSize, NSInteger expectedSize) {
if (!activityIndicator) {
[weakImageView addSubview:activityIndicator = [UIActivityIndicatorView.alloc initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray]];
activityIndicator.center = weakImageView.center;
[activityIndicator startAnimating];
}
}
completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
[activityIndicator removeFromSuperview];
activityIndicator = nil;
}];
self.thirdImage.contentMode = UIViewContentModeScaleAspectFill;
[self.thirdImage setClipsToBounds:YES];
[thirdView addSubview:self.thirdImage];
}
self.firstImageLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, self.firstImage.frame.origin.y + self.firstImage.frame.size.height + 10, self.quarterSize, 20)];
self.firstImageLabel.text = [self.dataOne objectForKey:#"title"];
self.firstImageLabel.numberOfLines = 2;
self.firstImageLabel.textColor = [UIColor whiteColor];
self.firstImageLabel.font = [UIFont fontWithName:#"HelveticaNeue" size:13];
[self.firstImageLabel sizeToFit];
[firstView addSubview:self.firstImageLabel];
self.secondImageLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, self.firstImage.frame.origin.y + self.firstImage.frame.size.height + 10, self.quarterSize, 20)];
self.secondImageLabel.text = [self.dataTwo objectForKey:#"title"];
self.secondImageLabel.numberOfLines = 2;
self.secondImageLabel.textColor = [UIColor whiteColor];
self.secondImageLabel.font = [UIFont fontWithName:#"HelveticaNeue" size:13];
[self.secondImageLabel sizeToFit];
[secondView addSubview:self.secondImageLabel];
self.thirdImageLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, self.firstImagele.frame.origin.y + self.firstImage.frame.size.height + 10, self.quarterSize, 20)];
self.thirdImageLabel.text = [self.dataThree objectForKey:#"title"];
self.thirdImageLabel.numberOfLines = 2;
self.thirdImageLabel.textColor = [UIColor whiteColor];
self.thirdImageLabel.font = [UIFont fontWithName:#"HelveticaNeue" size:13];
[self.thirdImageLabel sizeToFit];
[thirdView addSubview:self.thirdImageLabel];
self.firstImageOwnerLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, self.firstImageLabel.frame.origin.y + self.firstImageLabel.frame.size.height, self.quarterSize, 30)];
self.firstImageOwnerLabel.text = [self.dataOne objectForKey:#"owner"];
self.firstImageOwnerLabel.numberOfLines = 1;
self.firstImageOwnerLabel.textColor = [UIColor lightGrayColor];
self.firstImageOwnerLabel.font = [UIFont fontWithName:#"HelveticaNeue" size:11];
[firstView addSubview:self.firstImageOwnerLabel];
[self.view addSubview:firstView];
self.secondImageOwnerLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, self.firstImageLabel.frame.origin.y + self.firstImageLabel.frame.size.height, self.quarterSize, 30)];
self.secondImageOwnerLabel.text = [self.dataTwo objectForKey:#"owner"];
self.secondImageOwnerLabel.numberOfLines = 1;
self.secondImageOwnerLabel.textColor = [UIColor lightGrayColor];
self.secondImageOwnerLabel.font = [UIFont fontWithName:#"HelveticaNeue" size:11];
[secondView addSubview:self.secondImageOwnerLabel];
[self.view addSubview:secondView];
self.thirdImageOwnerLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, self.firstImageLabel.frame.origin.y + self.firstImageLabel.frame.size.height, self.quarterSize, 30)];
self.thirdImageOwnerLabel.text = [self.dataThree objectForKey:#"owner"];
self.thirdImageOwnerLabel.numberOfLines = 1;
self.thirdImageOwnerLabel.textColor = [UIColor lightGrayColor];
self.thirdImageOwnerLabel.font = [UIFont fontWithName:#"HelveticaNeue" size:11];
[thirdView addSubview:self.thirdImageOwnerLabel];
[self.view addSubview:thirdView];
}
}
- (UIColor *)paperColorLightBlue500 { return UIColorFromRGB(0x03a9f4); }
- (void)openFirstImage:(UITapGestureRecognizer *)recognizer {
NSLog(#"Please open the First Image");
}
- (void)openSecondImage:(UITapGestureRecognizer *)recognizer {
NSLog(#"Please open the Second Image");
}
- (void)openThirdImage:(UITapGestureRecognizer *)recognizer {
NSLog(#"Please open the Third Image");
}
- (id)initWithCoder:(NSCoder *)aDecoder {
if (self = [super initWithCoder:aDecoder]) {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(userDefaultsDidChange:)
name:NSUserDefaultsDidChangeNotification
object:nil];
}
return self;
}
- (UIEdgeInsets)widgetMarginInsetsForProposedMarginInsets:(UIEdgeInsets)defaultMarginInsets
{
return UIEdgeInsetsZero;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
self.firstImageLabel = nil;
self.secondImageLabel = nil;
self.thirdImageLabel = nil;
self.firstImageOwnerLabel = nil;
self.secondImageOwnerLabel = nil;
self.thirdImageOwnerLabel = nil;
}
- (void)widgetPerformUpdateWithCompletionHandler:(void (^)(NCUpdateResult))completionHandler {
// Perform any setup necessary in order to update the view.
// If an error is encountered, use NCUpdateResultFailed
// If there's no update required, use NCUpdateResultNoData
// If there's an update, use NCUpdateResultNewData
completionHandler(NCUpdateResultNewData);
}
- (void)userDefaultsDidChange:(NSNotification *)notification {
[self updateNumberLabelText];
}
- (void)updateNumberLabelText {
NSUserDefaults *defaults = [[NSUserDefaults alloc] initWithSuiteName:#"group.testapp.TodayExtensionDefaults"];
self.dataOne = [defaults objectForKey:#"dataOne"];
self.dataTwo = [defaults objectForKey:#"dataTwo"];
self.dataThree = [defaults objectForKey:#"dataThree"];
for (id key in self.dataOne) {
NSLog(#"key: %#, value: %# \n", key, [self.dataOne objectForKey:key]);
}
for (id key in self.dataThree) {
NSLog(#"key: %#, value: %# \n", key, [self.dataThree objectForKey:key]);
}
}
#end
The only error I get is that the Extension is Terminated due to Memory Error.
Extensions have much lower memory limits than normal apps. You'll have to investigate why you extension is using so much memory. Perhaps there's a leak.

iOS: Creating a Text Area with Clickable hashtags and usernames

I'm trying to create a view with text that contains clickable hashtags (#abc) and usernames (#xyz). Initially I subclassed UILabel and although I got it working, the area was only clickable if the text was at a range less that 102 characters in (the boundingRectForCharacterRange function below started returning {0, 0}).
Next I tried to subclass a UITextView and it increased this limit to about 300 characters, but still the same problem.
Anyone have any ideas about how I can increase this limit? I use up to 1000 characters.
My subclassed UITextView code is below (I know I've not completed the protocol bit yet but hopefully you get my issues...):
ClickableTextView.h
#import <UIKit/UIKit.h>
#protocol ClickableTextViewDelegate <NSObject>
#required
- (void)hashTagPressed:(NSString*)hashtagName;
- (void)usernamePressed:(NSString*)username;
#end
#interface ClickableTextView : UITextView
{
NSMutableArray *hashtags;
NSMutableArray *usernames;
UIColor *clickableColor;
//id <ClickableTextViewDelegate> labelDelegate;
}
//#property (nonatomic,strong) id labelDelegate;
- (void)setClickableColor:(UIColor*)color;
#end
ClickableTextView.m
#import "ClickableTextView.h"
#implementation ClickableTextView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
clickableColor = [UIColor blueColor];
self.userInteractionEnabled = YES;
self.editable = NO;
self.scrollEnabled = NO;
self.textContainerInset = UIEdgeInsetsZero;
UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(respondToTapGesture:)];
tapRecognizer.numberOfTapsRequired = 1;
[self addGestureRecognizer:tapRecognizer];
}
return self;
}
- (void)setText:(NSString*)text
{
[super setText:text];
NSMutableAttributedString *attrString = [[NSMutableAttributedString alloc] initWithString:text];
[self setAttributedText:attrString];
if(!hashtags) {
hashtags = [NSMutableArray array];
}
if(!usernames) {
usernames = [NSMutableArray array];
}
[hashtags removeAllObjects];
[usernames removeAllObjects];
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"#(\\w+)" options:0 error:nil];
NSArray *matches = [regex matchesInString:text options:0 range:NSMakeRange(0, text.length)];
for(NSTextCheckingResult *match in matches) {
NSRange tagRange = [match rangeAtIndex:1];
tagRange.location--;
tagRange.length++;
[attrString addAttribute:NSForegroundColorAttributeName value:clickableColor range:tagRange];
CGRect tagRect = [self boundingRectForCharacterRange:tagRange];
[hashtags addObject:[NSDictionary dictionaryWithObjects:#[[text substringWithRange:tagRange], [NSNumber numberWithInt:tagRect.origin.x], [NSNumber numberWithInt:tagRect.origin.y], [NSNumber numberWithInt:tagRect.size.width], [NSNumber numberWithInt:tagRect.size.height]] forKeys:#[#"text", #"x", #"y", #"width", #"height"]]];
}
regex = [NSRegularExpression regularExpressionWithPattern:#"#(\\w+)" options:0 error:nil];
matches = [regex matchesInString:text options:0 range:NSMakeRange(0, text.length)];
for(NSTextCheckingResult *match in matches) {
NSRange userRange = [match rangeAtIndex:1];
userRange.location--;
userRange.length++;
[attrString addAttribute:NSForegroundColorAttributeName value:clickableColor range:userRange];
CGRect userRect = [self boundingRectForCharacterRange:userRange];
[usernames addObject:[NSDictionary dictionaryWithObjects:#[[text substringWithRange:userRange], [NSNumber numberWithInt:userRect.origin.x], [NSNumber numberWithInt:userRect.origin.y], [NSNumber numberWithInt:userRect.size.width], [NSNumber numberWithInt:userRect.size.height]] forKeys:#[#"text", #"x", #"y", #"width", #"height"]]];
}
[self setAttributedText:attrString];
[self sizeToFit];
}
- (CGRect)boundingRectForCharacterRange:(NSRange)range
{
NSTextStorage *textStorage = [[NSTextStorage alloc] initWithAttributedString:[self attributedText]];
NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];
[textStorage addLayoutManager:layoutManager];
NSTextContainer *textContainer = [[NSTextContainer alloc] initWithSize:[self bounds].size];
[layoutManager addTextContainer:textContainer];
NSRange glyphRange;
[layoutManager characterRangeForGlyphRange:range actualGlyphRange:&glyphRange];
return [layoutManager boundingRectForGlyphRange:glyphRange inTextContainer:textContainer];
}
- (void)respondToTapGesture:(UITapGestureRecognizer*)recognizer
{
CGPoint point = [recognizer locationInView:self];
for(NSDictionary *hashtag in hashtags) {
CGRect tagRect = CGRectMake([[hashtag objectForKey:#"x"] floatValue], [[hashtag objectForKey:#"y"] floatValue], [[hashtag objectForKey:#"width"] floatValue], [[hashtag objectForKey:#"height"] floatValue]);
if(CGRectContainsPoint(tagRect, point)) {
NSLog(#"Hashtag: %#", [hashtag objectForKey:#"text"]);
}
}
for(NSDictionary *username in usernames) {
CGRect userRect = CGRectMake([[username objectForKey:#"x"] floatValue], [[username objectForKey:#"y"] floatValue], [[username objectForKey:#"width"] floatValue], [[username objectForKey:#"height"] floatValue]);
if(CGRectContainsPoint(userRect, point)) {
NSLog(#"Username: %#", [username objectForKey:#"text"]);
}
}
}
- (void)setClickableColor:(UIColor*)color
{
clickableColor = color;
if(self.text) {
[self setText:self.text];
}
}
#end
ViewController.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
ClickableTextView *textView = [[ClickableTextView alloc] initWithFrame:CGRectMake(50, 100, self.view.frame.size.width - 100, 100)];
textView.text = #"A #quick test. A quick test. A quick test. A quick test. A quick test. A quick test. A quick test. A quick test. A quick test. A quick test. A #quick test. A quick test. A quick test. A quick test. A quick test. A quick test. A quick test. A quick test. A quick test. A quick test. A quiiiiiiick #test";
[self.view addSubview:textView];
}
#end
Please help!

Change image of a scrollview or replace the array of images

I have a problem with changing images in the scrollview, the scrollview problem is that depending on the action that makes me have to change the image that contains other, as I do not change the picture or the array of images, I need help, thanks
- (void)viewDidLoad
{
[super viewDidLoad];
NSMutableArray *imgNames = [[NSMutableArray alloc] initWithObjects:#"cooper.png", #"cabrio.png",#"country.png", nil];
NSMutableArray *imgArray = [[NSMutableArray alloc] init];
UIImageView *tempImageView;
for(NSString *name in imgNames) {
tempImageView = [[UIImageView alloc] init];
tempImageView.contentMode = UIViewContentModeScaleAspectFit;
tempImageView.image = [UIImage imageNamed:name];
[imgArray addObject:tempImageView];
}
CGSize pageSize = scrollView.frame.size;
NSUInteger page = 0;
for(UIView *view in imgArray) {
[scrollView addSubview:view];
view.frame = CGRectMake(pageSize.width * page++ + 10, 0, pageSize.width - 20, pageSize.height);
}
scrollView.contentSize = CGSizeMake(pageSize.width * [imgArray count], pageSize.height);
}
- (IBAction)btnAction:(id)sender {
NSMutableArray *imgNames = [[NSMutableArray alloc] initWithObjects:#"hello.png", #"bye.png",#"trues.png", nil];
NSMutableArray *imgArray = [[NSMutableArray alloc] init];
UIImageView *tempImageView;
for(NSString *name in imgNames) {
tempImageView = [[UIImageView alloc] init];
tempImageView.contentMode = UIViewContentModeScaleAspectFit;
tempImageView.image = [UIImage imageNamed:name];
[imgArray addObject:tempImageView];
}
CGSize pageSize = scrollView.frame.size;
NSUInteger page = 0;
for(UIView *view in imgArray) {
[scrollView addSubview:view];
view.frame = CGRectMake(pageSize.width * page++ + 10, 0, pageSize.width - 20, pageSize.height);
}
scrollView.contentSize = CGSizeMake(pageSize.width * [imgArray count], pageSize.height);
}
}
You can directly set the image alone if UIImageView is already allocated in viewDidLoad like,
for(UIImageView *view in imgArray) {
view.image = [UIImage imageNamed:[imgNames objectAtIndex:[imgArray indexOfObject:view]]]
}

DTAttributedTextView in ios

In my ios app
im rendering html tags
using
DTAttributedTextView
this is the rest of the coding structure
//create the custom label to get positions
UILabel *customLabel = [[UILabel alloc]initWithFrame:CGRectMake(lblContent.frame.origin.x, lblContent.frame.origin.y,lblContent.frame.size.width,lblContent.frame.size.height)];
customLabel.text = _artistDetail.strContent;
customLabel.numberOfLines = 0;
[customLabel sizeToFit];
[lblContent removeFromSuperview];
CGRect frame = CGRectMake(customLabel.frame.origin.x, customLabel.frame.origin.y,customLabel.frame.size.width,500);
NSString *htmlText = HTML_DIV_TAG;
htmlText = [htmlText stringByAppendingFormat:#"%#%#",_artistDetail.strContent,#"</div>"];
htmlText = [htmlText stringByReplacingOccurrencesOfString:#"''" withString:#"'"];
NSData *data = [htmlText dataUsingEncoding:NSUTF8StringEncoding];
NSAttributedString *string = [[NSAttributedString alloc] initWithHTML:data options:nil documentAttributes:NULL];
[DTAttributedTextContentView setLayerClass:[CATiledLayer class]];
DTAttributedTextView *_textView = [[DTAttributedTextView alloc] initWithFrame:frame];
_textView.textDelegate = self;
_textView.attributedString = string;
[_textView sizeToFit];
_textView.autoresizesSubviews = YES;
[self.contentView addSubview:_textView];
Now i want to increas the label according to the content height
Is thr any way to do it
Thanks
Have you tried something like:
[DTAttributedTextContentView setLayerClass:[CATiledLayer class]];
DTAttributedTextView *_textView = [[DTAttributedTextView alloc] initWithFrame:frame];
_textView.textDelegate = self;
_textView.attributedString = string;
CGRect frame = _textView.frame;
CGSize size = _textView.contentSize;
frame.size.height = size.height;
_textView.frame = frame;
[self.contentView addSubview:_textView];

Resources