UIActivityViewController Crash - uiactivityviewcontroller

i have no idea why the uiactivityviewcontroller crash when i use the prensentViewController method.
it is weird, anyone has any clue?
the program is running fine not untile when i use the presenviewcontroller.
#import "ActivityViewController.h"
#interface ActivityViewController ()
#end
#implementation ActivityViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
[self createTextField];
[self createButton];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void) createTextField
{
self.myTextField = [[UITextField alloc] initWithFrame:CGRectMake(20.0f, 35.0f, 280.0f, 30.0f)];
self.myTextField.translatesAutoresizingMaskIntoConstraints = NO;
self.myTextField.borderStyle = UITextBorderStyleRoundedRect;
self.myTextField.placeholder =#"Enter text to Share";
self.myTextField.delegate = self;
[self.view addSubview:self.myTextField];
}
- (void) createButton
{
self.myButtonShare = [UIButton buttonWithType:UIButtonTypeRoundedRect];
self.myButtonShare.frame = CGRectMake(20.0f, 80.0f, 280.0f, 40.0f);
self.myButtonShare.translatesAutoresizingMaskIntoConstraints = NO;
[self.myButtonShare setTitle:#"Share" forState:UIControlStateNormal];
[self.myButtonShare addTarget:self action:#selector(handleShare:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:self.myButtonShare];
}
- (void) handleShare:(id)sender
{
NSArray *activities = #[UIActivityTypeMail,UIActivityTypeMessage];
self.myActivityViewController = [[UIActivityViewController alloc] initWithActivityItems:#[self.myTextField.text] applicationActivities:activities];
[self presentViewController:self.myActivityViewController animated:YES completion:nil];
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[self.myButtonShare resignFirstResponder];
return YES;
}

What ccjensen said is all correct, except you can actually restrict your share sheet to just Mail & Message by excluding activities, this way for example:
activityController.excludedActivityTypes = #[ UIActivityTypeCopyToPasteboard, UIActivityTypeAddToReadingList ];
This would only show the email sharing by default.

The documentation for UIActivityViewController's initWithActivityItems:applicationActivities: states that the NSArray passed as the second parameter (applicationActivities) should be an "array of UIActivity". You are passing in an array containing the two objects UIActivityTypeMail and UIActivityTypeMessage which are of type NSString *const. It seems that you were hoping that you could restrict the share sheet to only show the mail and messages activity, which is currently not possible.
To stop the crash from happening, change your code to:
<...>
self.myActivityViewController = [[UIActivityViewController alloc] initWithActivityItems:#[self.myTextField.text] applicationActivities:nil];
<...>

Related

UItableview on second page and want to nevigate in third page how it is possible?

I have UITableview in second page then I try to navigate into third page but problem is that my code is not working. Here is the code for both AppDelegate.m file and also SecondViewController.m file,
Plz check the code and give me suggestion what i am doing wrong
SecondViewController.m file code
- (void)tableView: (UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
ThirdViewController *third = [[ThirdViewControllerr alloc] initWithNibName: #"ThirdViewControllerr" bundle:nil];
ForthViewController *forth = [[ForthViewControlle alloc] initWithNibName: #"ForthViewController" bundle:nil];
if(indexPath.row==0)
{
[[self navigationController] pushViewController:third animated:YES];
}
if(indexPath.row==1)
{
[[self navigationController] pushViewController:forth animated:YES];
}
In AppDelegate.m file i write the code for Secondviewcontroller in witch using UITableview, also i have initialized the UINavigationController inside AppDelegate.m file.If anyone have idea reply me as soon as possible,
without use UINavigationController inside AppDelegate.m file its possible for UItableview Navigation
AppsDelegate.m file
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.viewController = [[MobileViewController alloc] initWithNibName:#"MobileViewController" bundle:nil];
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
return YES;
self.window1=[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen]bounds]];
self.viewController1=[[HealthCalculatorsViewController alloc]initWithNibName:#"HealthCalculatorsViewController" bundle:nil];
UINavigationController *nav1=[[UINavigationController alloc]initWithRootViewController:_viewController1];
self.window1.rootViewController=nav1;
[self.window1 makeKeyAndVisible];
return YES;
}
Please guide me.
Thanks.
add this in your Appdelegate.h
UINavigationController * navController;
and this in your Appdelegate.m
if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone)
{
FirstViewController * viewPhone =[[FirstViewController alloc]initWithNibName:#"FirstViewController_iPhone" bundle:nil];
navController=[[UINavigationController alloc]initWithRootViewController:viewPhone];
}
else
{
FirstViewControllerController * viewPad =[[FirstViewControllerController alloc]initWithNibName:#"FirstViewController_iPad" bundle:nil];
navController=[[UINavigationController alloc]initWithRootViewController:viewPad];
}
navController.navigationBar.tintColor = [UIColor blackColor];
self.window.rootViewController=navController;
on your button click
- (IBAction)Btn_Pressed:(id)sender {
SecondViewController * second=[[SecondViewController alloc]init];
if (UI_USER_INTERFACE_IDIOM()==UIUserInterfaceIdiomPhone)
second = [[SecondViewController alloc] initWithNibName:#"SecondViewController_iPhone" bundle:nil];
else
second = [[SecondViewController alloc] initWithNibName:#"SecondViewController_iPad" bundle:nil];
[self.navigationController pushViewController:lagrangae animated:YES];
}
if you dont want navigation bar just hide it by
[[self navigationController] setNavigationBarHidden:YES animated:YES];

When and how is collectionView:viewForSupplementaryElementOfKind:atIndexPath: called?

I'm trying to implement a native-Calendar-app-like timeline view with UICollectionView and custom layout. And I'm new to it.
Here is where my problem come from.
I'm using Decoration View to implement those background gridlines, and trying to use Supplementary View to make the time labels (near the gridlines), and will use Cell to make the events but not that far yet.
But before doing the events, I found when I run it all the supplementary views are not working, no matter if I have cell or not. And I found my collectionView:viewForSupplementaryElementOfKind:atIndexPath: method is not called.
So I'm wondering how and when this method is called? What could be leading to my situation that it's not called?
Actually, is it good to make those time labels with supplementary view? I'm not sure about it since I do need them to be visible even when there's no event (no cell/item in section).
Here is my code:
View Controller
- (void)viewDidLoad
{
[super viewDidLoad];
self.collectionView.backgroundColor = [UIColor whiteColor];
[self.collectionView registerClass:TodayCellKindTask.class forCellWithReuseIdentifier:CellKindTaskIdentifier];
[self.collectionView registerClass:TodayTimelineTimeHeader.class forSupplementaryViewOfKind:TimelineKindTimeHeader withReuseIdentifier:TimelineTimeHeaderIdentifier];
[self.timelineViewLayout registerClass:TodayTimelineTileWhole.class forDecorationViewOfKind:TimelineKindTileWholeHour];
[self.timelineViewLayout registerClass:TodayTimelineTileHalf.class forDecorationViewOfKind:TimelineKindTileHalfHour];
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return 5;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
TodayCellKindTask *cellTask = [collectionView dequeueReusableCellWithReuseIdentifier:CellKindTaskIdentifier forIndexPath:indexPath];
return cellTask;
}
- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath {
NSLog(#"viewForSupplementaryElementOfKind");
TodayTimelineTimeHeader *timeHeader = [self.collectionView dequeueReusableSupplementaryViewOfKind:TimelineKindTimeHeader withReuseIdentifier:TimelineTimeHeaderIdentifier forIndexPath:indexPath];
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDate *today = [NSDate date];
NSDateComponents *comps = [calendar components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit) fromDate:today];
[comps setHour:indexPath.item];
timeHeader.time = [calendar dateFromComponents:comps];
return timeHeader;
}
Custom Layout
// in prepareLayout
NSMutableDictionary *timeHeaderAttributes = [NSMutableDictionary dictionary];
CGSize headerSize = [TodayTimelineTimeHeader defaultSize];
CGFloat headerOffsetY = (tileSize.height - headerSize.height) / 2;
for (NSInteger hour = 24; hour >= 0; hour--) {
NSIndexPath *timeHeaderIndexPath = [NSIndexPath indexPathForItem:hour inSection:0];
UICollectionViewLayoutAttributes *currentTimeHeaderAttributes = [UICollectionViewLayoutAttributes layoutAttributesForSupplementaryViewOfKind:TimelineKindTimeHeader withIndexPath:timeHeaderIndexPath];
CGFloat headerPosY = hour * 2 * tileSize.height + headerOffsetY;
currentTimeHeaderAttributes.frame = CGRectMake(TimeHeaderPosX, headerPosY, headerSize.width, headerSize.height);
timeHeaderAttributes[timeHeaderIndexPath] = currentTimeHeaderAttributes;
}
self.timelineTileAttributes[TimelineKindTimeHeader] = timeHeaderAttributes;
// layoutAttributesForSupplementaryViewOfKind
- (UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryViewOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath {
return self.timelineTileAttributes[kind][indexPath];
}
// layoutAttributesForElementsInRect
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect {
NSMutableArray *allAttributes = [NSMutableArray arrayWithCapacity:self.timelineTileAttributes.count];
[self.timelineTileAttributes enumerateKeysAndObjectsUsingBlock:^(NSString *elementIdentifier,
NSDictionary *elementsInfo,
BOOL *stop) {
[elementsInfo enumerateKeysAndObjectsUsingBlock:^(NSIndexPath *indexPath,
UICollectionViewLayoutAttributes *attributes,
BOOL *stop) {
if (CGRectIntersectsRect(rect, attributes.frame)) {
[allAttributes addObject:attributes];
}
}];
}];
return allAttributes;
}
// collectionViewContentSize
- (CGSize)collectionViewContentSize {
CGSize tileSize = [TodayTimelineTileWhole defaultSize];
CGFloat contentHeight = tileSize.height * self.numberOfTiles;
return CGSizeMake(tileSize.width, contentHeight);
}
I tried not to post all the code here since that'd be a lot, but let me know if you need to know others.
Any tip is appreciated!
Pine
So, this problem is solved, and the reason was my stupid mistake, setting those views' position x out of the screen, and due to that the method was not called. Nothing else.
I found this reason by logging out each view's frame in prepareLayout, and found the x position was wrong. I got this position from the retina design so…
I used supplementary view and it was working without any problem.
My lesson: no worries, calm down. This can save you time from making mistake.

I have a UICollectionView and i want to show an image in a Cell, that goes to a normal ViewController. How do i do that?

I have a UICollectionViewController (with a navigation controller) and i want to show an image in a Cell that 'pushes' to a normal ViewController (different by every image). How do i do that?
Seem you want to build photo gallery by UICollectionView.
If use storyBoard, use segue
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"showDetail"])
{
NSIndexPath *selectedIndexPath = [[self.collectionView indexPathsForSelectedItems] objectAtIndex:0];
// load the image, to prevent it from being cached we use 'initWithContentsOfFile'
NSString *imageNameToLoad = [NSString stringWithFormat:#"%d_full", selectedIndexPath.row];
NSString *pathToImage = [[NSBundle mainBundle] pathForResource:imageNameToLoad ofType:#"JPG"];
UIImage *image = [[UIImage alloc] initWithContentsOfFile:pathToImage];
DetailViewController *detailViewController = [segue destinationViewController];
detailViewController.image = image;
}
}
If use nib: inside didSelectItemAtIndexPath, use self.navigationController push.
-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath{
NSString *imageNameToLoad = [NSString stringWithFormat:#"%d_full", indexPath.row];
NSString *pathToImage = [[NSBundle mainBundle] pathForResource:imageNameToLoad ofType:#"JPG"];
UIImage *image = [[UIImage alloc] initWithContentsOfFile:pathToImage];
DetailViewController *detailViewController = [[DetailViewController alloc] initWithNibName:#"DetailViewController" bundle:nil];
detailViewController.image = image;
[self.navigationController pushViewController:detailViewController animated:YES];
}
Sample code from Apple:
https://developer.apple.com/library/ios/#samplecode/CollectionView-Simple/Introduction/Intro.html
CollecionView tutorial: http://www.raywenderlich.com/22324/beginning-uicollectionview-in-ios-6-part-12

How to access user input from UIAlertView completion block without delegation?

Using iOS6:
I would like to retrieve the text entered by a user into a UITextField associated with the UIAlertView. I am aware that I could achieve the desired result with a delegate however I am curious about solving this issue with a callback function as I believe this may be an interesting pattern. I began by examining a common pattern for category extension of the UIAlertView class. Code below. Thanks in advance for any suggestions.
import <UIKit/UIKit.h>
#interface UIAlertView (Block)
- (id)initWithTitle:(NSString *)title message:(NSString *)message completion:(void (^)(BOOL cancelled, NSInteger buttonIndex, UITextField *textField))completion cancelButtonTitle:(NSString *)cancelButtonTitle otherButtonTitles:(NSString *)otherButtonTitles, ... NS_REQUIRES_NIL_TERMINATION;
#end
The .m for the category follows:
#import "UIAlertView+Block.h"
#import <objc/runtime.h>
static char const * const alertCompletionBlockTag = "alertCompletionBlock";
#implementation UIAlertView (Block)
- (id)initWithTitle:(NSString *)title
message:(NSString *)message
completion:(void (^)(BOOL cancelled, NSInteger buttonIndex))completion
cancelButtonTitle:(NSString *)cancelButtonTitle
otherButtonTitles:(NSString *)otherButtonTitles, ... {
self = [self initWithTitle:title message:message delegate:self cancelButtonTitle:cancelButtonTitle otherButtonTitles:nil ];
if (self) {
objc_setAssociatedObject(self, alertCompletionBlockTag, completion, OBJC_ASSOCIATION_COPY);
va_list _arguments;
va_start(_arguments, otherButtonTitles);
for (NSString *key = otherButtonTitles; key != nil; key = (__bridge NSString *)va_arg(_arguments, void *)) {
[self addButtonWithTitle:key];
}
va_end(_arguments);
}
[self setAlertViewStyle:UIAlertViewStylePlainTextInput];
return self;
}
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
id completion = objc_getAssociatedObject(self, alertCompletionBlockTag);
[self complete:completion index:buttonIndex];
}
- (void) complete:(void (^)(BOOL cancelled, NSInteger buttonIndex))block index:(NSInteger)buttonIndex {
BOOL _cancelled = (buttonIndex == self.cancelButtonIndex);
block(_cancelled, buttonIndex );
objc_setAssociatedObject(self, alertCompletionBlockTag, nil, OBJC_ASSOCIATION_COPY);
//objc_removeAssociatedObjects(block);
}
#end
Usage for the category is set below. The main problem is my inability to reference the UIAlertView textField at Index 0 from within the completion block.
[[[UIAlertView alloc] initWithTitle:#"Add"
message:#"Add New Asset Type"
completion:^(BOOL cancelled, NSInteger buttonIndex){
if (!cancelled) {
//call on completion of UISheetAction ???
NSLog(#"%#",needToAccessUIAlertView._textFields[0]);
}
}
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"OK", nil] show];
So basically you want to access the alert view from the block. You can do something like this:
__block __weak UIAlertView *alertViewWeak;
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Add"
message:#"Add New Asset Type"
completion:^(BOOL cancelled, NSInteger buttonIndex){
if (!cancelled) {
//call on completion of UISheetAction ???
NSLog(#"%#",[alertViewWeak textFieldAtIndex:0]);
}
}
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"OK", nil];
alertViewWeak = alertView;
[alertView show];
If you want to make a category by yourself, above is good enough.
But, there are many classes that uses delegation pattern. Do you want to make categories one by one?
There is REKit. With it, you can use that classes as if they were Block-based:
UIAlertView *alertView;
alertView = [[UIAlertView alloc]
initWithTitle:#"title"
message:#"message"
delegate:nil
cancelButtonTitle:#"Cancel"
otherButtonTitles:#"OK", nil
];
[alertView
respondsToSelector:#selector(alertView:didDismissWithButtonIndex:)
withKey:nil
usingBlock:^(id receiver, UIAlertView *alertView, NSInteger buttonIndex) {
// Do something…
}
];
alertView.delegate = alertView;
Try this library Here is another useful library to do the same. http://ichathan.com/2014/08/19/ichalertview/

UIWebview is not loading on IOS 6

shouldStartLoadWithRequest:navigationType and webViewDidStartLoad methods of UIWebview gets called once but after that the activityIndicator keeps on rotating (starts in webViewDidStartLoad) and none of the delegate methods webViewDidFinishLoad or didFailLoadWithError gets called. This is an issue on IOS 6 only.
This is working for me in iOS 5 and 6. Make sure you connect your outlets in Interface Builder. You should probably do some sort of check to see if Internet access is available. I'm doing it with the Apple Reachability class:
Header:
#import <UIKit/UIKit.h>
#interface HelpWebViewController : UIViewController <UIWebViewDelegate>
{
IBOutlet UIWebView *webView;
IBOutlet UIActivityIndicatorView *activityIndicator;
}
#property (nonatomic, strong) UIWebView *webView;
#property (nonatomic, strong) UIActivityIndicatorView *activityIndicator;
#property (nonatomic, strong) NSString *webHelpURLString;
- (void)webViewDidStartLoad:(UIWebView *)webView; //a web view starts loading
- (void)webViewDidFinishLoad:(UIWebView *)webView;//web view finishes loading
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error; //web view failed to load
#end
Implementation file:
#import "HelpWebViewController.h"
#import "Reachability.h" // Needs System Configuration Framework
#interface HelpWebViewController ()
#end
#implementation HelpWebViewController
#synthesize webView = ivWebView;
#synthesize activityIndicator = ivActivityIndicator;
#synthesize webHelpURLString = ivWebHelpURLString;
-(BOOL)reachable {
Reachability *r = [Reachability reachabilityWithHostName:#"apple.com"];
NetworkStatus internetStatus = [r currentReachabilityStatus];
if(internetStatus == NotReachable) {
return NO;
}
return YES;
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
NSURL *webHelpURL = [NSURL URLWithString:#"support.apple.com"];
NSURLRequest *myrequest = [NSURLRequest requestWithURL:webHelpURL];
[self.webView loadRequest:myrequest];
self.webView.scalesPageToFit = YES;
if ([self reachable]) {
NSLog(#"Reachable");
}
else {
NSLog(#"Not Reachable");
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(#"cantOpenWebPageAlertTitle", #"Cannot Open Page - UIAlert can't open web page")
message:NSLocalizedString(#"cantOpenWebPageAlertMessage", #"The page cannot be opened because you're not connected to the Internet.")
delegate:nil
cancelButtonTitle:NSLocalizedString(#"cantOpenWebPageAlertOKButton", #"OK - accept alert")
otherButtonTitles:nil];
[alert show];
alert = nil;
}
}
- (void)webViewDidStartLoad:(UIWebView *)webView
{
[self.activityIndicator startAnimating];
}
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
[self.activityIndicator stopAnimating];
}
- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
{
[self.activityIndicator stopAnimating];
}
#end

Resources