has anyone seen "[StdMovieUISliderCell sliderType]: unrecognized selector sent to instance" - cocoa

I am using QTMovieView and , sometimes, I get the following log and follow by an unknown selector exception. The program has options for users to set to show and hide controller of the QTMovieView. The SDK that the program is linking against is 10.7
"[StdMovieUISliderCell sliderType]: unrecognized selector sent to instance"
thanks for any help

This looks like a bug that was introduced in OS X Mountain Lion 10.8 (Edit: there are also reports on OS X 10.7, see comments below) . I guess that QTMovieView will get deprecated in one of the next major OS X releases. The best solution is to move to AV Foundation (AVPlayer and the corresponding AVPlayerLayer class). Apple has some documentation about playing back assets using this framework.
That said, if you can’t update to AV Foundation or you can’t turn off Auto Layout, you still can fix this issue by adding the missing methods dynamically during runtime to the StdMovieUISliderCell class. Make sure to add the Objective C runtime header file and to add the methods as early as possible (e.g. + (void)load in your application delegate). For App Store static analyzer rejection foo reasons, it’s also safe to add some simple encoding to the class name like rot13.
// Make sure that we have the right headers.
#import <objc/runtime.h>
// The selectors should be recognized by class_addMethod().
#interface NSObject (SliderCellBugFix)
- (NSSliderType)sliderType;
- (NSInteger)numberOfTickMarks;
#end
// Add C implementations of missing methods that we’ll add
// to the StdMovieUISliderCell class later.
static NSSliderType SliderType(id self, SEL _cmd)
{
return NSLinearSlider;
}
static NSInteger NumberOfTickMarks(id self, SEL _cmd)
{
return 0;
}
// rot13, just to be extra safe.
static NSString *ResolveName(NSString *aName)
{
const char *_string = [aName cStringUsingEncoding:NSASCIIStringEncoding];
NSUInteger stringLength = [aName length];
char newString[stringLength+1];
NSUInteger x;
for(x = 0; x < stringLength; x++)
{
unsigned int aCharacter = _string[x];
if( 0x40 < aCharacter && aCharacter < 0x5B ) // A - Z
newString[x] = (((aCharacter - 0x41) + 0x0D) % 0x1A) + 0x41;
else if( 0x60 < aCharacter && aCharacter < 0x7B ) // a-z
newString[x] = (((aCharacter - 0x61) + 0x0D) % 0x1A) + 0x61;
else // Not an alpha character
newString[x] = aCharacter;
}
newString[x] = '\0';
return [NSString stringWithCString:newString encoding:NSASCIIStringEncoding];
}
// Add both methods if they aren’t already there. This should makes this
// code safe, even if Apple decides to implement the methods later on.
+ (void)load
{
Class MovieSliderCell = NSClassFromString(ResolveName(#"FgqZbivrHVFyvqrePryy"));
if (!class_getInstanceMethod(MovieSliderCell, #selector(sliderType)))
{
const char *types = [[NSString stringWithFormat:#"%s%s%s",
#encode(NSSliderType), #encode(id), #encode(SEL)] UTF8String];
class_addMethod(MovieSliderCell, #selector(sliderType),
(IMP)SliderType, types);
}
if (!class_getInstanceMethod(MovieSliderCell, #selector(numberOfTickMarks)))
{
const char *types = [[NSString stringWithFormat: #"%s%s%s",
#encode(NSInteger), #encode(id), #encode(SEL)] UTF8String];
class_addMethod(MovieSliderCell, #selector(numberOfTickMarks),
(IMP)NumberOfTickMarks, types);
}
}
I made two assumptions while implementing both methods:
A movie view can only have a linear slider, not a circular one.
A movie view won’t have tick marks.
The latter could be a problem if your movie has chapters, but I don’t know how they are handled, because I don’t need or use them.

I had the same problem if I tried to use setMovie: with AutoLayout on. An update to Xcode 4.4.1 fixed the problem.

i know it's a fairly old post, but for others out there, i had the same problem, i've just deactivated the cocoa autolayout for the xib file containing the QTMovieView and it worked like it should have.
i'm currently working with xcode 4.5.2 under OSX 10.7.4

Fixed this issue by adding empty updateConstraintsForSubtreeIfNeeded method in QtMovieView subclass.

Related

Testing for existence of a property (i.e. numberOfValidItemsForDrop)

My general question is if and how it is possible to test to see if an arbitrary object supports a given property. For methods, this is simple. I would send a respondsToSelector: message to the object and check the result. I cannot find a similar mechanism for properties.
My specific problem at hand is that I'm writing a custom NSView that supports dropping of image files (plural) onto it. I am building on 10.9 and deploying on 10.6. For machines running 10.7 and later, I would like to take advantage of the user feedback provided in the drag image (number and acceptable files) by enumerateDraggingItemsWithOptions:... method and the numberOfValidItemsForDrop property.
My initial thought is as follows. Test the sender (declared id < NSDraggingInfo >) provided to the draggingEntered: method. If so, use the mechanisms provided in 10.7. If not, go back to the earlier mechanisms.
if( [sender respondsToSelector:#selector(enumerateDraggingItemsWithOptions:forView:classes:searchOptions:usingBlock:) ] )
{
__block NSInteger n=0;
[sender enumerateDraggingItemsWithOptions:NSDraggingItemEnumerationClearNonenumeratedImages
forView:self
classes:types
searchOptions:options
usingBlock:^(NSDraggingItem *draggingItem, NSInteger idx, BOOL *stop) { ++n; } ];
self.numberOfValidItemsForDrop = n;
rval = (n>0 ? NSDragOperationCopy : NSDragOperationNone);
}
else
{
NSArray *itemsInDrag = [[sender draggingPasteboard] readObjectsForClasses:types options:options];
rval = [itemsInDrag count]>0 ? NSDragOperationCopy : NSDragOperationNone);
}
My concern is whether or not the assignment to the numberOfValidItemsForDrop will cause problems in the 10.6 environment. I threw together a quick test in which I assigned to a bogus property inside an if(0) condition and the compiler choked.
if(0)
{
sender.bogus=1;
}
This is not really the same thing as the property is not valid in the development environment. But, it has me concerned that the assignment to numberOfValidItemsForDrop might also have a problem at runtime on 10.6 even though it should never actually be executed.
I have thrown together a small dummy application which I have sent to my tester, but have not yet heard back and would like to keep moving on this project.
Thanks for any/all info.
You can use the Objective-C runtime function class_getProperty to test for the existence of a named property:
if(class_getProperty([self class], "numberOfValidItemsForDrop")) {
// property exists
}
See https://developer.apple.com/library/mac/documentation/Cocoa/Reference/ObjCRuntimeRef/Reference/reference.html
To check if a property exists or not, you can use as : the property is assumed not to be readonly.
if ([yourClassObject respondsToSelector:#selector(set<yourPropertyName>:)]) {
NSLog(#"yes it exists");
}
else{
NSLog(#"no it doesn't exists");
}

CoreMIDI call back function issue with using bridge casting on void pointer

Background: I am trying to write a program that will take MIDI information from my synthesizer and do various things with it musically. I have already connected the keyboard so that I receive MIDI data. In my midiInputCallback() method, which is the method that is called when MIDI data is generated, it takes 3 parameters: a MIDIPacketList, any object from "the outside" and the input source of the MIDI info. I'm trying to use the second parameter to pass in a UIButton. For now, I am using UIButtons for the piano keys. When I play on my synth, I want it to show (on my GUI) that a certain note has been played. To show this, the button that is associated with the key on my keyboard will appear "pressed".
Problem: Just to test this process, I tried passing in a NSNumber called test.
- (void)awakeFromNib {
MIDIClientRef midiClient;
checkError(MIDIClientCreate(CFSTR("MIDI client"), NULL, NULL, &midiClient), "MIDI client creation error");
test = [NSNumber numberWithInt:4];
MIDIPortRef inputPort;
checkError(MIDIInputPortCreate(midiClient, CFSTR("Input"), midiInputCallback, &test, &inputPort), "MIDI input port error");
unsigned long sourceCount = MIDIGetNumberOfSources();
for (int i = 0; i < sourceCount; ++i) {
MIDIEndpointRef endPoint = MIDIGetSource(i);
CFStringRef endpointName = NULL;
checkError(MIDIObjectGetStringProperty(endPoint, kMIDIPropertyName, &endpointName), "String property not found");
checkError(MIDIPortConnectSource(inputPort, endPoint, NULL), "MIDI not connected");
}
}
I pass test into MIDIInputPortCreate() which sets up the callback method as midiInputCallback().
Here's what midiInputCallBack() looks likes:
static void midiInputCallback(const MIDIPacketList *list, void *procRef, void *srcRef) {
NSNumber *test = (__bridge_transfer NSNumber*)procRef;
NSLog(#"%#", test);
...
I tried regular casting at first: NSNumber test = (NSNUmber) procRef, but then XCode said to use some bridge casting instead. I've read up on this a bit and someone suggested to use __bridge_transfer instead of just __bridge. Each time I run this I get a EXC_BAD_ACCESS(code=1, address=0x43f) error for my NSLog() in midiInputCallback() and I'm not sure how to proceed. Let me know if you need more information. I'm fairly new to developing for the Mac. Thanks in advance!
Had the same problem some time ago when writing a similar app that receives MIDI input and logs it to the console.
Am assuming you are working with ARC.
Have solved the problem as follows:
First, I did the following cast (that would be in your awakeFromNib method, whereas &test would be some_object):
SomeClass *some_object = [[SomeClass alloc] init];
MIDIInputPortCreate(midiClient, CFSTR("Input"), midiInputCallback, (__bridge_retained void *)some_object, &inputPort);
Then, inside midiInputCallback, I have casted it back with:
SomeClass *some_object = (__bridge SomeClass*)procRef;
Hope I don't have any typos here, just did a quick copy and paste with some modifications for the context of this answer.
Checkout the following question and its answers, helped me a lot understanding it:
ARC and bridged cast

How to detect that a provisioning profile is for development or distribution, programmatically

I would like to detect if a given provisioning profile is a development profile or a distribution (adhoc or app store) profile. I need to do this purely programmatically.
I already understand how to detect adhoc vs appstore. And am specifically interested in dev vs. distribution.
I've examined the plists internal to each type of profile and cannot find a discernable difference (via security cms -D -i #{#profilePath}). I've also looked into the openssl api and am using this for some certificate manipulation.
This is for a custom xcode automated build system. As part of pre-build validation I need to ensure that the specified profile is not for development.
Is this even possible? If so, how can I programmatically differentiate between the two?
Thanks in advance for any ideas!
I've build a more concise and efficient version of Toom's code:
I'll maintain code snippets like this in a gist, you might find a more up to date version here: https://gist.github.com/steipete/7668246
static BOOL PSPDFIsDevelopmentBuild(void) {
#if TARGET_IPHONE_SIMULATOR
return YES;
#else
static BOOL isDevelopment = NO;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// There is no provisioning profile in AppStore Apps.
NSData *data = [NSData dataWithContentsOfFile:[NSBundle.mainBundle pathForResource:#"embedded" ofType:#"mobileprovision"]];
if (data) {
const char *bytes = [data bytes];
NSMutableString *profile = [[NSMutableString alloc] initWithCapacity:data.length];
for (NSUInteger i = 0; i < data.length; i++) {
[profile appendFormat:#"%c", bytes[i]];
}
// Look for debug value, if detected we're a development build.
NSString *cleared = [[profile componentsSeparatedByCharactersInSet:NSCharacterSet.whitespaceAndNewlineCharacterSet] componentsJoinedByString:#""];
isDevelopment = [cleared rangeOfString:#"<key>get-task-allow</key><true/>"].length > 0;
}
});
return isDevelopment;
#endif
}
This was something I tackled in one of my own build systems for much the same purpose...let's take a trip back in time to Day 1 of the then 'iPhone Developer Program'. If you were around the community at that time, you may remember that the toolchain was...shall we say less friendly...than it is today.
When you wanted to build for the AppStore or for AdHoc builds you had to make this curious entitlements.plist file, then paste a blob of XML into the body of that file. You then ran the build and at that time what appeared to be magic occurred and the sheer presence of that file made the build work, allowed you to manually construct your IPA, and carry on with business as usual. Now that we are a few years older and hopefully a bit wiser than in those early days of the SDK, we have come to recognize that the magic XML blob wasn't actually so magical at all -- the 'get-task-allow' key is a setting to indicate if the binary should allow other processes (like perhaps a debugger) to attach to the binary. When signing apps using a Development Provisioning Profile, this key will be set to 'true' (and thus allow LLDB to attach and interact with your app)...and naturally when signing apps using a Distribution Provisioning Profile, this key will be set to 'false'.
Apple has provided some updates in Tech Note TN2250 about reading the XML (and by extension the entitlements) out of Provisioning Profiles:
security cms -D -i /path/to/the.app/embedded.mobileprovision
This will return the XML in the Provisioning profile -- from there you can parse out the key value pair for 'get-task-allow' and use that value to determine if the Provisioning Profile is Development or Distribution.
I absolutely agree that it would be nice to have a tool that would tell us that directly so we don't have to sniff through the profile for clues, but at the same time, at least we have a highly reliable, albeit roundabout way to make that distinction before running off and making a build we can't use.
Good luck and let me know if you need any more clarification or have other questions.
Based on Bryan Musial great answer I wrote some code that allow you to check "get-task-allow" directly from application at runtime. In my case I'm using this boolean to only log in debug apps :
+ (BOOL)isDevelopmentApp
{
// Special case of simulator
if (isSimulator)
{
return YES;
}
// There is no provisioning profile in AppStore Apps
NSString *profilePath = [[NSBundle mainBundle] pathForResource:#"embedded" ofType:#"mobileprovision"];
// Check provisioning profile existence
if (profilePath)
{
// Get hex representation
NSData *profileData = [NSData dataWithContentsOfFile:profilePath];
NSString *profileString = [NSString stringWithFormat:#"%#", profileData];
// Remove brackets at beginning and end
profileString = [profileString stringByReplacingCharactersInRange:NSMakeRange(0, 1) withString:#""];
profileString = [profileString stringByReplacingCharactersInRange:NSMakeRange(profileString.length - 1, 1) withString:#""];
// Remove spaces
profileString = [profileString stringByReplacingOccurrencesOfString:#" " withString:#""];
// Convert hex values to readable characters
NSMutableString *profileText = [NSMutableString new];
for (int i = 0; i < profileString.length; i += 2)
{
NSString *hexChar = [profileString substringWithRange:NSMakeRange(i, 2)];
int value = 0;
sscanf([hexChar cStringUsingEncoding:NSASCIIStringEncoding], "%x", &value);
[profileText appendFormat:#"%c", (char)value];
}
// Remove whitespaces and new lines characters
NSArray *profileWords = [profileText componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
NSString *profileClearText = [profileWords componentsJoinedByString:#""];
// Look for debug value
NSRange debugRange = [profileClearText rangeOfString:#"<key>get-task-allow</key><true/>"];
if (debugRange.location != NSNotFound)
{
return YES;
}
}
// Return NO by default to avoid security leaks
return NO;
}
Here is a version for Swift 3, based on #steipete's answer:
static func isDevelopmentProvisioningProfile() -> Bool {
#if IOS_SIMULATOR
return true
#else
// there will be no provisioning profile in AppStore Apps
guard let fileName = Bundle.main.path(forResource: "embedded", ofType: "mobileprovision") else {
return false
}
let fileURL = URL(fileURLWithPath: fileName)
// the documentation says this file is in UTF-8, but that failed
// on my machine. ASCII encoding worked ¯\_(ツ)_/¯
guard let data = try? String(contentsOf: fileURL, encoding: .ascii) else {
return false
}
let cleared: String = data.components(separatedBy: .whitespacesAndNewlines).joined()
return cleared.contains("<key>get-task-allow</key><true/>")
#endif
}
If curious, get-task-allow is a flag that the build uses to determine whether you should be able to hook up a debugger and other processes like that - so it's quite accurate for whether it is a dev build or no.

How do you set a label text as something from an NSMutableArray?

I am trying to understand how to set a label to be the text from an array when you press the button. When I press the button, the label disappears, and then nothing comes up. No crashes in code.
Relevant code:
-(void)setupArray {
wordArray = [[NSMutableArray alloc] init];
[wordArray addObject:#"test1"];
[wordArray addObject:#"test2"];
[wordArray addObject:#"test3"];
}
- (IBAction)start:(id)sender {
int value = (arc4random() % 3) + 1;
self.typeThis.text = [self.wordArray objectAtIndex:value];
}
typeThis is the label name, and I think I have hooked up everything already, i.e. set up the buttons/delegates/etc...I don't understand why it isn't working. Can anybody help?
considering you have bound everything properly and you are not under ARC. Here is a thing that might cause you the issue.
when you are allocating wordArray you can try using following code snippet.
NSMutableArray tempArray = [[NSMutableArray alloc] init];
self.wordArray = tempArray;
[tempArray release];
if you are under ARC you can try self.wordArray = [NSMutableArray array];
then add objects to self.wordArray i.e.[self.wordArray addObject:#"test1"];. Here is some explanation about arc4random().
EDIT :
Here's a public spec for Automatic Reference Counting and a quote from the public iOS 5 page:
Automatic Reference Counting (ARC) for Objective-C makes memory
management the job of the compiler. By enabling ARC with the new Apple
LLVM compiler, you will never need to type retain or release again,
dramatically simplifying the development process, while reducing
crashes and memory leaks. The compiler has a complete understanding of
your objects, and releases each object the instant it is no longer
used, so apps run as fast as ever, with predictable, smooth
performance.
It is possible to detect if ARC is enabled. Simply add the following snippet to any file that requires ARC.
#ifndef __has_feature
#define __has_feature(x) 0 /* for non-clang compilers */
#endif
#if !__has_feature(objc_arc)
#error ARC must be enabled!
#endif
More info :
http://clang.llvm.org/docs/LanguageExtensions.html#__has_feature_extension
HTH.
Your '+1' is giving you a result between 1 and 3, and your indexes are from 0 to 2, so I'd expect it to go wrong one time in 3.
Is this under ARC? If so, is wordArray declare as strong?

Deep copy of dictionaries gives Analyze error in Xcode 4.2

I have the following method in a NSDictionary category, to do a deep copy, which works fine.
I just upgraded from Xcode 4.1 to 4.2, and the Analyze function gives two analyzer warnings for this code, as indicated:
- (id)deepCopy;
{
id dict = [[NSMutableDictionary alloc] init];
id copy;
for (id key in self)
{
id object = [self objectForKey:key];
if ([object respondsToSelector:#selector(deepCopy)])
copy = [object deepCopy];
else
copy = [object copy];
[dict setObject:copy forKey:key];
// Both -deepCopy and -copy retain the object, and so does -setObject:forKey:, so need to -release:
[copy release]; // Xcode 4.2's Analyze says this is an incorrect decrement of the reference count?!
}
return dict; // Xcode 4.2's Analyze says this is a potential leak
}
Are these bugs in Xcode's analyzer, or are there changes I can make to avoid these warnings?
I'm not using ARC yet, though I am interested if there are additional changes needed to support ARC for this method.
Presumably, it is because deepCopy does not begin with the prefix copy.
So you may want to change to something like copyWithDeepCopiedValues (or something like that), and then see if the analyzer flags that.
Update
As Alexsander noted, you can use attributes to denote reference counting intent. This should (IMO) be the exception to the rule, and used rarely, if ever. Personally, I will not use attributes for objc methods because it is fragile.
The only attribute I have used so far has been consume, and every time I use these attributes has been in statically typed contexts (e.g. C functions and C++ functions and methods).
The reasons you should avoid attributes when possible:
1) Stick with conventions for the programmers' sake. The code is clearer and you do not need to refer to the documentation.
2) The approach is fragile. You can still introduce reference count imbalances, and attributes can be used to introduce build errors due to conflicts in attributes.
The following cases are all built with ARC enabled:
Case #1
#import <Foundation/Foundation.h>
#interface MONType : NSObject
- (NSString *)string __attribute__((objc_method_family(copy)));
#end
#implementation MONType
- (NSString *)string
{
NSMutableString * ret = [NSMutableString new];
[ret appendString:#"MONType"];
return ret;
}
#end
int main (int argc, const char * argv[])
{
#autoreleasepool {
id obj = nil;
if (random() % 2U) {
obj = [[NSAttributedString alloc] initWithString:#"NSAttributedString"];
}
else {
obj = [MONType new];
}
NSLog(#"Result: %#, %#", obj, [obj string]);
}
/* this tool's name is ARC, dump the leaks: */
system("leaks ARC");
return 0;
}
This program produces the following error: error: multiple methods named 'string' found with mismatched result, parameter type or attributes.
Great, the compiler's doing what it can to prevent these issues. What that means is that conflicts in attributes can introduce errors based on the translation. This is bad because when nontrivial codebases are combined and attributes conflict, you will have errors to correct and programs to update. This also means that simply including other libraries in translation units can break existing programs when attributes are used.
Case #2
Header.h
extern id NewObject(void);
Header.m
#import <Foundation/Foundation.h>
#import "Header.h"
#interface MONType : NSObject
- (NSString *)string __attribute__((objc_method_family(copy)));
#end
#implementation MONType
- (NSString *)string
{
NSMutableString * ret = [NSMutableString new];
[ret appendString:#"-[MONType string]"];
return ret;
}
#end
id NewObject(void) {
id obj = nil;
if (random() % 2U) {
obj = [[NSAttributedString alloc] initWithString:#"NSAttributedString"];
}
else {
obj = [MONType new];
}
return obj;
}
main.m
#import <Foundation/Foundation.h>
#import "Header.h"
int main (int argc, const char * argv[])
{
#autoreleasepool {
for (size_t idx = 0; idx < 8; ++idx) {
id obj = NewObject();
NSLog(#"Result: %#, %#", obj, [obj string]);
}
}
/* this tool's name is ARC, dump the leaks: */
system("leaks ARC");
return 0;
}
Ok. This is just bad. We've introduced leaks because the necessary information was not available in the translation unit. Here's the leaks report:
leaks Report Version: 2.0
Process 7778: 1230 nodes malloced for 210 KB
Process 7778: 4 leaks for 192 total leaked bytes.
Leak: 0x1005001f0 size=64 zone: DefaultMallocZone_0x100003000 __NSCFString ObjC CoreFoundation mutable non-inline: "-[MONType string]"
Leak: 0x100500320 size=64 zone: DefaultMallocZone_0x100003000 __NSCFString ObjC CoreFoundation mutable non-inline: "-[MONType string]"
Leak: 0x100500230 size=32 zone: DefaultMallocZone_0x100003000 has-length-byte: "-[MONType string]"
Leak: 0x100500390 size=32 zone: DefaultMallocZone_0x100003000 has-length-byte: "-[MONType string]"
note: the count may differ because we used random()
This means that because MONType is not visible to main(), the compiler bound the ARC properties to methods which were visible to the current TU (that is, string from declarations in Foundation, all of which follow convention). As a result, the compiler got it wrong and we were able to introduce leaks into our program.
Case 3
Using a similar approach, I was also able to introduce negative reference count imbalances (premature releases, or a messaged zombie).
note: Code not provided because Case #2 already illustrates how one can accomplish a reference count imbalance.
Conclusion
You can avoid all these problems and improve readability and maintainability by sticking with convention, rather than using attributes.
Bringing the conversation back to non-ARC code: Using attributes makes manual memory management more difficult for programmers' readability, and for the tools which are there to help you (e.g. compiler, static analysis). If the program is suitably complex such that the tools can't detect such errors, then you should reconsider your design, because it will be equally complex for you or somebody else to debug these issues.
Adding onto #Justin's answer, you can tell the compiler that -deepCopy returns a retained object by appending the NS_RETURNS_RETAINED attribute to the method's declaration like so:
- (id) deepCopy NS_RETURNED_RETAINED;
Alternatively, you can use explicitly control the method's "family" using the objc_method_family attribute like so:
- (id) deepCopy __attribute__((objc_method_family(copy)));
If you do this, the compiler will know that this method is in the copy family and returns a copied value.

Resources