UIImage 设置器 NSInvalidArgumentException

发布于 2024-12-19 16:22:49 字数 832 浏览 2 评论 0原文

类中的对象设置器存在问题。 我有 GEOImage 类,其中描述、标题等内容将根据 到图像。

@interface GEOImage : UIImage
{
    NSString *title;
    NSString *imgDescription;
    NSString *latitude;
    NSString *longitude;
    NSDictionary *editInfo;
}
@property (nonatomic, copy) NSString *title, *imgDescription, *latitude, *longitude;
@property (nonatomic, copy) NSDictionary *editInfo;
@end

现在我尝试存储另一个类的描述:

self.chosenImage.imgDescription = @"description";

其中 selectedImage 的类型为 GEOImage。

但我收到错误:

-[UIImage setTitle:]:无法识别的选择器发送到实例 0x939d220 2011-12-05 10:59:40.621 GeoPG[511:17c03] * 由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“-[UIImage setTitle:]:无法识别的选择器发送到实例 0x939d220 '

如果我在调试器中查找,则选择的图像不是NULL,并且在图像视图中正确显示。

问候 s4l鱼

have a problem with object setters in a class.
I have the class GEOImage, where things like description, title etc. will be saved according
to an image.

@interface GEOImage : UIImage
{
    NSString *title;
    NSString *imgDescription;
    NSString *latitude;
    NSString *longitude;
    NSDictionary *editInfo;
}
@property (nonatomic, copy) NSString *title, *imgDescription, *latitude, *longitude;
@property (nonatomic, copy) NSDictionary *editInfo;
@end

Now i try to store a description out of another class:

self.chosenImage.imgDescription = @"description";

where chosenImage is of type GEOImage.

But i get the error:

-[UIImage setTitle:]: unrecognized selector sent to instance 0x939d220
2011-12-05 10:59:40.621 GeoPG[511:17c03] * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIImage setTitle:]: unrecognized selector sent to instance 0x939d220'

If I'm looking in the debugger, the chosenImage is not NULL, and its been displayed correct in an image view.

Greets
s4lfish

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

我做我的改变 2024-12-26 16:22:49

我们可以安全地推断 chosenImage 不是 nil;如果它是nil,那么向它发送消息将不会执行任何操作,也不会崩溃。

(另外,我假设您在使用示例中指的是 title 而不是 imgDescription,或者您实现了 setImgDescription: 来设置 <依次为 code>title。)

有两种可能性:

死亡对象

您创建了存储到 chosenImage 的图像作为 GEOImage,但随后它在您持有它时死亡了。随后,在同一地址创建了一个 UIImage(如异常消息中所示),因此您现在仍然持有的指针指向 UIImage。您向它发送了一条仅适用于 GEOImage 的消息,但它只是一个 UIImage,因此它不会响应该消息,这是例外。

一个物体在你持有时死亡的原因是,要么你没有把它保留在你应该保留的地方,要么你把它释放到了你不应该保留的地方。或者可能两者兼而有之。

使用 Zombies 模板在 Instruments 下运行您的应用程序。当您遇到此崩溃时,它会升起一个标志,然后您可以通过单击该标志中的按钮进行调查。从末尾开始查看所有的 Release 和 Autorelease 事件,找到不应该出现的事件;然后,如果释放本身是无根据的,请将其取出,或者如果它应该由先前的保留来平衡,则将其中之一放入。

崩溃的一个可能原因是您声明了 chosenImage 属性为分配,但您应该将其声明为retain/strong。如果这是问题所在,您的 Instruments 调查结果将支持该问题。

从长远来看,您应该转换为 ARC,这可以消除 90% 可能发生此问题的情况。

您一开始就没有创建过 GEOImage

仅仅因为您声明 chosenImage 将保存指向 GEOImage 的指针并不意味着它确实如此。您可以在那里分配任何对象指针,并且在许多情况下,编译器不知道它是否实际上不是 GEOImage。

(他们在 Clang 的未来版本中引入了一个名为“相关结果类型”的功能,这应该会大大降低这种可能性。)

据猜测,我会说你正在做这样的事情:

self.chosenImage = [GEOImage imageNamed:@"blah blah blah"];

或者这样:

self.chosenImage = [imagePicker takePicture];

