I have my first view controller imageResults and in that calls the MWPhotoBrowser with the code below. I see it displays a new view controller using the data from self.photos. I've tried a few options for adding more data but none successful. I want to be able to load more data in the new view and add it to the photobrowser, the adding more data part is already don't, now how do i set the current browser to load the new array without loosing the current position?
-(void)mvTouched:(NSIndexPath *)indexPath {
NSLog(#"Arr:%lu Url:%lu", [titlesMutable count], [mediaUrlDict count]);
NSMutableArray *tmpPhotos = [NSMutableArray array];
for(NSString *titleString in titlesMutable) {
NSString *url = [mediaUrlDict objectForKey:titleString];
MWPhoto *currentPhoto = [MWPhoto photoWithURL:[NSURL URLWithString:url]];
currentPhoto.caption=[NSString stringWithFormat:#"%#", titleString];
[tmpPhotos addObject:currentPhoto];
//[tmpPhotos addObject:[MWPhoto photoWithURL:[NSURL URLWithString:url]]];
}
self.photos = [NSArray arrayWithArray:tmpPhotos];
MWPhotoBrowser *browser = [[MWPhotoBrowser alloc] initWithDelegate:self];
// Set options
browser.displayActionButton = YES; // Show action button to allow sharing, copying, etc (defaults to YES)
browser.displayNavArrows = YES; // Whether to display left and right nav arrows on toolbar (defaults to NO)
browser.displaySelectionButtons = NO; // Whether selection buttons are shown on each image (defaults to NO)
browser.zoomPhotosToFill = YES; // Images that almost fill the screen will be initially zoomed to fill (defaults to YES)
browser.alwaysShowControls = YES; // Allows to control whether the bars and controls are always visible or whether they fade away to show the photo full (defaults to NO)
browser.enableGrid = YES; // Whether to allow the viewing of all the photo thumbnails on a grid (defaults to YES)
browser.startOnGrid = NO; // Whether to start on the grid of thumbnails instead of the first photo (defaults to NO)
browser.edgesForExtendedLayout = YES;
browser.extendedLayoutIncludesOpaqueBars = YES;
// Optionally set the current visible photo before displaying
//[browser setCurrentPhotoIndex:1];
[browser setCurrentPhotoIndex:indexPath.row];
self.navigationController.navigationBar.hidden=NO;
// Present
[self.navigationController pushViewController:browser animated:YES];
// Manipulate
[browser showNextPhotoAnimated:YES];
[browser showPreviousPhotoAnimated:YES];
//[browser setCurrentPhotoIndex:1];
[browser setCurrentPhotoIndex:indexPath.row];
[browser reloadData];
}
-(void)loadMore {
[self addDataToArray];
//[self mvTouched:nil];
[self.collectionView reloadData];
}
- (NSUInteger)numberOfPhotosInPhotoBrowser:(MWPhotoBrowser *)photoBrowser {
return _photos.count;
}
- (id <MWPhoto>)photoBrowser:(MWPhotoBrowser *)photoBrowser photoAtIndex:(NSUInteger)index {
if (index < _photos.count)
return [_photos objectAtIndex:index];
return nil;
}
- (void)photoBrowser:(MWPhotoBrowser *)photoBrowser actionButtonPressedForPhotoAtIndex:(NSUInteger)index {
// Do your thing!
NSLog(#"ACTION!!!");
}
Calling [self.collectionView reloadData] will only reload the current view's collection instead of the MWPhotoBrowser's. You need to call the browsers reloadData function for this to work like so:
[browser reloadData]
Note that there is currently an issue with the browsers collection view not displaying the new photos after calling this method. I managed to work around this by adding this code to the reloadData method found in the MWPhotoBrowser.m file:
if (_gridController) {
[_gridController.collectionView reloadData];
}
Related
I'm using ELCImagePickerController in my project. Select multiple images from the gallery through it. I'm facing an issue that , how i can show the selected multiple images in an image view in a view controller. I have created a select image button which take us to photolibrary where we select multiple images.My code is,
- (IBAction)Select:(id)sender {
ELCImagePickerController *elcPicker = [[ELCImagePickerController alloc] initImagePicker];
elcPicker.maximumImagesCount = 100; //Set the maximum number of images to select to 100
elcPicker.returnsOriginalImage = YES; //Only return the fullScreenImage, not the fullResolutionImage
elcPicker.returnsImage = YES; //Return UIimage if YES. If NO, only return asset location information
elcPicker.onOrder = YES; //For multiple image selection, display and return order of selected images
// elcPicker.mediaTypes = #[(NSString *)kUTTypeImage, (NSString
*)kUTTypeMovie]; //Supports image and movie types
elcPicker.imagePickerDelegate = self;
[self presentViewController:elcPicker animated:YES completion:nil];
}
- (void)elcImagePickerController:(ELCImagePickerController *)picker
didFinishPickingMediaWithInfo:(NSArray *)info
{
[self dismissViewControllerAnimated:YES completion:nil];
for (NSDictionary *dict in info)
{
if ([dict objectForKey:UIImagePickerControllerMediaType] ==
ALAssetTypePhoto)
{
if ([dict objectForKey:UIImagePickerControllerOriginalImage])
{
UIImage* image=[dict
objectForKey:UIImagePickerControllerOriginalImage];
_arrimage.image;
}
}
}
}
- (void)elcImagePickerControllerDidCancel:(ELCImagePickerController *)picker
{
[self dismissViewControllerAnimated:YES completion:nil];
}
You can use CreolePhotoSelection to get and select multiple images. It will help to you gets multiple selection and retrieve all selected value into delegate method.
Below is the sample code for it:
CreolePhotoSelection *objCreolePhotoSelection= [[CreolePhotoSelection alloc] initWithNibName:#"CreolePhotoSelection" bundle:nil];
objCreolePhotoSelection.strTitle = YOUR_TITLE_FOR_PHOTO_VIEW;
objCreolePhotoSelection.delegate = self; // It will help to retrive all selected photos from CreolePhotoSelection
objCreolePhotoSelection.arySelectedPhoto = YOUR_CURRENT_ARRAY; // You need to pass same array which is holding selected image
objCreolePhotoSelection.maxCount = YOUR_MAX_PHOTOS_LIMIT; // Eg. 5, 10 anythings...
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:objCreolePhotoSelection];
[self.navigationController presentViewController:navController animated:YES completion:nil];
// Delegate Method
#pragma mark - Photo selected Delegate Method
-(void)getSelectedPhoto:(NSMutableArray *)aryPhoto
{
// You will selected image array into aryPhoto object and you can use it
}
First of all an Image View is to show a single image. From the piece of code you shared I am not clear what did you mean by
UIImage* image=[dict
objectForKey:UIImagePickerControllerOriginalImage];
_arrimage.image;
What does this _arrimage mean? Is that a reference to the Image view? then it should be
_arrimage.image = image; //the image fetched in the above line
But this won't fix your issue as this will show only the very last object found in the for loop (probably the last selected image).
To show all selected images it is better to go with a collection view with the array of images as the data source and load each images in each cells of the collection view.
If you want to show all images within the same image view, there is another option by setting it as animationimages
imageView.animationImages = imagesListArray //the list of image you selected
imageView.animationDuration = 2.0
imageView.startAnimating()
This just show each images one at a time from the array with a time interval of 2 seconds
You can't Show Multiple Images in a single ImageView at a same time but yes you can show multiple images on a same ImageView for sometime using Image Animation.
var imagesArray = [UIImage]()
for imageName in 1...3
{
imagesArray.append(UIImage(named: "\(imageName).png")!)
}
// You can also use below code to add images if not want to use loop
// imagesArray.append(UIImage(named: "a.png")!)
// imagesArray.append(UIImage(named: "b.png")!)
// imagesArray.append(UIImage(named: "c.png")!)
self.imageView.animationImages = imagesArray
self.imageView.animationDuration = 2.0
self.imageView.startAnimating()
In my VC I have a UITableView. Each cell has a UITableView as one of its contents. Timer is set updating each cell every 10secs. Events are handled which also reloads the respective cell.
Method that timer calls :-
-(void) updateVisitotsLists {
NSLog(#"UPDATING VISITORS LIST ***************************");
// Call API's to get lists
[api getVisitorsList];
// Init Arrays
browsingList = [MainAppDataObject sharedAppDataObject].visitors_browsingList;
secondList = [MainAppDataObject sharedAppDataObject].visitors_secondList;
thirdList = [MainAppDataObject sharedAppDataObject].visitors_thirdList;
fourthList = [MainAppDataObject sharedAppDataObject].visitors_fourthList;
// AS these are no more useful, so make it nil & save memory
[MainAppDataObject sharedAppDataObject].visitors_browsingList = nil;
[MainAppDataObject sharedAppDataObject].visitors_secondList = nil;
[MainAppDataObject sharedAppDataObject].visitors_thirdList = nil;
[MainAppDataObject sharedAppDataObject].visitors_fourthList = nil;
// Reload all lists with latest data
[self reloadBrowsingRow];
[self reloadSecondRow];
[self reloadThirdRow];
[self reloadFourthRow];
}
Event Handler Method :-
-(void) handleNewVisitor : (NSNotification *) notification {
// UPDATE VISITOR'S LIST
Visitor *v = [notification object];
#try {
if (v != nil) {
// Add V to browsing list
[browsingList addObject:v];
// Reload browsing list
[self reloadBrowsingRow];
}
}#catch (NSException *e) {
NSLog(#"EXCEP - %#", e);
}
v = nil;
return;
}
Reloading Method -
-(void)reloadBrowsingRow {
// Browsing
VisitorsListsCell *bcell = (VisitorsListsCell*)[self.visitorlistsTv cellForRowAtIndexPath:[NSIndexPath indexPathForRow:2 inSection:0]];
[bcell.listsTableView reloadData];
[bcell updateButtonText];
[bcell setNeedsDisplay];
bcell = nil;
return;
}
The Problem :-
When updateVisitotsLists is called thru timer, the updated contents are not reflected on cell.
When event handler method calls the same [self reloadBrowsingRow]; method, the contents of the cell are updated and reflected.
Due to this despite cells contents are updated but are not reflected until the state of cell is changed - expanded or collapsed.
I tried removing timer and cell updates properly on event caught, but when timer was on and event was caught, method is called but contents are not reflected on the screen.
I feel both methods may be calling reload method at same time, hence this must be happening or what ? How can this be handled making sure that the contents of cells are updated in any respect ? Any help is highly appreciated. Thanks.
Use [tableview reloadData]; on that method.
Because Reload on tableView will reload all data, so it will be more helpful.
I have two UIViewControllers, one is a UIPickerViewController, the Other a UITableViewController. Ideally the Picker should get a request from the user to add x amount of some item to the tableView. The Picker gets user inputs and assigns them to variables val1, val2, val3, where val1 is the number of items (number of rows) and val2 is the name or label for the item.
PickerViewController.m
- (IBAction)add:(id)sender
{
TableViewController *tvc = [[TableViewController alloc] init];
[tvc setValues:self.val1 :self.val2 :self.val3];
[self presentViewController:tvc animated:YES completion:nil];
}
TableViewController.m
-(void)setValues:(NSString *)newVal1 :(NSString *)newVal2 :(NSString *)newVal3
{
self.val1 = newVal1;
self.val2 = newVal2;
self.val3 = newVal3;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:#"UITableViewCell"];
// This is just a header which holds my "Add" button
UIView *header = self.headerView;
[self.tableView setTableHeaderView:header];
[self addNew:self.val1 :self.val2 :self.val3];
}
- (void)addNew:(NSString *)newVal1 :(NSString *)newVal2 :(NSString *)newVal3
{
if(!self.numberOfRows){
NSLog(#"Initially no of rows = %d", self.numberOfRows);
self.numberOfRows = [self.val1 intValue];
NSLog(#"Then no of rows = %d", self.numberOfRows);
}
else
{
self.numberOfRows = self.numberOfRows + [newVal1 intValue];
NSLog(#"New no rows = %d", self.numberOfRows);
}
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:self.numberOfRows inSection:0];
// Only run when called again .. not initially
if(self.run != 0){
[self.tableView beginUpdates];
[self.tableView insertRowsAtIndexPaths:#[indexPath]withRowAnimation:UITableViewRowAnimationBottom];
self.run ++;
[self.tableView endUpdates];
}
}
// "ADD" button which should go back to the picker and get new items to add to the table
- (IBAction)testAdd:(id)sender
{
PickerViewController *pvc = [[PickerViewController alloc] init];
[self presentViewController:pvc animated:YES completion:nil];
}
Now, I realize every time I call the next view controller I am creating a new instance of it, but I don't know how else to do it, I figure this is the main problem. As of right now, I expect when I leave the tableview for the picker view and return the console should log "New no of rows = x" but that doesn't happen.
I know val3 isn't used and my addNew: may not be the best, but I just need it to handle the basic logging mentioned above and I should be able to take it from there.
Been stuck on this for days
Create a property for TableViewController, and only create it the first time you present it,
- (IBAction)add:(id)sender {
if (! self.tvc) {
self.tvc = [[TableViewController alloc] init];
}
[self.tvc setValues:self.val1 :self.val2 :self.val3];
[self presentViewController:self.tvc animated:YES completion:nil];
}
It's not entirely clear from you question, whether it's this presentation or the one you have in the table view class that you're talking about. It also looks like you're doing something wrong in terms of presentation -- you're presenting the picker view from the table view controller, and also presenting the table view controller from the picker. That's not correct, you should present which ever controller you want to appear second, and that controller should use dismissViewControllerAnimated to go back, not present another controller.
In testAdd you don't need to create a new instance and present it. If you want to go back to the presentingViewController, just use dismissViewControllerAnimated .
And you will go one controller up in the stack.
I am using MWPhotoBrowser to display images in navigation. For multiple images it is working fine. But when displaying one image(number of images is 1) it does not display image name as title of navigation bar. How do i fix that? here is the code of delegate method:
- (void) photoBrowser:(MWPhotoBrowser *)photoBrowser didDisplayPhotoAtIndex:(NSUInteger)index {
NSLog(#"Photo displayed");
if (index < [self.imagesGallery count]) {
NSString *imageName = [self.imagesGallery objectAtIndex:index];
photoBrowser._titleText = [imageName stringByDeletingPathExtension];
NSLog(#"Title: %#", photoBrowser._titleText);
NSString *element = [[[imageName stringByDeletingPathExtension] componentsSeparatedByString:#"-"] objectAtIndex:1];
int index_ = [deficiencesShort indexOfObject:element];
photoBrowser._actionButton.title = [NSString stringWithFormat:#"Go To %# Deficiency", [deficiences objectAtIndex:index_]];
}
}
For single image, NSLog(#"Title: %#", photoBrowser._titleText) displays image name as output but does not set as navigation bar title
Maybe you make some changes with MWPhotoBrowser library, show me your code.
Setting title of of MWPhotoBrowser's Navigation:
add name property in MWPhoto
modifier updateNavigation method, in handleMWPhotoLoadingDidEndNotification, pass a title in updateNAvigation (two functions in MWPhotoBrowser.m)
Put below condition in updateNavigation method in MWPhotoBrowser.m file
remove self.title = nil;and add this condition in else part.
if ([_delegate respondsToSelector:#selector(photoBrowser:titleForPhotoAtIndex:)]) {
self.title = [_delegate photoBrowser:self titleForPhotoAtIndex:_currentPageIndex];
}
else {
self.title = nil;
}
Make sure you need to implement photoBrowser:titleForPhotoAtIndex delegate.
THIS QUESTION HAS BEEN RE-WRITTEN IN ORDER TO PROPERLY COMMUNICATE THE INTENTIONS OF THE AUTHOR
I have a MasterDetail App that will eventually become a way to track an amount of "players" through a fixed amount of "challenges" (60 to be exact). The challenges are the same for every player, while the status of each player on the individual challenges may vary. All of the data about the players are being stored on a Postgres Database and then fetched using the JSONModel in the LeftViewController. I am getting all of the data correctly from the DB and I have successfully put it into a NSMutableDictionary. The data in the Dictionary looks like this (this is one player):
player = (
{
id = 9;
name = "Arthur Dent";
currentChallenge = "Cooking";
timeStarted = "04 Jul 2013 1:08 PM";
challengesDone = (
{
challengeName = "Flying";
timeCompleted = "04 Jul 2013 12:08 PM";
}
);
nextChallenge = "Swimming";
freePass = (
Running,
"Climbing"
);
},
As you can see, the player has some challenges "done" ("done"), some he has doesn't need to do ("pass") on, one he is doing ("currentChallenge") and the one challenge that he will do next ("nextChallenge"). For each of these states that a player can be in, I want the "Challenges" that are in the RightViewController to be color coded so you can understand what is happening at a glance. I need the "challenges" to light up different colors, based on the status of the player, which is determined by the data that is in my NSMutableDictionary.
By creating arrays from the data in the NSDictionary I can get the colors to change by doing this:
if ([freePassArray containsObject:#"challenge three name"])
{
UIImage *image = [UIImage imageNamed:#"status_pass.png"]; //status_pass.png is my color
[challengeThreeImageView setImage:image];
}
But if I did it like this, I would have to write 240 if and else if statements to cover all possible statuses on all 60 challenges.
My arrays only contain the data of the player selected because I pass the data over like so:
*LeftViewController.m * didSelectRowAtIndexPath
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
//Re-fetch the feed from the Postgres Database when a user selects an entry
[JSONHTTPClient getJSONFromURLWithString:#"http://myurl" completion:^(NSDictionary *json, JSONModelError *err) {
NSError* error = nil;
_feed = [[PostgresFeed alloc] initWithDictionary:json error:&error];
[[NSNotificationCenter defaultCenter] postNotificationName:#"myNotification" object:nil userInfo:[[json objectForKey:#"preclear"] objectAtIndex:indexPath.row]];
}];
Player *selectedPlayer = [_players objectAtIndex:indexPath.row];
if (_delegate)
{
[_delegate selectedPlayer:selectedPlayer];
}
}
So the images wont set for all of the players at once, but they also do not clear after another player is selected.
How do I get the colors to change without writing 240 if and else if statements? and how would I get the colors to clear when I select another player?
Assuming you have all the 50 images and you know which challenge corresponds to which image I would put the status image on top of the actual challenge image:
- (void)setChallengesDone:(NSArray*)doneAr next:(NSArray*)nextAr current:(NSArray*)currentAr andPass:(NSArray*)passAr
{
// remove additions from the previous selected player
UIView *prevAdditionsView = [self.view viewWithTag:122333];
while (prevAdditionsView != nil)
{
[prevAdditionsView removeFromSuperview];
prevAdditionsView = [self.view viewWithTag:122333];
}
for (int i=0; i<[doneAr count]; i++)
{
[self addChallengeImageAdditionWithImage:#"status_done" forChallenge:[doneAr objectAtIndex:i]];
}
for (int i=0; i<[nextAr count]; i++)
{
[self addChallengeImageAdditionWithImage:#"status_next" forChallenge:[nextAr objectAtIndex:i]];
}
for (int i=0; i<[currentAr count]; i++)
{
[self addChallengeImageAdditionWithImage:#"status_current" forChallenge:[currentAr objectAtIndex:i]];
}
for (int i=0; i<[passAr count]; i++)
{
[self addChallengeImageAdditionWithImage:#"status_free" forChallenge:[passAr objectAtIndex:i]];
}
}
- (void)addChallengeImageAdditionWithImage:(NSString*)image forChallenge:(NSString*)challengeTitle
{
UIImageView *challengeImage = [challenges objectForKey:challengeTitle];
CGRect frame = challengeImage.frame;
UIImageView *statusImg = [[[UIImageView alloc] initWithImage:[UIImage imageNamed:image]] autorelease];
[statusImg setFrame:frame];
[statusImg setAlpha:0.5]; // optionally add some transparency
[statusImg setTag:122333];
[self.view addSubview:statusImg];
[self.view bringSubviewToFront:challengeImage]; // bring challenge image to front
}
The simplest way to map your challenge titles with the UIImageViews is to maintain a NSDictionary with the challenge titles as keys, and a references to their corresponding UIImageViews as values.
This is an excellent example of the model/view concept.
Each challenge is a model with all the info required (challenge name, status, timestamp and others).
Each of your 50 views is a "challenge view" that knows how to render any challenge.
The status data is in the model; the status image is in the view.
Example:
-(void) drawChallenge: (Challenge*) challenge
{
// Draw challenge name as text
switch ([challenge status])
{
case done: // draw "done" image
case next: // draw "next" image
}
}
The idea is that the challenge itself should not know about how it is rendered, and the view should not know about what the challenge contains. The view is responsible for drawing it.
This could be packed into a ChallengeView subclass of UIView. Then, create your 50 or so ChallengeViews, and call [currentView drawChallenge: currentChallenge].
Essentially, when a new challenge is added, you create a view for it, and give the view a pointer to the challenge. When the challenge view is rendered by iOS, it'll draw "its" challenge as you have described in the drawChallenge method.
If you need a primer on the Model-View-Controller pattern, this section of the Apple docs is pretty good. You can disregard the Controller role in this situation.