is it possible to move object between 2 `UICollectionView` - objective-c

i'm working with UICollectionView, I have 2 collection. and I need to move object from the first one to the second by dragging.
my project is based on LXReorderableCollectionViewFlowLayout.
Is it possible to move object between 2 UICollectionView by dragging?

Yes! (with a caveat)
You need to replace the delegate method willMoveToIndexPath and make a few modifications:
- (void)collectionView:(UICollectionView *)theCollectionView layout:(UICollectionViewLayout *)theLayout itemAtIndexPath:(NSIndexPath *)theFromIndexPath willMoveToIndexPath:(NSIndexPath *)theToIndexPath
{
/* code removed from example code
id theFromItem = [self.deck objectAtIndex:theFromIndexPath.item];
[self.deck removeObjectAtIndex:theFromIndexPath.item];
[self.deck insertObject:theFromItem atIndex:theToIndexPath.item];
*/
NSLog(#"From: %d %d To: %d %d", theFromIndexPath.section, theFromIndexPath.row, theToIndexPath.section, theToIndexPath.row);
NSMutableArray *fromSectionArray = mySectionArray[theFromIndexPath.section];
NSMutableArray *toSectionArray = mySectionArray[theToIndexPath.section];
id theFromItem = fromSectionArray.myItemArray[theFromIndexPath.item];
[fromSectionArray.myItemsArray removeObjectAtIndex:theFromIndexPath.item];
[toSectionArray.myItemsArray insertObject:theFromItem atIndex:theToIndexPath.item];
}
I'm just writing the code here (it might have errors) but I think you get the gist of what I'm doing. I'm just adding one layer for section and not assuming that the "from" and "to" items come from the same section.
The caveat:
This code works but I'm having problems if the section is initially empty of items.
Hope this helps.

Related

replacement for tabbar selected index

I have an old app where I have 5 tabs. Each tab have list of ads & there is details. Also each tab have respective add ad. Design for all 5 tabs is same except some changes, so I decided to use 1 screen only for all 5 tabs.
Now what I am doing is while add ad, I am checking which tab I am and based on tab bar index, I am showing hiding fields. Same is applicable for details screen also. Sample code is as shown below.
if (self.tabBarController.selectedIndex==0) {
field1.hidden = NO;
} else if (self.tabBarController.selectedIndex==1) {
field1.hidden = NO;
} else if (self.tabBarController.selectedIndex==2) {
field1.hidden = NO;
} else if (self.tabBarController.selectedIndex==3) {
field1.hidden = NO;
} else if (self.tabBarController.selectedIndex==4) {
field1.hidden = YES;
}
Now I have around 15 fields for each form so I write this code for all fields.
What I noticed that client change the tab bar position continuously so I was looking for efficient way of doing it.
Right now what I do is at all places manually change index positions by doing Search-Replace, however I dont like this.
I was looking for a way where instead of selectedIndex, I was looking for someconstant value that I will assign to tab item of tab bar, so my code will change as below
if (self.tabBarController.selectedIndex==adType_News) {
field1.hidden = NO;
} else if (self.tabBarController.selectedIndex==adType_Occasions) {
.
.
And so on...
This way, I only need to change in the storyboard and code level will not have any changes.
Is there way where I can achieve this?
Main Issue
As client ask to change tab bar completely, I need to make changes of selectedIndex changes at all places which I don't like and feel more in-efficient way. So I was looking for a way where I will make change in storyboard only and coding level there won't be any change.
The main issue for me is changing selectedIndex in all files which make more error.
I think I understand the question to mean that the code is full of number literals, referring to the selected index of the tabbar, and the business requirements about the ordering of items are shifting. Fix by changing the literals to something symbolic that can be controlled centrally:
// in a new file, indexes.h
#define INDEXA (0)
#define INDEXB (1)
#define INDEXC (2)
// wherever existing code refers to the tab selection
#import "indexes.h"
// in the code, for example if selectedIndex == 2, change to
if (self.tabBarController.selectedIndex==INDEXC) {
// ...

Two linked NSTables by NSArrayControllers are not updating simultaneously, if I update one of them

I am using Core data in cocoa. Since I cannot post pictures, I will try my best to explain the problem
My object model is:
Book:highlightInBooks >> Highlight
Objects are managed by BookArrayController and HighlightArrayController.
BookNSTableView datasource is BookArrayController and HighlightNSTableView datasource is HighlightArrayController.
I have created a NSMenu for highlight table that use Highlight attribute: markHighlightToTrash
The action attached to NSMenue item:
- (IBAction)trashHighlight:(id)sender {
Highlight *highlight = [_highlightArrayController arrangedObjects][[_highlightTableView clickedRow]];
[highlight setHighlightToTrash];
]
In highlight subclass:
-(void) setHighlightToTrash{
self.markHighlightToTrash = #1;
}
So what above code does is, when user trash all the highlight of a book in Highlight table trash that book in Book Table also.
I have set two NSButton in the sidebar namely AllBooks and Trash.
- (IBAction)allBookButton:(id)sender {
NSPredicate *predicateTwo = [NSPredicate predicateWithFormat:#"SUBQUERY(highlightsInBook, $highlight, $highlight.markHighlightToTrash = NO) .#count > 0"];
[_bookArrayController setFilterPredicate:predicateTwo];
[_highlightArrayController setFilterPredicate:[NSPredicate predicateWithFormat:#"markHighlightToTrash = NO "]];
}
- (IBAction)trashButton:(id)sender {
[_highlightArrayController setFilterPredicate:[NSPredicate predicateWithFormat:#"markHighlightToTrash = YES"]];
NSPredicate *predicateTwo = [NSPredicate predicateWithFormat:#"SUBQUERY(highlightsInBook, $highlight, $highlight.markHighlightToTrash = YES) .#count > 0"];
[_bookArrayController setFilterPredicate:predicateTwo];
}
So if AllBooks is clicked, tables will show only those books which are not marked to trash. And when Trash button is clicked tables will show books whose highlight is marked as trash.
Problem While above code works, the problem is when I mark all the highlight of Book X in highlight table, the Book X still remain visible in BookTable.
Although when I click Trash button and agin click back AllBook button, the Book X, do hide (as intended).
So why Book table only updates itself after I cycle through those two buttons.
The arraycontrollers don't (and can't) observe the properties used in the filter predicate. If you want to reapply the filter after changing highlight, you can do so with [arrayController rearrangeObjects].

How to hide the iOS 8 Today Widget when there is nothing to display?

I'm using the today widget for iOS8 to display information relevant to the current day. The problem is I don't want to display the widget/section at all if there are no relevant messages to show.
I know it must be possible as the BA app does it (it only shows the widget when there is a flight, the rest of the time its not visible at all). I just cant figure out a way to achieve this behaviour.
Does anyone know how this can be done?
I found the way to do this is using the NCWidgetController. This allows you to easily specify when the today widget should be displayed based on whatever criteria you see fit.
Simply add the following into your viewDidLoad method (or anywhere that will be called when the widget reloads) in the today widget view controller and it will work:
BOOL hasDataToDisplay = NO;
NCWidgetController *widgetController = [NCWidgetController widgetController];
[widgetController setHasContent:hasDataToDisplay forWidgetWithBundleIdentifier:#"com.my-company.my-app.my-widget"];
Apple Docs: https://developer.apple.com/library/ios/documentation/NotificationCenter/Reference/NCWidgetController_Class/index.html#//apple_ref/occ/cl/NCWidgetController
WARNING: The NCWidgetController cannot be reset from the widget itself once you have set there is no content to display. In other words once you set it to NO then there is no going back unless you trigger it from the parent/containing app.
In the widget's ViewController's viewDidLoad method add the following:
BOOL DisplayWidget = NO;
[[NCWidgetController widgetController] setHasContent:DisplayWidget
forWidgetWithBundleIdentifier:#"<widget's bunder identifier>"];
This will disable the widget from showing.
To enable it again, you must do that from the containing app using the same line passing YES to setHasContent parameter. Make sure to add the necessary imports to the containing app in the ViewController which will re-enable the widget:
#import <NotificationCenter/NotificationCenter.h>
#interface ViewController () <NCWidgetProviding> {...}
[Check out page 41 of the documentations for widgets
https://developer.apple.com/library/ios/documentation/General/Conceptual/ExtensibilityPG/ExtensibilityPG.pdf ]
The approach which I used, though not perfect and has a small remnant in Notification Center, but worked for me:
In viewDidLoad() set preferred content size height to 1:
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view from its nib.
preferredContentSize = CGSizeMake(0, 1)
view.setNeedsLayout()
}
then when widget updates, gets real height and set it:
var data: NSData?
func updateData() {
// fetch data
if let data = data {
let viewHeight: CGFloat
// UI preperation and initialize viewHeight var
preferredContentSize = CGSizeMake(0, viewHeight);
} else {
preferredContentSize = CGSizeMake(0, 1);
}
}
func widgetPerformUpdateWithCompletionHandler(completionHandler: ((NCUpdateResult) -> Void)) {
// Perform any setup necessary in order to update the view.
// If an error is encountered, use NCUpdateResult.Failed
// If there's no update required, use NCUpdateResult.NoData
// If there's an update, use NCUpdateResult.NewData
updateData()
completionHandler(data != nil ? NCUpdateResult.NewData : NCUpdateResult.NoData)
}
It is better use
+ (instancetype)widgetController
then call
- (void)setHasContent:(BOOL)flag forWidgetWithBundleIdentifier:(NSString *)bundleID

Update current page number after pageviewcontroller animation is completed

Problem having is that it start updating current page number after you turn 3 or 4 pages over then it start updating current page number starting from 1, 2, 3, 4,..... which is wrong. and if you start in reverse order turning page over lets suppose from 12 then it shows 13 and then from next page it starts updating current pagenumber in reverse order.
- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:(BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:(BOOL)completed{
if (!completed) {
return;
}
if (currentIndex<totalPages -1 ){
[self displaycurrentIndex:currentIndex + 1];
}else if (currentIndex>totalPages + 1){
[self displaycurrentIndex:currentIndex - 1];
}
}
- (void) displaycurrentIndex:(NSUInteger)currentIndex {
self.navigationItem.title = [NSString stringWithFormat:
#"Page %i of %i",
currentIndex + 1,
CGPDFDocumentGetNumberOfPages(PDFDocument)];
}
Please help in how to fix this updating current page number from the beginning and also when going in reverse order.
Edit:
After removing
if (!completed) {
return;
}
Now it is Updating after turning first page over but now updates current page number from 0 of 20 and then 1 of 20 and so on but still when turning page over in reverse order it still updates current pagenumber in forward and then in reverse order.
Thanks for help.
From my experience (and also it is confirmed in the past WWDC session videos dedicated to this class) the best way to manage the page numbers in a UIPageViewController is to store as a property the page number information directly in the page view controller (that is in the view controller that contains the single page you want to show).
Then if you want to show a general purpose status bar with the page number, you simply fetch the viewControllers property of the UIPageViewController, which returns one or two view controllers depending on the UIPageViewController setup.
So in pseudo-code when the page view controller asks its data source which are the new view controllers to display your code:
- will get the current view controller(s)
- will fetch from it (them) the page number
- will calculate the next or prev page number(s) (depends on the page curl/swipe direction)
- will ask to the data source for the new calculated page numbers view controllers and will assign to their page number property the new value
In this way you are protected from strange animation behaviours and you don't need to keep in memory a global "currentIndex" which may lead to issues, as you experienced.

NSMenu --> Adding SubMenu --> receive select event

I need to create a Menu for a selected row of a table,
I am able to create by overriding
-(NSMenu*)menuForEvent:(NSEvent*)evt
Method, of a table, This particular Menu has two sub-menu, i am able to make the Sub-Menu
but facing Following Problem
1 -- To Add a Sub-Menu in a MenuItem, i need to get Sub-Menu from a different class/Interface, i am calling following method
pSubMenu = [CommonUIUtil GetCommonUIMenu:pSubMenu
ActionId:self
Selector:#selector(MyMenuAction)];
Where prototype of this function is as follow
+(NSMenu *)GetCommonStatusMenu:(NSMenu *)pMenu ActionId:(NSObject*)aDelegate Selector:(SEL)selector
Implementation as below,
// pStrArray is Array of String to have the Menu Title
for(int idx =0;idx<[pStrArray count];idx++)
{
pTempStr = [pStrArray objectAtIndex:idx];
pImage = [CommUIController CommonGetImage:[CommonUIUtil GetImageByStatus:pTempStr]];
[pImage setSize:NSMakeSize(20,20)];
pMenuItem =[[NSMenuItem alloc]init];
[pMenuItem setTitle:pTempStr];
// this should set the selector
[pMenuItem setAction:selector];
// Setting the target
[pMenuItem setTarget:aDelegate];
[pMenuItem setImage:pImage];
[pMenuItem setEnabled:YES];
[pMenu addItem:pMenuItem];
[pMenuItem release];
}
return pMenu;
I am able to see the Image, String on this Sub Menu, but the problem i am facing is this menu is not at all Enable, can anyone guide me , where i am making the mistake,
This function will return the Menu and Menu i will add as below,
pMenuItem = [pCTTableMenu itemWithTitle:#"Status"];
//status menu is the menu returned from the above function,
[pMainMenu setSubmenu:pStatusMenu forItem:pMenuItem];
Thanks in Advance :)
looks like, i am not passing the selector method properly, in fact i don't know how to pass function pointer in Cocoa, probably i am mixing Cocoa/Objective C and Normal C both :), corrected, it, in the method just creating the view and in the main class/interface assigning target and action