How do I make a toggle button affect a user script (cmix) in Xcode 4.3 - objective-c

I am building a simple step sequencer in IRTcmix (version of RTcmix for the iphone/ipad), using UI Buttons to control which notes are on or off in the sequence.
I have been working with a set of RTcmix examples of other apps, and trying to piece my own together, but i'm unsure how to change values of a variable within the .sco (score file) with a toggle-style UIButton.
Here are some snippets from a working RTcmix App:
From the RTcmix manager .h:
#interface RTcmixManager : RTcmixPlayer {
RTcmixScore *polyScore;
}
#property (nonatomic, retain) RTcmixScore *polyScore;
- (void)noteOn:(int)note;
- (void)noteOff:(int)note;
#end
and the RTcmix manager .m
- (void)noteOn:(int)note {
[polyScore.mainScoreParameters replaceObjectAtIndex:0 withObject:[NSNumber numberWithInt:note]];
[polyScore.mainScoreParameters replaceObjectAtIndex:1 withObject:[NSNumber numberWithInt:1]];
[self parseScoreWithRTcmixScore:polyScore];
polyScore.setupIsActive = YES;
}
- (void)noteOff:(int)note {
[polyScore.mainScoreParameters replaceObjectAtIndex:0 withObject:[NSNumber numberWithInt:note]];
[polyScore.mainScoreParameters replaceObjectAtIndex:1 withObject:[NSNumber numberWithInt:0]];
[self parseScoreWithRTcmixScore:polyScore];
}
the viewcontroller .h:
#interface RTPolyphonyViewController : UIViewController {
RTcmixManager *rtcmixManager;
}
- (IBAction)keyDown:(UIButton *)sender;
- (IBAction)keyUp:(UIButton *)sender;
#end
viewcontroller .m:
- (IBAction)keyDown:(UIButton *)sender {
[rtcmixManager noteOn:sender.tag];
}
- (IBAction)keyUp:(UIButton *)sender {
[rtcmixManager noteOff:sender.tag];
}
and a snippet from the .sco file (the "%#" is the variables changed by user input):
NoteNumber = %#
NoteVelocity = %#
alreadySounding = note_exists(oscNotes[NoteNumber])
MAXMESSAGE(0, alreadySounding)
I am very new to objective C and xcode, I was wondering how to make a UI button toggle between two values in the score file (acting like a switch) for example, a button when toggled making the value of NoteNumber(in the score file) set to 1, while the value is 0 when toggled off. Because I am a beginner with Xcode(and objective C), I'm not sure about the proper syntax for making a button able to be toggled on and off, and i am also not sure how to connect said button with my .sco file, as much as I look at the sample code, I cannot seem to figure out how they all connect.

Related

Substitute keystroke

