How to optimize UITextView - objective-c

I use UITextView as the rich text view
- (void)openPhotoLibrary {
[self presentImagePickerController:UIImagePickerControllerSourceTypePhotoLibrary];
}
- (void)presentImagePickerController:(UIImagePickerControllerSourceType)sourceType {
UIImagePickerController *picker = [[UIImagePickerController alloc] init];
picker.delegate = self;
picker.sourceType = sourceType;
[self presentViewController:picker animated:YES completion:nil];
}
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary<NSString *,id> *)info {
[picker dismissViewControllerAnimated:YES completion:nil];
UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
NSData *dataImage = UIImageJPEGRepresentation(image, 0.1);
UIImage *resultImage = [UIImage imageWithData:dataImage];
[self insertImageOfTheTextView:self.textview withImage:resultImage];
[picker dismissViewControllerAnimated:YES completion:nil];
}
- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
[picker dismissViewControllerAnimated:YES completion:nil];
}
- (void)insertImageOfTheTextView:(UITextView *)textView withImage:(UIImage *)image {
if (image == nil || ![image isKindOfClass:[UIImage class]]) {
return;
}
NImageAttachment *attachment = [[NImageAttachment alloc] init];
attachment.image = image;
attachment.imageSize = [self scaleImageSize:image];
NSAttributedString *imageAttributedString = [self insertImageDoneAutoReturn:[NSAttributedString attributedStringWithAttachment:attachment]];
[textView.textStorage insertAttributedString:imageAttributedString atIndex:textView.selectedRange.location];
textView.selectedRange = NSMakeRange(textView.selectedRange.location + 3, 0);
}
- (CGSize)scaleImageSize:(UIImage *)image {
CGFloat imageScale = image.size.width / image.size.height;
CGFloat imageWidth = self.view.frame.size.width;
CGSize imageSize = CGSizeMake(imageWidth, imageWidth / imageScale);
return imageSize;
}
- (NSAttributedString *)insertImageDoneAutoReturn:(NSAttributedString *)imageAttributedString {
NSAttributedString *returnAttributedString = [[NSAttributedString alloc] initWithString:#"\n"];
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithAttributedString:imageAttributedString];
[attributedString appendAttributedString:returnAttributedString];
[attributedString insertAttributedString:returnAttributedString atIndex:0];
return attributedString;
}
If the photo I picked from PhotoLibrary is small, the uitextivew will be fine, if the photo is large, the uitextview will be slow when I scroll or edit the uitextview, it seems stucks, how can I optimize it?

Related

UICollectionViewCell memory leak when user click image loading all images(150) in slide objective c