没有理由这样做期望 takePicture 返回一个 GEOImage (它怎么知道这就是你想要的?),并且很可能 +[UIImage imageNamed:] (假设你只是继承它)获胜也不是。除非您自己使用 alloc 和初始化程序创建 GEOImage 实例,否则您不能假设您获得的任何 UIImage 都是 GEOImage。

解决方案是让从 UIImage 创建 GEOImage 变得容易(这将涉及包装 这个方法),然后执行 那。


一旦您的 chosenImage 属性中有一个活动的(不是死的)GEOImage(不是 UIImage),它就会起作用。

We can safely infer that chosenImage is not nil; if it were nil, sending it a message would simply do nothing, not crash.

(Also, I'm assuming that you meant title rather than imgDescription in your usage sample, or that you implemented setImgDescription: to set the title in turn.)

There are two possibilities:

Dead object

You created the image you stored to chosenImage as a GEOImage, but then it died while you were holding on to it. Subsequently, a UIImage (as identified in the exception message) was created at the same address, so the pointer you still hold now points to a UIImage. You sent a message to it that only works on GEOImages, but it's only a UIImage, so it doesn't respond to the message, which is the exception.

The cause of an object dying while you're holding it is that either you didn't retain it somewhere where you should have, or you released it somewhere where you shouldn't have. Or possibly both.

Run your app under Instruments with the Zombies template. It will raise a flag when you hit this crash, and you can then investigate by clicking the button in that flag. Look at all of the Release and Autorelease events, starting from the end, to find the one that shouldn't be there; then, if the release itself is unwarranted, take it out, or if it should be balanced by a previous retain, put one of those in.

One possible cause of the crash is that you declared the chosenImage property as assign, but you should have declared it as retain/strong. If this is the problem, your Instruments findings will support it.

Long-term, you should convert to ARC, which eliminates 90% of the cases where this problem could happen.

You never created a GEOImage in the first place

Just because you declared that chosenImage will hold a pointer to a GEOImage doesn't mean it does. You can assign any object pointer there, and in many cases, the compiler doesn't know if it isn't actually a GEOImage.

(They introduced a feature called “related result types” in a future version of Clang that should make this much less likely.)

At a guess, I'd say you're doing something like this:

self.chosenImage = [GEOImage imageNamed:@"blah blah blah"];

or this:

self.chosenImage = [imagePicker takePicture];

There is no reason to expect takePicture to return a GEOImage (how should it know that's what you want?), and it's likely that +[UIImage imageNamed:] (assuming you simply inherit it) won't, either. Unless you create a GEOImage instance yourself, using alloc and an initializer, you cannot assume that any UIImage you get will be a GEOImage.

The solution is to make it easy to create a GEOImage from a UIImage (which will involve wrapping this method), and then do that.


Once you have a live (not dead) GEOImage (not UIImage) in your chosenImage property, it will work.

拥有 2024-12-26 16:22:49

事实上,就像 Peter 所说:我从未创建过 GEOImage。我现在像这样创建 GEOImage:

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
    UIImage *image = [info valueForKey:@"UIImagePickerControllerOriginalImage"];
    NSURL *imgURL = [info valueForKey:@"UIImagePickerControllerMediaURL"];
    CGImageRef imageRef = [image CGImage];
    [self createGEOImage:imageRef info:info imageURL:imgURL];
}

以及使用 imageRef 调用的方法:

- (void)createGEOImage:(CGImageRef*)imageRef info:(NSDictionary*)info imageURL:(NSURL*)imgURL{
    GEOImage *geoImage = [[GEOImage alloc]initWithCGImage:imageRef];
    geoImage = info;
    geoImage = imgURL;
}

感谢您的帮助!

In fact, it was like Peter said: I never created an GEOImage. I now I create the GEOImage like this:

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
    UIImage *image = [info valueForKey:@"UIImagePickerControllerOriginalImage"];
    NSURL *imgURL = [info valueForKey:@"UIImagePickerControllerMediaURL"];
    CGImageRef imageRef = [image CGImage];
    [self createGEOImage:imageRef info:info imageURL:imgURL];
}

And the method called with the imageRef:

- (void)createGEOImage:(CGImageRef*)imageRef info:(NSDictionary*)info imageURL:(NSURL*)imgURL{
    GEOImage *geoImage = [[GEOImage alloc]initWithCGImage:imageRef];
    geoImage = info;
    geoImage = imgURL;
}

Thanks for your help!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文