I am trying to intercept a keystroke, and substitute it with a different character. I have been able to intercept the key being pressed, as well as perform some extra operations. Now I need to hold the key being pressed if it matches one of the ones I am watching, and insert a different character. Here is the code I have right now:
#import "AppDelegate.h"
#import <AppKit/AppKit.h>
#import <CoreGraphics/CoreGraphics.h>
#include <ApplicationServices/ApplicationServices.h>
#interface AppDelegate ()
#property (weak) IBOutlet NSWindow *window;
#end
#implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
//Keys that are being watched to be switched out
NSArray *keysToWatch = [[NSArray alloc] initWithObjects:#"c",#".", nil];
// register for keys throughout the device...
[NSEvent addGlobalMonitorForEventsMatchingMask:NSKeyDownMask
handler:^(NSEvent *event){
//Get characters
NSString *chars = [[event characters] lowercaseString];
//Get the actual character being pressed
unichar character = [chars characterAtIndex:0];
//Transform it to a string
NSString *aString = [NSString stringWithCharacters:&character length:1];
//If it is in the list, start looking if Keynote is active
if ([keysToWatch containsObject:[NSString stringWithString:aString]]) {
//DEBUG: Print a message
NSLog(#"Key being watched has been pressed");
//Get a list of all running apps
for (NSRunningApplication *currApp in [[NSWorkspace sharedWorkspace] runningApplications]) {
//Get current active app
if ([currApp isActive]) {
//Check if it is Keynote, if yes perform remap
if ([[currApp localizedName] isEqualToString:#"Keynote"]){
//DEBUG: Print a small message
NSLog(#"Current app is Keynote");
if (character=='.') {
NSLog(#"Pressed a dot");
//I want to post a different character here
PostKeyWithModifiers((CGKeyCode)11, FALSE);
}
else if ([aString isEqualToString:#"c"]) {
NSLog(#"Pressed c");
}
}
else if ([[currApp localizedName] isEqualToString:#"Microsoft PowerPoint"]){
}
}
}
}
}
];
}
- (void)applicationWillTerminate:(NSNotification *)aNotification {
// Insert code here to tear down your application
}
- (BOOL)acceptsFirstResponder {
return YES;
}
void PostKeyWithModifiers(CGKeyCode key, CGEventFlags modifiers)
{
CGEventSourceRef source = CGEventSourceCreate(kCGEventSourceStateCombinedSessionState);
CGEventRef keyDown = CGEventCreateKeyboardEvent(source, key, TRUE);
CGEventSetFlags(keyDown, modifiers);
CGEventRef keyUp = CGEventCreateKeyboardEvent(source, key, FALSE);
CGEventPost(kCGAnnotatedSessionEventTap, keyDown);
CGEventPost(kCGAnnotatedSessionEventTap, keyUp);
CFRelease(keyUp);
CFRelease(keyDown);
CFRelease(source);
}
#end
My problem is that I am not able to stop the original keystroke. Please keep in mind that I am completely new at Obj C, so let me know if there is anything that I can do better. Thanks!
From the docs for +[NSEvent addGlobalMonitorForEventsMatchingMask:handler:]:
Events are delivered asynchronously to your app and you can only
observe the event; you cannot modify or otherwise prevent the event
from being delivered to its original target application.
You would have to use a Quartz Event Tap for that.
So, after a LOT of digging around, I found a way to do this using Quartz Event Taps here. Thanks to #Ken Thomases for pointing me in the correct direction. I then combined my code with the one explained in this article and voilĂ , it works.

UIAlertView showing twice

I have an application that, in part, loops through the contents of an NSSet and displays a UIAlertView for each item found in the set. When there is only one item in the set, the UIAlertView behaves itself properly. However, if there's more than one, the first view flashes up (normally with the contents of the last item in the set) and then disappears without any user intervention. The first item in the NSSet will then display and wait for a response, before displaying the next item in the NSSet and so on.
It is the same experience as is being described in this unresolved question: IPHONE: UIAlertView called twice in a custom function/IBAction
Here's the code:
#import "CalcViewController.h"
#interface CalcViewController()
#property (nonatomic) int variablesCount;
#property (nonatomic, strong) NSMutableDictionary *variablesSet;
#end
#implementation CalcViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.variablesSet = [[NSMutableDictionary alloc] init];
}
- (IBAction)variablePressed:(UIButton *)sender
{
[[self calcModel] setVariableAsOperand:sender.titleLabel.text];
self.expressionDisplay.text = [[self calcModel] descriptionOfExpression:self.calcModel.expression];
}
- (IBAction)solveExpressionPressed:(UIButton *)sender {
self.variablesCount = 0;
[self.variablesSet removeAllObjects];
NSSet *variablesCurrentlyInExpression = [[NSSet alloc] initWithSet:[CalcModel variablesInExpression:self.calcModel.expression]];
self.variablesCount = [variablesCurrentlyInExpression count];
if (variablesCurrentlyInExpression){
for (NSString *item in variablesCurrentlyInExpression) {
UIAlertView *alertDialog;
alertDialog = [[UIAlertView alloc] initWithTitle:#"Enter value for variable"
message:item
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
alertDialog.alertViewStyle=UIAlertViewStylePlainTextInput;
UITextField * alertTextField = [alertDialog textFieldAtIndex:0];
alertTextField.keyboardType = UIKeyboardTypeNumbersAndPunctuation;
[alertDialog show];
}
}
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
if (buttonIndex == 0){
if ([[alertView textFieldAtIndex:0] text]){
self.variablesSet[alertView.message] = [[alertView textFieldAtIndex:0] text];
}
}
if ([self.variablesSet count] == self.variablesCount){
NSLog(#"time to solve");
[[self calcDisplay] setText:[NSString stringWithFormat:#"%g", [CalcModel evaluateExpression:self.calcModel.expression usingVariableValues:self.variablesSet]]];
}
}
I've checked the IBActions behind the button that triggers the solveExpressionPressed method and that is the only one that exists. I've also placed some logging before the [alertDialog show]; line and it is only called twice when the variablesCurrentlyInExpression NSSet contains two values, yet the UIAlertView appears three times (flashing up once).
Finally, i've tried it without the following code:
UITextField * alertTextField = [alertDialog textFieldAtIndex:0];
alertTextField.keyboardType = UIKeyboardTypeNumbersAndPunctuation;
and the problem still occurs, so I don't think it's that.
I've been stuck on this a while and haven't figured it out (hence the post!!), so any help would be greatly appreciated.
Thanks
Try showing the first UIAlertView and then showing the second after the first is dismissed.
What's happens is if an app or the OS calls [alert show] and a UIAlertView is already being displayed, the original alertView gets placed in a queue and the new one is presented. When the new one is dismissed, the original UIAlertView is re-shown.
Hope this helps
Easily fixed with a boolean flag that you set to YES when the first alert is shown. Then when the second match is found and the boolean is already YES because the alert is visible you won't show it. Then again you might want to know the exact amount of matches in the NSSet. In that case you keep track with a counter and show the alert after the match function has been done and the counter is not 0.
Avoid showing the alert inside the method of the button trigger. Instead split every function into different sets of methods. Not just for making your function work but maintainability of the code later.
To get this done, you'll need to keep some extra state in your class, like this...
#property (strong, nonatomic) NSMutableSet *promptVariables;
#property (strong, nonatomic) NSString *promptVariable;
#property (strong, nonatomic) NSMutableDictionary *promptResults;
You can probably get away with less by keeping some in your model as it is (or hiding a little in the alert view message as you cleverly do currently), but I'll use all new variables for clarity.
When you want to make several prompts, set up your state like this...
self.promptVariables = [[NSSet alloc] initWithSet:[CalcModel variablesInExpression:self.calcModel.expression]];
[self promptForVariables];
Define promptForVariables to bail if it has no work to do (promptVariables is empty) or remove one and do the alert for it.
- (void)promptForVariables {
if (![self.promptVariables count]) return;
self.promptResults = [NSMutableDictionary dictionary];
self.promptVariable = [self.promptVariables anyObject];
[self.promptVariables removeObject:self.promptVariable];
// do your alert here, I won't repeat your code
}
Then when the alert is done, process the result as you have and call promptForVariables again. The next time, since you've changed state, it has less work to do.
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
if (buttonIndex == 0){
if ([[alertView textFieldAtIndex:0] text]){
[self.promptResults setValue:[[alertView textFieldAtIndex:0] text] forKey:self.promptVariable];
}
[self performSelector:#selector(promptForVariables) withObject:nil afterDelay:0.0];
}
}
When this is done, promptResults will contain variable names as keys and user inputs as values.

ShareKit: Customizing text for different sharers (SHKActionSheet)

According to the official FAQ from ver.2 to customize your text/content depending on what sharer was selected by the user, you need:
subclass from SHKActionSheet and override
dismissWithClickedButtonIndex
set your new subclass name in
configurator (return it in (Class)SHKActionSheetSubclass;).
It doesn't work for me. But even more: I put
NSLog(#"%#", NSStringFromSelector(_cmd));
in (Class)SHKActionSheetSubclass to see if it's even got called. And it's NOT ;(( So ShareKit doesn't care about this config option...
Has anybody worked with this before?
thank you!
UPD1: I put some code here.
Here's how my subclass ITPShareKitActionSheet looks like. According to the docs I need to override dismissWithClickedButtonIndex:animated:, but to track if my class gets called I also override the actionSheetForItem::
+ (ITPShareKitActionSheet *)actionSheetForItem:(SHKItem *)item
{
NSLog(#"%#", NSStringFromSelector(_cmd));
ITPShareKitActionSheet *as = (ITPShareKitActionSheet *)[super actionSheetForItem:item];
return as;
}
- (void)dismissWithClickedButtonIndex:(NSInteger)buttonIndex animated:(BOOL)animate
{
NSLog(#"%#", NSStringFromSelector(_cmd));
NSString *sharersName = [self buttonTitleAtIndex:buttonIndex];
[self changeItemForService:sharersName];
[super dismissWithClickedButtonIndex:buttonIndex animated:animate];
}
And here's what I do in code to create an action sheet when user presses 'Share' button:
- (IBAction)shareButtonPressed:(id)sender
{
// Create the item to share
SHKItem *item = [SHKItem text:#"test share text"];
// Get the ShareKit action sheet
ITPShareKitActionSheet *actionSheet = [ITPShareKitActionSheet actionSheetForItem:item];
// Display the action sheet
[actionSheet showInView:self.view]; // showFromToolbar:self.navigationController.toolbar];
}
When I run this code, press 'Share' button and select any sharer I expect to get two lines in log:
actionSheetForItem: - custom action sheet got created
dismissWithClickedButtonIndex:animated: - custom mechanics to
process action sheet's pressed button got called.
But for some reason I get only the first line logged.
I was having the same issues but I've suddenly got it to call my Subclass successfully.
Firstly My Configurator is setup as so:
-(Class) SHKActionSheetSubclass{
return NSClassFromString(#"TBRSHKActionSheet");
}
Now My Subclass:
.h File
#import "SHKActionSheet.h"
#interface TBRSHKActionSheet : SHKActionSheet
#end
.m implementation override:
#import "TBRSHKActionSheet.h"
#import "SHKActionSheet.h"
#import "SHKShareMenu.h"
#import "SHK.h"
#import "SHKConfiguration.h"
#import "SHKSharer.h"
#import "SHKShareItemDelegate.h"
#implementation TBRSHKActionSheet
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
+ (SHKActionSheet *)actionSheetForItem:(SHKItem *)i
{
NSLog(#"%#", NSStringFromSelector(_cmd));
SHKActionSheet *as = [self actionSheetForType:i.shareType];
as.item = i;
return as;
}
- (void)dismissWithClickedButtonIndex:(NSInteger)buttonIndex animated:(BOOL)animated
{
NSInteger numberOfSharers = (NSInteger) [sharers count];
// Sharers
if (buttonIndex >= 0 && buttonIndex < numberOfSharers)
{
bool doShare = YES;
SHKSharer* sharer = [[NSClassFromString([sharers objectAtIndex:buttonIndex]) alloc] init];
[sharer loadItem:item];
if (shareDelegate != nil && [shareDelegate respondsToSelector:#selector(aboutToShareItem:withSharer:)])
{
doShare = [shareDelegate aboutToShareItem:item withSharer:sharer];
}
if(doShare)
[sharer share];
}
// More
else if ([SHKCONFIG(showActionSheetMoreButton) boolValue] && buttonIndex == numberOfSharers)
{
SHKShareMenu *shareMenu = [[SHKCONFIG(SHKShareMenuSubclass) alloc] initWithStyle:UITableViewStyleGrouped];
shareMenu.shareDelegate = shareDelegate;
shareMenu.item = item;
[[SHK currentHelper] showViewController:shareMenu];
}
[super dismissWithClickedButtonIndex:buttonIndex animated:animated];
}
Finally on my implementation file I've not modified the call to SHKActionSheet as Vilem has suggested because of some dependancies that seemed to cause conflicts for me.
So this is my caller (straight from tutorial):
NSURL *url = [NSURL URLWithString:#"http://getsharekit.com"];
SHKItem *item = [SHKItem URL:url title:#"ShareKit is Awesome!" contentType:SHKURLContentTypeWebpage];
// Get the ShareKit action sheet
SHKActionSheet *actionSheet = [SHKActionSheet actionSheetForItem:item];
// ShareKit detects top view controller (the one intended to present ShareKit UI) automatically,
// but sometimes it may not find one. To be safe, set it explicitly
[SHK setRootViewController:self];
// Display the action sheet
[actionSheet showFromToolbar:self.navigationController.toolbar];
This Calls no problems for me.
edit: by far the best way to achieve this is to use SHKShareItemDelegate. More info is in ShareKit's FAQ.

Use camera scan QRCode or BarCode in ObjectiveC

I want to build an app to scan QRCode and Barcode. I want to use camera scan image contains the code (QRCode or BarCode) but not take photo. Now I have no idea to do it. Anyone, give some references, please!
You should look at: http://zbar.sourceforge.net/
Download the ZBarSDK and import it in pch file then use this code
// BarCodeView.h
#interface BarCodeView : UIViewController < ZBarReaderDelegate > {
UIImageView *resultImage;
UITextView *resultText;
}
#property (nonatomic, retain) IBOutlet UIImageView *resultImage;
#property (nonatomic, retain) IBOutlet UITextView *resultText;
- (IBAction) scanButtonTapped;
// BarCodeView.m
#synthesize resultImage, resultText;
- (IBAction) scanButtonTapped
{
NSLog(#"TBD: scan barcode here...");
// ADD: present a barcode reader that scans from the camera feed
ZBarReaderViewController *reader = [ZBarReaderViewController new];
reader.readerDelegate = self;
reader.supportedOrientationsMask = ZBarOrientationMaskAll;
ZBarImageScanner *scanner = reader.scanner;
// TODO: (optional) additional reader configuration here
// EXAMPLE: disable rarely used I2/5 to improve performance
[scanner setSymbology: ZBAR_I25
config: ZBAR_CFG_ENABLE
to: 0];
// present and release the controller
[self presentModalViewController: reader
animated: YES];
[reader release];
}
- (void) imagePickerController: (UIImagePickerController*) reader didFinishPickingMediaWithInfo: (NSDictionary*) info
{
// ADD: get the decode results
id<NSFastEnumeration> results =
[info objectForKey: ZBarReaderControllerResults];
ZBarSymbol *symbol = nil;
for(symbol in results)
// EXAMPLE: just grab the first barcode
break;
// EXAMPLE: do something useful with the barcode data
resultText.text = symbol.data;
// EXAMPLE: do something useful with the barcode image
resultImage.image =
[info objectForKey: UIImagePickerControllerOriginalImage];
// ADD: dismiss the controller (NB dismiss from the *reader*!)
[reader dismissModalViewControllerAnimated: YES];
}
The two most active projects are ZBar and ZXing.
You didn't mention if you were targeting iOS or OS X. I don't believe ZBar suports OS X. ZXing does. I believe ZBar has better support for 1D codes than the C++-based ports of ZXing.
(FWIW, I'm an active contributor to the C++/OS X/iOS port of ZXing.)

passing button id from one .m to another .m

Need to pass a button id from one .m to another and clear my table view at the same time so i can load new data in. Nothing seems to be happening, the table still contains what it was populated with on viewDidLoad and the background image does not change. Please help.
There are no warning or errors so im not sure what im doing wrong but the value of senderIdentifier in ClassTwo.h is always 0
Thank you.
in my classOne.m i have the following button action
-(IBAction) btnPushViewtabel:(id)sender{
ClassTwo *classtwo = [[ClassTwo alloc]init];
classtwo.myTable = nil;
classtwo.senderIdentifier = [sender tag];
[self.view addSubview:viewtableController.view];
}
in ClassTwo.h
#interface ClassTwo : UIViewController <UITableViewDelegate, UITableViewDataSource> {
....
int senderIdentifier;
}
#property (nonatomic, readwrite) int senderIdentifier;
in ClassTwo.m
if(senderIdentifier == 0){
// getNewData
//set background img1
} else {
// getNewData
//set background img2
}
if(mySenderIdentifier == 0){ //
getNewData //set background img1 }
else { // getNewData //set
background img2 }
what method is this code block in?
Edit:
This Line:
classtwo.mySenderIdentifier = [sender
tag];
is called after:
viewDidLoad
In other words- when you are checking it you havn't actually set it yet.
There are a number of ways to solve this but my personal preference would be to create a custom init method for classTwo like this:
-(id)initWithSenderIdentifier:(int)identifier{
if(self=[super init]){
self.senderIdentifier = identifier;
self.myTable = nil;
}
return self;
}
Or elimate the need to store the int (given that's only used to set the background once)
-(id)initWithSenderIdentifier:(int)identifier{
if(self=[super init]){
if(identifier)//set backgroundimg1;
else //set backgroundimg2;
self.myTable = nil;
}
return self;
}
you use it like this:
ClassTwo *classtwo = [[ClassTwo alloc]
initWithSenderIdentifier:[sender tag]];
If this is helpful, please mark it was answered