Basically I want to display images in slide which are coming from server. it works for maximum 10 images. And I am displaying them in UICollectionView with Cell but when I click folder that has 100 +more images it gives me error that memory leak because it loads all images (3Gigabytes+) in one time when clicked. I tried to call by index it loads clicked image but when i swipe other images are not loading.
I resized all images with Bitmap all works but Image has too many details when zooming it's impossple to read. Is there any other way to load images one by one when Cell calls image?
Here is my LocalFileDeailViewController.m
(void) initPaging {
CGFloat width = self.scrollView.frame.size.width;
CGFloat height = self.scrollView.frame.size.height;
CGRect innerFrame = CGRectMake(0, 0, width, height);
for (int i = 0; i < self.fileList.count; i++) {
__block UIImage* Image = nil;
if ([self.ListType isEqual: #"url"]) {
NSData * imageData = [[NSData alloc] initWithContentsOfURL: [NSURL URLWithString: self.fileList[i]]];
Image = [UIImage imageWithData: imageData];
} else {
NSString * filePath = (NSString *) self.fileList[i];
NSString *imageFullPath = [self.filePath stringByAppendingPathComponent:filePath];
BOOL isLoadAble = [[NSFileManager defaultManager] fileExistsAtPath:imageFullPath];
if ( isLoadAble ) {
Image = [UIImage imageWithContentsOfFile:imageFullPath];
} else {
//TODO 이미지가 없는경우 뭘 표시하나?
continue;
}
}
CGRect frame = CGRectMake(i * width, 0, width, height);
UIImageView *imgV = [[UIImageView alloc] initWithFrame:innerFrame] ;
[imgV setImage:Image];
[imgV setContentMode:UIViewContentModeScaleAspectFit];
[imgV setBackgroundColor:[UIColor blackColor]];
imgV.tag = VIEW_FOR_ZOOM_TAG;
UIScrollView *psv = [[UIScrollView alloc] initWithFrame:frame];
[psv setBackgroundColor:[UIColor blackColor]];
psv.minimumZoomScale = ZOOM_MIN;
psv.maximumZoomScale = ZOOM_MAX;
psv.zoomScale = ZOOM_SCALE;
psv.contentSize = imgV.bounds.size;
psv.delegate = self.scrollDelegate;
psv.showsHorizontalScrollIndicator = NO;
psv.showsVerticalScrollIndicator = NO;
[psv addSubview:imgV];
[self.contentView addSubview:psv];
[self.pages addObject:psv];
}
self.contentViewWidth.constant = self.fileList.count * width;
[self.scrollView setContentOffset:CGPointMake(width * self.index, 0) animated:NO];
And LocalImageGridViewController.m
#define CELL_ID #"LocalFileImageCollectionViewCell"
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
LocalFileImageCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:CELL_ID forIndexPath:indexPath];
NSString * fileName = (NSString *) self.fileList[indexPath.row];
[ cell prepareForReuse];
cell.layer.shouldRasterize = YES;
cell.layer.rasterizationScale = [UIScreen mainScreen].scale;
[cell setImagePath:self.filePath imageName:fileName index: indexPath.row];
if (![cell superview]){
[_collectionView addSubview:cell];
}
return cell;
#pragma mark <UICollectionViewDelegate>
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
[collectionView deselectItemAtIndexPath:indexPath animated:NO]; NSLog(#"indexpath >>>> %#", indexPath);
// NSString * fileName = (NSString *) self.fileList[indexPath.row];
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:[NSBundle mainBundle]];
LocalFileImageDetailViewController *vc = [storyboard instantiateViewControllerWithIdentifier:#"LocalFileImageDetailViewController"];
// [vc setFileName:fileName];
[vc setFileName:self.fileName];
[vc setFilePath:self.filePath];
[vc setFileList:self.fileList];
[vc setIndex:indexPath.item];
[self.navigationController pushViewController:vc animated:YES];
NSLog(#"vc >>>> %#", vc);
}
You should use UICollectionView in LocalFileDeailViewController instead of UIScrollView. Collection view load cells by demand, not on load view controller

Image is not fit into circle UIImageview in iOS Objective-C?

I know it's a common question but i am stack to implement it. I have an imageview which weight and height are equal. When I pick an image from media library some image are fit into circle but some image not fit into circle imageview.
Can any one suggest me how to set any type of image set into circle image view?
Because I want to implement to user can set his/her profile image. so user insert any type of image or any resolution, I need to crop that image but I am not able to do this. And also I don't prefer any 3rd library.
Here is my code:
-(void)btnImgAct //Button Action
{
UIImagePickerController *imagePickerController = [[UIImagePickerController alloc] init];
imagePickerController.delegate = self;
if ([UIImagePickerController isSourceTypeAvailable:
UIImagePickerControllerSourceTypePhotoLibrary])
{
imagePickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
}
[self presentViewController:imagePickerController animated:YES completion:nil];
}
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)image editingInfo:(NSDictionary *)Info
{
UIImage *pickerImage=[[UIImage alloc]init];
pickerImage=image;
imageDataPicker =[[NSData alloc] init];
imageDataPicker = UIImageJPEGRepresentation(pickerImage, 0.1); //For resize
if([imageDataPicker length]<2097152) //bytes 1048576
{
[[picker parentViewController] dismissModalViewControllerAnimated:YES];
[self dismissViewControllerAnimated:YES completion:nil];
picker=nil;
[self SubmitImage1:pickerImage];
}
-(void)SubmitImage1:(UIImage *)image
{
EditProfileImage.image=image; //insert image into imageview
//Create circle imageview
EditProfileImage.layer.cornerRadius = EditProfileImage.frame.size.width / 2;
[EditProfileImage setContentMode:UIViewContentModeScaleAspectFit];
EditProfileImage.layer.masksToBounds = YES;
EditProfileImage.layer.borderWidth = 3.0f;
EditProfileImage.layer.borderColor = [UIColor blackColor].CGColor;
}
enter image description here
enter image description here
Removed a few unnecessary lines and changed the image view to do aspect fill of the resulting image. I have tested this and it works fine with whatever images I tried.
-(IBAction)buttonPressed:(UIButton *)sender
{
UIImagePickerController *imagePickerController = [[UIImagePickerController alloc] init];
imagePickerController.delegate = self;
if ([UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypePhotoLibrary]) {
imagePickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
}
[self presentViewController:imagePickerController animated:YES completion:nil];
}
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingImage:(UIImage *)image editingInfo:(NSDictionary *)Info
{
NSData *imageDataPicker = UIImageJPEGRepresentation(image, 0.1); //For resize
if([imageDataPicker length]<2097152) //bytes 1048576
{
[self dismissViewControllerAnimated:YES completion:nil];
[self SubmitImage1:image];
}
}
// UIViewContentModeScaleAspectFill will fill the entire view
-(void)SubmitImage1:(UIImage *)image
{
_EditProfileImage.image = image;
_EditProfileImage.layer.cornerRadius = _EditProfileImage.frame.size.width / 2;
_EditProfileImage.contentMode = UIViewContentModeScaleAspectFill;
_EditProfileImage.layer.masksToBounds = YES;
_EditProfileImage.layer.borderWidth = 3.0f;
_EditProfileImage.layer.borderColor = [UIColor blackColor].CGColor;
}

Change color NavigationBar in detail screen CNContactPickerViewController

I have a problem like in this question, but answers don't help me. I want that colors navigation bar in seconds screen will be like a first screen. iOS 9 or later.
- (void) showAdressBookActionForIOSNineOrLater {
CNContactPickerViewController * newPicker = [[CNContactPickerViewController alloc] init];
newPicker.delegate = self;
NSDictionary *attributesNormal = [NSDictionary dictionaryWithObjectsAndKeys:
[UIFont appFont_Headline], NSFontAttributeName,
[UIColor appColor_white_0], NSForegroundColorAttributeName, nil];
//appColor_white_0 my custom color APP_RGBA(255.0f, 255.0f, 255.0f, 1.0f); appFont_Headline - [UIFont HelveticaNeueRegularFont:fontSize];
newPicker.navigationController.navigationBar.titleTextAttributes = attributesNormal;
newPicker.navigationController.navigationBar.translucent = NO;
newPicker.navigationController.navigationBar.barStyle = UIBarStyleBlack;
newPicker.navigationController.navigationBar.tintColor = [UIColor appColor_white_0];
[[UIBarButtonItem appearanceWhenContainedInInstancesOfClasses:#[[UINavigationController class]]] setTintColor:[UIColor appColor_white_0]];
[[UINavigationBar appearanceWhenContainedInInstancesOfClasses:#[[UINavigationController class]]] setTintColor:[UIColor appColor_white_0]];
[[UINavigationBar appearanceWhenContainedInInstancesOfClasses:#[[UINavigationController class]]] setBarTintColor:[UIColor appColor_white_0]];
[[UINavigationBar appearanceWhenContainedInInstancesOfClasses:#[[UINavigationController class]]] setTitleTextAttributes:attributesNormal];
newPicker.predicateForEnablingContact = [NSPredicate predicateWithFormat:#"phoneNumbers.#count > 0"];
newPicker.predicateForSelectionOfContact = [NSPredicate predicateWithFormat:#"phoneNumbers.#count == 1"];
newPicker.predicateForSelectionOfProperty = [NSPredicate predicateWithFormat:#"key == phoneNumber"];
newPicker.displayedPropertyKeys = #[CNContactPhoneNumbersKey];
//
[[self currentNavigationController] presentViewController:newPicker animated:YES completion:nil];
And implement delegate methods:
- (void)contactPicker:(CNContactPickerViewController *)picker didSelectContactProperty:(CNContactProperty *)contactProperty{
CNContact *contact = contactProperty.contact;
NSString *identify = contactProperty.identifier;
NSString * selectedNumber = #"";
for (CNLabeledValue<CNPhoneNumber*>* number in contact.phoneNumbers) {
if ([number.identifier isEqualToString:identify]) {
selectedNumber = ((CNPhoneNumber *)number.value).stringValue;
}
} [self.currentNavigationController.presentedViewController dismissViewControllerAnimated:YES completion:nil];
}
- (void)contactPickerDidCancel:(CNContactPickerViewController *)picker {
[self.currentNavigationController.presentedViewController dismissViewControllerAnimated:YES completion:nil];
}
Screen story:

didFinishPickingMediaWithInfo for two images

I have two image views named obsPic1 and obsPic2
They receive an image from picker/camera. This works fine for one image but any more and the images are the same. How do I do this for more than one image? Ive tried accessing the buttons sender tag but get undeclared identifier error, ive also tried using if statements. Whats the correct way to do this?
- (IBAction)addObsPhotoBtnPresssed:(id)sender {
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
LogCmd();
UIImagePickerController *imagePicker = [[UIImagePickerController alloc] init];
imagePicker.sourceType = UIImagePickerControllerSourceTypeCamera;
imagePicker.delegate = self;
imagePicker.allowsEditing = YES;
[self.editController presentModalViewController:imagePicker animated:YES];
//iPad
}
else {
if (self.pop) {
[self.pop dismissPopoverAnimated:YES];
}
UIImagePickerController *imagePickerController = [[UIImagePickerController alloc] init];
imagePickerController.sourceType = UIImagePickerControllerSourceTypeCamera;
imagePickerController.delegate = self;
imagePickerController.allowsEditing = YES;
self.pop=[[UIPopoverController alloc] initWithContentViewController:imagePickerController];
[self.pop presentPopoverFromRect:((UIButton *)sender).bounds inView:sender permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
}
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
[picker dismissModalViewControllerAnimated:YES];
UIImage *image = [info objectForKey:UIImagePickerControllerEditedImage];
self.obsPic1.backgroundColor = [UIColor whiteColor];
self.obsPic1.image = image;
NSData *imageData = UIImagePNGRepresentation(image);
NSString *path = [ICUtils pathForDocument:#"obsPic.png"];
[imageData writeToFile:path atomically:NO];
UIImage *image2 = [info objectForKey:UIImagePickerControllerEditedImage];
self.obsPic2.backgroundColor = [UIColor whiteColor];
self.obsPic2.image = image2;
NSData *imageData2 = UIImagePNGRepresentation(image);
NSString *path2 = [ICUtils pathForDocument:#"obsPic2.png"];
[imageData2 writeToFile:path2 atomically:NO];
}
Both your image and image2 reference the same image:
[info objectForKey:UIImagePickerControllerEditedImage]
Are you perhaps looking to reference the Edited and Original images:
UIImage *image = [info objectForKey:UIImagePickerControllerEditedImage];
and
UIImage *image2 = [info objectForKey:UIImagePickerControllerOriginalImage];
or vice versa? If OTOH you're trying to allow for multiple image picking look into ELCImagePickerController

uiview animatewithduration completion continues after view is dismissed

I have a modelViewController that contains a UIView animation. When the animation block finishes it calls itself, thus looping.
When I dismiss the modelViewController (dismissInfo) which calls [_starView removeFromSuperview], the function gets called over and over very rapidly with the NSLog line being printed multiple times a second.
#implementation InfoVC
{
NSArray *imgs;
NSString *currentImg;
}
- (void)viewDidLoad
{
[super viewDidLoad];
_imageview.contentMode = UIViewContentModeLeft;
_imageviewUnder.contentMode = UIViewContentModeLeft;
imgs = [NSArray arrayWithObjects:
#"01.jpg",
#"02.jpg",
#"03.jpg",
#"04.jpg",
#"05.jpg",
#"06.jpg",
nil];
_imgInt = (arc4random()%6);
[self initialImage];
}
- (void)viewWillAppear:(BOOL)animated{
}
- (void)viewDidAppear:(BOOL)animated{
NSLog(#"viewDidAppear");
}
- (void)initialImage
{
_starView.contentMode = UIViewContentModeLeft;
_imageviewUnder.contentMode = UIViewContentModeLeft;
currentImg = [imgs objectAtIndex:_imgInt];
UIImage *image = [UIImage imageNamed:currentImg];
_starView = [[UIImageView alloc] initWithImage:image];
// Size the image view to the image (it's bigger)
_starView.bounds = CGRectMake(0.0, 44.0, 416.0, 416.0);
NSLog(#"tarView.center %#", NSStringFromCGPoint(_starView.center) );
_starView.alpha=1;
int nextImgInt = _imgInt + 1 ;
if (nextImgInt>5)
{
nextImgInt=0;
}
NSString *nextImg = [imgs objectAtIndex:nextImgInt];
UIImage *nextImage = [UIImage imageNamed:nextImg];
[_imageviewUnder setImage:nextImage];
[self.view sendSubviewToBack:_imageviewUnder];
_imgInt++;
if (_imgInt>5) {
_imgInt=0;
}
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView animateWithDuration:7.6f
delay:0.1f
options:UIViewAnimationCurveLinear
animations:^{
[_starView setCenter:CGPointMake(112, 208)];
[_starView setAlpha:0.0f];
}
completion:^(BOOL finished){
[_starView removeFromSuperview];
[self initialImage];
}];
[self.view insertSubview:_starView atIndex:1];
}
- (void)visitTwitter
{
NSURL *URL = [NSURL URLWithString:#"http://twitter.com/"];
SVWebViewController *webViewController = [[SVWebViewController alloc] initWithURL:URL];
[self.navigationController pushViewController:webViewController animated:YES];
}
- (IBAction)dismissInfo:(id)sender
{
[self cleanup];
[self dismissModalViewControllerAnimated:YES];
}
- (void)cleanup
{
[_starView.layer removeAllAnimations];
[self.view.layer removeAllAnimations];
[_starView removeFromSuperview];
}
- (void)viewDidUnload
{
[self cleanup];
[super viewDidUnload];
}
#end
Make yourself an animating flag, set true in viewDidLoad, and false in cleanup. Then check it in your initialImage method:
if ( ! animating )
return;
This is the second time I've come across this. One possible cause is the method being initialised in viewDidLoad but the subview and image not being ready in time (it seems the first pass of the animation loop doesn't work adding a ghost to the machine).
I moved the call to ViewDidAppear, making sure to display an initialisation image to stop the white flash. At last an infinite animation in a modal window
- (void)viewDidLoad
{
[super viewDidLoad];
_imageview.contentMode = UIViewContentModeLeft;
_imageviewUnder.contentMode = UIViewContentModeLeft;
imgs = [NSArray arrayWithObjects:
#"01.jpg",
#"02.jpg",
#"03.jpg",
#"04.jpg",
#"05.jpg",
#"06.jpg",
nil];
_imgInt = (arc4random()%6);
currentImg = [imgs objectAtIndex:_imgInt];
UIImage *image = [UIImage imageNamed:currentImg];
[_imageviewUnder setImage:image];
}
- (void)viewDidAppear:(BOOL)animated{
[self initialImage];
}
- (void)initialImage
{
currentImg = [imgs objectAtIndex:_imgInt];
UIImage *image = [UIImage imageNamed:currentImg];
_starView = [[UIImageView alloc] initWithImage:image];
// Size the image view to the image (it's bigger)
_starView.bounds = CGRectMake(0.0, 44.0, 416.0, 416.0);
NSLog(#"initialImage");
_starView.alpha=1;
[self.view insertSubview:_starView atIndex:1];
int nextImgInt = _imgInt + 1 ;
if (nextImgInt>5)
{
nextImgInt=0;
}
NSString *nextImg = [imgs objectAtIndex:nextImgInt];
UIImage *nextImage = [UIImage imageNamed:nextImg];
[_imageviewUnder setImage:nextImage];
[self.view sendSubviewToBack:_imageviewUnder];
_imgInt++;
if (_imgInt>5) {
_imgInt=0;
}
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:7.6];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationCurve:UIViewAnimationCurveLinear];
//[UIView setAnimationDidStopSelector:#selector(initialImage) ];
[_starView setCenter:CGPointMake(112, 208)];
[_starView setAlpha:0.0f];
[UIView commitAnimations];
[self performSelector:#selector(initialImage) withObject:nil afterDelay:7.6];
}
- (IBAction)dismissInfo:(id)sender
{
[self cleanup];
[self dismissModalViewControllerAnimated:YES];
}
- (void)cleanup
{
[NSObject cancelPreviousPerformRequestsWithTarget:self];
[_starView.layer removeAllAnimations];
[self.view.layer removeAllAnimations];
[_starView removeFromSuperview];
}
If you just want to create a looping animation, the best thing to do is use the option: 'UIViewAnimationOptionRepeat'. For example:
[UIView animateWithDuration:2.0
delay:0.0f
options:UIViewAnimationOptionRepeat
animations:^{
[myUIViewThing setCenter:CGPointMake(myUIViewThing.center.x - 100, myUIViewThing.center.y)];
}
completion:nil];