I am trying to share images via UIActivityViewController similar to this. However if I share several images, Twitter and Facebook will disappear in the UIActivityViewController.
Is there a way to share one image for both Twitter and Facebook, several images for mail as attachment?
EDIT:
// return different string depends on the type
CustomActivityItemProvider *textProvider = [[CustomActivityItemProvider alloc] initWithText:textContent url:url title:textTitle];
NSMutableArray *applicationActivities = [NSMutableArray array];
NSMutableArray *activityItems = [#[
textProvider,
image,
url
] mutableCopy];
// custom applicationActivities
...
// If add multiple images, facebook and twitter will not show up
for(int i = 0; i < [images count]; ++i)
{
if(images[i] != image) [activityItems addObject:images[i]];
}
UIActivityViewController *activityController = [[UIActivityViewController alloc] initWithActivityItems:activityItems
applicationActivities:applicationActivities];
[activityController setValue:textTitle forKey:#"subject"];
activityController.excludedActivityTypes = excludeActivities;
[self presentViewController:activityController animated:YES completion:nil];
Is there a way similar to the UIActivityItemProvider?
A similar way to textActivityItemProvider I've end up using:
ImageActivityItemProvider.h
#import <UIKit/UIKit.h>
#interface ImageActivityItemProvider : UIActivityItemProvider
#property (nonatomic, strong, readonly) UIImage *image;
#property (nonatomic, readonly) NSInteger index;
#property (nonatomic, readonly) NSInteger shouldShowIndex;
- (instancetype)initWithImage:(UIImage*)image index:(NSInteger)index shouldShowIndex:(NSInteger)shouldShowIndex;
#end
ImageActivityItemProvider.m
#import "ImageActivityItemProvider.h"
#interface ImageActivityItemProvider ()
#property (nonatomic, strong) UIImage *image;
#property (nonatomic) NSInteger index;
#property (nonatomic) NSInteger shouldShowIndex;
#end
#implementation ImageActivityItemProvider
- (instancetype)initWithImage:(UIImage*)image index:(NSInteger)index shouldShowIndex:(NSInteger)shouldShowIndex
{
// make sure the placeholder is nil instead of the image
self = [super initWithPlaceholderItem:nil];
if (self)
{
self.image = image;
self.index = index;
self.shouldShowIndex = shouldShowIndex;
}
return self;
}
- (id)item
{
if (
[self.activityType isEqualToString:UIActivityTypeMail] ||
self.index == self.shouldShowIndex
)
{
return self.image;
}
return self.placeholderItem;
}
#end
Related
I am trying to include MWPhotoBrowser in my project
When its used as given in the sample it working fine.
But when a new viewcontroller is subclassed from MWPhotoBrowser, photos are not loaded except empty black theme.
Delegate methods are not getting called. As the controller is subclass of MWPhotoBrowser, I assume there is no need to set it explicitly.
Storyboard is used and the nib class in it is set.
.h file
#interface MDRPhotoViewerController : MWPhotoBrowser
{
NSMutableArray *_selections;
}
#property (nonatomic, strong) NSMutableArray *photos;
#property (nonatomic, strong) NSMutableArray *thumbs;
#property (nonatomic, strong) NSMutableArray *assets;
#property (nonatomic, strong) NSMutableIndexSet *optionIndices;
#property (nonatomic, strong) UITableView *tableView;
#property (nonatomic, strong) ALAssetsLibrary *ALAssetsLibrary;
- (void)loadAssets;
#end
**.m file **
- (void)viewWillAppear:(BOOL)animated
{
NSMutableArray *photos = [[NSMutableArray alloc] init];
NSMutableArray *thumbs = [[NSMutableArray alloc] init];
//mwphotobrowser options setup
BOOL displayActionButton = YES;
BOOL displaySelectionButtons = NO;
BOOL displayNavArrows = NO;
BOOL enableGrid = YES;
BOOL startOnGrid = NO;
BOOL autoPlayOnAppear = NO;
//loading data
NSArray *photosDataArray = [MDRDataController GetPhotos]; //creating array
for (NSString *urlString in photosDataArray) { //Formating the data source for images
NSString *urlFullString = [NSString stringWithFormat:#"%#%#",KBASEURL,urlString];
//Photos
[photos addObject:[MWPhoto photoWithURL:[NSURL URLWithString:urlFullString]]];
//thumbs
[thumbs addObject:[MWPhoto photoWithURL:[NSURL URLWithString:urlFullString]]];
}
// Options
self.photos = photos;
self.thumbs = thumbs;
// Create browser
self.displayActionButton = displayActionButton;
self.displayNavArrows = displayNavArrows;
self.displaySelectionButtons = displaySelectionButtons;
self.alwaysShowControls = displaySelectionButtons;
self.zoomPhotosToFill = YES;
self.enableGrid = enableGrid;
self.startOnGrid = startOnGrid;
self.enableSwipeToDismiss = NO;
self.autoPlayOnAppear = autoPlayOnAppear;
[self setCurrentPhotoIndex:0];
// Test custom selection images
// browser.customImageSelectedIconName = #"ImageSelected.png";
// browser.customImageSelectedSmallIconName = #"ImageSelectedSmall.png";
// Reset selections
if (displaySelectionButtons) {
_selections = [NSMutableArray new];
for (int i = 0; i < photos.count; i++) {
[_selections addObject:[NSNumber numberWithBool:NO]];
}
}
self.title = #"Phots";
//[self reloadData];
}
Debugging performed
Considering the image template of mwphotobrowser, tried reloading the code.
Shifted the code between viewwillappear and viewdidload.
Doesn't MWPhotoBrowser support this way or am i doing it wrong ?
For those who stumble upon this later...
If you look at MWPhotoBrowser.m you'll see various initializers:
- (id)init {
if ((self = [super init])) {
[self _initialisation];
}
return self;
}
- (id)initWithDelegate:(id <MWPhotoBrowserDelegate>)delegate {
if ((self = [self init])) {
_delegate = delegate;
}
return self;
}
- (id)initWithPhotos:(NSArray *)photosArray {
if ((self = [self init])) {
_fixedPhotosArray = photosArray;
}
return self;
}
- (id)initWithCoder:(NSCoder *)decoder {
if ((self = [super initWithCoder:decoder])) {
[self _initialisation];
}
return self;
}
The problem is there's no awakeFromNib initializer. Simplest solution is to fork the project and create the awakeFromNib initializer.
I was trying to solve assignment 2 from Stanford iOS7 development (Matchismo card game)
The game works fine. Now I have to add the Restart function. If the user press on the restart button, the game restarts (it deals new cards and it resets the score)
my game model is the #property (nonatomic, strong) CardMatchingGame *game;
this is the code for the CardMatchingGame.m:
#import "CardMatchingGame.h"
#import "PlayingCardDeck.h"
#interface CardMatchingGame()
#property (nonatomic, readwrite) NSInteger score;
#property (nonatomic, strong) NSMutableArray *cards;
#end
#implementation CardMatchingGame
static const int MATCH_BONUS = 4;
static const int MATCH_PENALTY = 2;
static const int COST_TO_CHOOSE = 1;
-(NSMutableArray *)cards{
if(!_cards) _cards = [[NSMutableArray alloc]init];
return _cards;
}
-(instancetype)initWithCardCount:(NSUInteger)count usingDeck:(Deck *)deck{
self = [super init];
if(self){
for(int i=0; i < count; i++){
Card *card = [deck drawRandomCard];
if(card){
[self.cards addObject:card];
} else{
self = nil;
break;
}
}
}
return self;
}
-(void)chooseCardAtIndex:(NSUInteger)index{
Card *card = [self cardAtIndex:index];
if(!card.isMatched){
if(card.isChosen){
card.chosen = NO;
} else{
for(Card *otherCard in self.cards){
if(otherCard.isChosen && !otherCard.isMatched){
int matchScore = [card match:#[otherCard]];
if(matchScore){
self.score += matchScore * MATCH_BONUS;
card.matched = YES;
otherCard.matched = YES;
} else{
self.score -= MATCH_PENALTY;
otherCard.chosen = NO;
}
break;
}
}
self.score -= COST_TO_CHOOSE;
card.chosen = YES;
}
}
}
-(Card *)cardAtIndex:(NSUInteger)index{
return (index < [self.cards count]) ? self.cards[index] : nil;
}
#end
here is my CardGameViewController.m:
#import "CardGameViewController.h"
#import "PlayingCardDeck.h"
#import "CardMatchingGame.h"
#interface CardGameViewController ()
#property (nonatomic, strong) Deck *deck;
#property (nonatomic, strong) CardMatchingGame *game;
#property (strong, nonatomic) IBOutletCollection(UIButton) NSArray *cardsCollection;
#property (weak, nonatomic) IBOutlet UILabel *scoreLabel;
#end
#implementation CardGameViewController
#synthesize game = _game;
-(CardMatchingGame *)game{
if(!_game) _game = [[CardMatchingGame alloc] initWithCardCount:[self.cardsCollection count]
usingDeck:self.deck];
return _game;
}
-(Deck *)deck{
if(!_deck) _deck = [[PlayingCardDeck alloc] init];
return _deck;
}
- (IBAction)touchRestartButton:(id)sender {
self.game = nil;
[self updateUI];
}
- (IBAction)touchCardButton:(UIButton *)sender {
int chosenButtonIndex = [self.cardsCollection indexOfObject:sender];
[self.game chooseCardAtIndex:chosenButtonIndex];
[self updateUI];
}
-(void)updateUI{
for(UIButton *cardButton in self.cardsCollection){
int buttonIndex = [self.cardsCollection indexOfObject:cardButton];
Card *card = [self.game cardAtIndex:buttonIndex];
[cardButton setTitle:[self titleForCard:card] forState:UIControlStateNormal];
[cardButton setBackgroundImage:[self backgroundImageForCard:card] forState:UIControlStateNormal];
cardButton.enabled = !card.isMatched;
}
self.scoreLabel.text = [NSString stringWithFormat:#"Score: %d", self.game.score];
}
-(NSString *)titleForCard:(Card *)card{
return card.isChosen ? card.contents : #"";
}
-(UIImage *)backgroundImageForCard:(Card *)card{
return [UIImage imageNamed: card.isChosen ? #"cardfront" : #"cardback"];
}
#end
In order to restart the game, I think I should simply re-initialize the property CardMatchingGame *game.
This is what I tried to do, by setting self.game = nil; Then it should automatically be re-initialized in the getter of game.
This is, indeed, the solution that I found on the internet. However, in my program it doesn't work. *game is set to nil and never restored, so the game ends when you click restart.
Could you please help me to figure out why self.game = nil doesn't work in my case?
- (IBAction)startover:(UIButton *)sender {
self.game= [[CardMatchingGame alloc] initWithCardCount:[self.cardButtons count] usingDeck:[self createDeck]];
[self updateUI];
}
If your program has the lazy init style recommended, there is no need for a new method such as start over. You are correct to set self.game to nil, now a call the the getter will start a new instance of the game. I did it by making a call to UIUpdate right after the self.game = nil. That has a call to the getter and lazily inits a new instance of the game.
Please help....I'm losing my mind trying to figure out this problem.
I'm fairly new to iOS so don't go too hard on me if it's something obvious! ;)
I'm using xcode 4.6 and targeting iPhone6.1 Simulator.
I get the following error when starting up my app:
EXC_BAD_ACCESS code = 2
There are hundres of threads appearing in Debug Navigator which leads to to believe there is some sort of infinite loop somewhere (I just cannot see where).
The error occurs beside (id)init in PlayingCardDeck.m after entering it from ViewController.m at line:
Card *card = [self.deck drawRandonCard];
ViewConrtoller:
#import "ViewController.h"
#import "PlayingCardDeck.h"
#interface ViewController ()
#property (weak, nonatomic) IBOutlet UILabel *flipsLabel;
#property (nonatomic) int flipCount;
#property (strong, nonatomic) Deck *deck;
#property (strong, nonatomic) IBOutletCollection(UIButton) NSArray *cardButtons;
#end
#implementation ViewController
#synthesize deck = _deck;
- (IBAction)flipCard:(UIButton *)sender {
sender.selected = !sender.isSelected;
self.flipCount++;
}
- (void)setFlipCount:(int)flipCount
{
_flipCount = flipCount;
self.flipsLabel.text = [NSString stringWithFormat:#"Flips: %d", self.flipCount];
}
- (Deck *)deck
{
if (!_deck) _deck = [[PlayingCardDeck alloc] init];
return _deck;
}
- (void)setCardButtons:(NSArray *)cardButtons
{
_cardButtons = cardButtons;
for (UIButton *cardButton in cardButtons)
{
Card *card = [self.deck drawRandonCard];
[cardButton setTitle:card.contents forState:UIControlStateSelected];
}
}
#end
Deck.m
#import "Deck.h"
#interface Deck()
#property (strong, nonatomic) NSMutableArray *cards;
#end
#implementation Deck
- (NSMutableArray *)cards
{
if (!_cards) _cards = [[NSMutableArray alloc] init];
return _cards;
}
- (void)addCard:(Card *)card atTop:(BOOL)atTop
{
if (atTop)
{
[self.cards insertObject:card atIndex:0];
}
else
{
[self.cards addObject:card];
}
}
- (Card *)drawRandonCard
{
Card *randomCard = nil;
if (self.cards.count)
{
unsigned index = arc4random() % self.cards.count;
randomCard = self.cards[index];
[self.cards removeObjectAtIndex:index];
}
return randomCard;
}
#end
PlayingCardDeck.m
#import "PlayingCardDeck.h"
#import "PlayingCard.h"
#implementation PlayingCardDeck
- (id)init
{
self = [self init];
if (self)
{
for (NSString *suit in [PlayingCard validSuits])
{
for (NSUInteger rank=1; rank <= [PlayingCard maxRank]; rank++)
{
PlayingCard *card = [[PlayingCard alloc] init];
card.suit = suit;
card.rank = rank;
[self addCard:card atTop:YES];
}
}
}
return self;
}
#end
In PlayerCardDeck.m self = [self init] should be self = [super init]. That's causing the infinite loop.
I'm making a Card game and trying to call UIImages from an object's instance variable to update a UIImageView
I have a Deck object, which has an NSArray instance variable of Card objects.
Each Card object has a few instance variables, one of which is an UIImage that I'm trying to display in a UIImageView....and this is where I'm having a problem
The storyboard isn't displaying the UIImageView and i'm not getting any compile errors
The UIImageView that I'm trying to update is cardDisplay (ViewController.h)
Here's some snippets from my code
ViewController.h
#import "Deck.h"
#import "Card.h"
#interface ViewController : UIViewController
{
UIImageView *cardDisplay;
}
#property (nonatomic, retain) IBOutlet UIImageView *cardDisplay;
#end
ViewController.m
#import "ViewController.h"
#import "Deck.h"
#import "Card.h"
#implementation ViewController
#synthesize cardDisplay;
- (void)viewDidLoad
{
[super viewDidLoad];
Deck *deck = [[Deck alloc]init];
NSLog(#"%#", deck);
for (id cards in deck.cards) {
NSLog(#"%#", cards);
}
self.cardDisplay = [[UIImageView alloc] initWithImage:
[[deck.cards objectAtIndex:0 ] cardImage]];
}
#end
Card.h
#interface Card : NSObject
{
NSString *valueAsString, *suitAsString;
NSInteger faceValue, countValue;
Suit suit;
UIImage *cardImage;
}
#property (nonatomic, retain) NSString *valueAsString;
#property (nonatomic, retain) NSString *suitAsString;
#property (nonatomic) NSInteger faceValue;
#property (nonatomic) NSInteger countValue;
#property (nonatomic) Suit suit;
#property (nonatomic) UIImage *cardImage;
- (id) initWithFaceValue:(NSInteger)aFaceValue countValue:(NSInteger)aCountValue
suit:(Suit)aSuit cardImage:(UIImage*)aCardImage;
#end
Deck.h
#import "Card.h"
#interface Deck : NSObject
{
NSMutableArray *cards;
}
#property(nonatomic, retain)NSMutableArray *cards;
#end
Deck.m
#import "Deck.h"
#import "Card.h"
#implementation Deck
#synthesize cards;
- (id) init
{
if(self = [super init])
{
cards = [[NSMutableArray alloc] init];
NSInteger aCount, picNum = 0;
for(int suit = 0; suit < 4; suit++)
{
for(int face = 1; face < 14; face++, picNum++)
{
if (face > 1 && face < 7)
aCount = 1;
else if (face > 6 && face < 10)
aCount = 0;
else
aCount = -1;
NSString *path = [[NSBundle mainBundle] bundlePath];
NSString *imagePath = [path stringByAppendingPathComponent:
[NSString stringWithFormat:#"/cards/card_%d.png",picNum]];
UIImage *output = [UIImage imageNamed:imagePath];
Card *card = [[Card alloc] initWithFaceValue:(NSInteger)face
countValue:(NSInteger)aCount
suit:(Suit)suit
cardImage:(UIImage *)output];
[cards addObject:card];
}
}
}
return self;
}
#end
This line:
self.cardDisplay = [[UIImageView alloc] initWithImage:
[[deck.cards objectAtIndex:0 ] cardImage]];
should be:
self.cardDisplay.image = [[deck.cards objectAtIndex:0 ] cardImage];
You need to set the image on the image view you created in IB, not create a new one. Doing it this way doesn't keep you from doing what you want with the timer later.
I have gone through a few tutorials including the sample app included
with Three20 and cannot figure out why photos aren't showing up in my
TTPhotoViewController. I actually find it pretty hard to debug.
Below is the code I have. Any thoughts on why images will not load
and how to debug it would be great. I get a completely black view in
between my bottom tabbar and upper nav bar. I also see left and right
arrows overlayed on the black view which seems to be for navigating
photos although I thought it was supposed to display a thumbnail
gallery.
// A TTPhoto class
// Photo.h
#import <Foundation/Foundation.h>
#import <Three20/Three20.h>
#interface Photo : NSObject <TTPhoto> {
NSString *_caption;
NSString *_urlLarge;
NSString *_urlSmall;
NSString *_urlThumb;
id <TTPhotoSource> _photoSource;
CGSize _size;
NSInteger _index;
}
#property (nonatomic, copy) NSString *caption;
#property (nonatomic, copy) NSString *urlLarge;
#property (nonatomic, copy) NSString *urlSmall;
#property (nonatomic, copy) NSString *urlThumb;
#property (nonatomic, assign) id <TTPhotoSource> photoSource;
#property (nonatomic) CGSize size;
#property (nonatomic) NSInteger index;
- (id)initWithCaption:(NSString *)caption urlLarge:(NSString
*)urlLarge urlSmall:(NSString *)urlSmall urlThumb:(NSString *)urlThumb
size:(CGSize)size;
#end
// Photo.m
#import "Photo.h"
#implementation Photo
#synthesize caption = _caption;
#synthesize urlLarge = _urlLarge;
#synthesize urlSmall = _urlSmall;
#synthesize urlThumb = _urlThumb;
#synthesize photoSource = _photoSource;
#synthesize size = _size;
#synthesize index = _index;
- (id)initWithCaption:(NSString *)caption urlLarge:(NSString
*)urlLarge urlSmall:(NSString *)urlSmall urlThumb:(NSString *)urlThumb
size:(CGSize)size {
if ((self = [super init])) {
self.caption = caption;
self.urlLarge = urlLarge;
self.urlSmall = urlSmall;
self.urlThumb = urlThumb;
self.size = size;
self.index = NSIntegerMax;
self.photoSource = nil;
}
return self;
}
- (void) dealloc {
self.caption = nil;
self.urlLarge = nil;
self.urlSmall = nil;
self.urlThumb = nil;
[super dealloc];
}
#pragma mark TTPhoto
- (NSString*)URLForVersion:(TTPhotoVersion)version {
switch (version) {
case TTPhotoVersionLarge:
return _urlLarge;
case TTPhotoVersionMedium:
return _urlLarge;
case TTPhotoVersionSmall:
return _urlSmall;
case TTPhotoVersionThumbnail:
return _urlThumb;
default:
return nil;
}
}
#end
// A TTPhotoSource class
// PhotoSet.h
#import <Foundation/Foundation.h>
#import "Three20/Three20.h"
#interface PhotoSet : TTURLRequestModel <TTPhotoSource> {
NSString *_title;
NSArray *_photos;
NSArray* _tempPhotos;
NSTimer* _fakeLoadTimer;
}
#property (nonatomic, copy) NSString *title;
#property (nonatomic, retain) NSArray *photos;
- (id) init;
#end
// PhotoSet.m
#import "PhotoSet.h"
#import "Photo.h"
#implementation PhotoSet
#synthesize title = _title;
#synthesize photos = _photos;
- (id) init {
_title = #"Test photo album";
_photos = [[NSArray alloc] initWithObjects:
[[[Photo alloc] initWithCaption:#"coming soon"
urlLarge:#"http://farm5.static.flickr.com/
4066/4653156849_0905e6b58e_o.jpg"
urlSmall:#"http://farm5.static.flickr.com/
4066/4653156849_0d15f0e3f0_s.jpg"
urlThumb:#"http://farm5.static.flickr.com/
4066/4653156849_0d15f0e3f0_s.jpg"
size:CGSizeMake(220, 112)] autorelease],
[[[Photo alloc] initWithCaption:#"coming soon 2"
urlLarge:#"http://farm5.static.flickr.com/
4023/4653774402_05e6acd995_o.jpg"
urlSmall:#"http://farm5.static.flickr.com/
4009/4653157237_c2f5f59e0d_s.jpg"
urlThumb:#"http://farm5.static.flickr.com/
4009/4653157237_c2f5f59e0d_s.jpg"
size:CGSizeMake(220, 112)] autorelease],
[[[Photo alloc] initWithCaption:#"coming soon 2"
urlLarge:#"http://farm5.static.flickr.com/
4023/4653774402_05e6acd995_o.jpg"
urlSmall:#"http://farm5.static.flickr.com/
4009/4653157237_c2f5f59e0d_s.jpg"
urlThumb:#"http://farm5.static.flickr.com/
4009/4653157237_c2f5f59e0d_s.jpg"
size:CGSizeMake(220, 112)] autorelease],
[[[Photo alloc] initWithCaption:#"coming soon 2"
urlLarge:#"http://farm5.static.flickr.com/
4023/4653774402_05e6acd995_o.jpg"
urlSmall:#"http://farm5.static.flickr.com/
4009/4653157237_c2f5f59e0d_s.jpg"
urlThumb:#"http://farm5.static.flickr.com/
4009/4653157237_c2f5f59e0d_s.jpg"
size:CGSizeMake(220, 112)] autorelease],
nil];
for (int i = 0; i < _photos.count; ++i) {
id<TTPhoto> photo = [_photos objectAtIndex:i];
if ((NSNull*)photo != [NSNull null]) {
NSLog(#"in here 65434");
photo.photoSource = self;
photo.index = i;
}
}
return self;
}
- (void) dealloc {
self.title = nil;
self.photos = nil;
[super dealloc];
}
#pragma mark TTModel
- (BOOL)isLoading {
return NO;
}
- (BOOL)isLoaded {
return YES;
}
#pragma mark TTPhotoSource
- (NSInteger)numberOfPhotos {
return _photos.count;
}
- (NSInteger)maxPhotoIndex {
return _photos.count-1;
}
- (id<TTPhoto>)photoAtIndex:(NSInteger)photoIndex {
if (photoIndex < _photos.count) {
return [_photos objectAtIndex:photoIndex];
} else {
return nil;
}
}
#end
// A TTPhotoViewController
// EventDetailViewController.h
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import <Three20/Three20.h>
#import "PhotoSet.h"
#class Event;
#interface EventDetailViewController :
TTPhotoViewController<UINavigationControllerDelegate,
UIImagePickerControllerDelegate> {
NSArray *photos;
Event *event;
PhotoSet *_photoSet;
}
#property (nonatomic, retain) NSArray *photos;
#property (nonatomic, retain) Event *event;
#property (nonatomic, retain) PhotoSet *photoSet;
- (id)initWithEvent:(Event *)e;
// EventDetailViewController.m
#import "EventDetailViewController.h"
#import "Event.h"
#import "PhotoSet.h"
#import "Photo.h"
#implementation EventDetailViewController
#synthesize photos;
#synthesize event;
#synthesize photoSet = _photoSet;
#pragma mark -
#pragma mark Initialization
- (void)viewDidLoad {
self.photoSet = [[PhotoSet alloc] init];
self.photoSource = self.photoSet;
}
- (id)initWithEvent:(Event *)e {
if (self) {
self.event = e;
}
return self;
}
#end
You may find an answer here: http://www.raywenderlich.com/1430/how-to-use-the-three20-photo-viewer