Frage

Ich versuche, Bilder auf dem iPhone mit mit abgerundeten Ecken, a la die Kontaktbilder in der Kontakte-Anwendung zu ziehen. Ich habe Code bekam, die im Allgemeinen arbeiten, aber es stürzt gelegentlich innerhalb der UIImage Zeichenroutinen mit einem EXEC_BAD_ACCESS - KERN_INVALID_ADDRESS. Ich dachte, dies könnte auf die Frage beschneiden ich vor ein paar Wochen gefragt, aber ich glaube, ich m korrekt den Beschneidungspfad einrichten.

Hier ist der Code ist verwende ich -. Wenn es nicht abstürzt, ist das Ergebnis sieht gut aus und jemand sucht einen ähnlichen Blick zu erhalten, ist frei, den Code zu leihen

- (UIImage *)borderedImageWithRect: (CGRect)dstRect radius:(CGFloat)radius {
    UIImage *maskedImage = nil;

    radius = MIN(radius, .5 * MIN(CGRectGetWidth(dstRect), CGRectGetHeight(dstRect)));
    CGRect interiorRect = CGRectInset(dstRect, radius, radius);

    UIGraphicsBeginImageContext(dstRect.size);
    CGContextRef maskedContextRef = UIGraphicsGetCurrentContext();
    CGContextSaveGState(maskedContextRef);

    CGMutablePathRef borderPath = CGPathCreateMutable();
    CGPathAddArc(borderPath, NULL, CGRectGetMinX(interiorRect), CGRectGetMinY(interiorRect), radius, PNDegreeToRadian(180), PNDegreeToRadian(270), NO);
    CGPathAddArc(borderPath, NULL, CGRectGetMaxX(interiorRect), CGRectGetMinY(interiorRect), radius, PNDegreeToRadian(270.0), PNDegreeToRadian(360.0), NO);
    CGPathAddArc(borderPath, NULL, CGRectGetMaxX(interiorRect), CGRectGetMaxY(interiorRect), radius, PNDegreeToRadian(0.0), PNDegreeToRadian(90.0), NO);
    CGPathAddArc(borderPath, NULL, CGRectGetMinX(interiorRect), CGRectGetMaxY(interiorRect), radius, PNDegreeToRadian(90.0), PNDegreeToRadian(180.0), NO);

    CGContextBeginPath(maskedContextRef);
    CGContextAddPath(maskedContextRef, borderPath);
    CGContextClosePath(maskedContextRef);
    CGContextClip(maskedContextRef);

    [self drawInRect: dstRect];

    maskedImage = UIGraphicsGetImageFromCurrentImageContext();
    CGContextRestoreGState(maskedContextRef);
    UIGraphicsEndImageContext();

    return maskedImage;
}

und hier ist das Crash-Protokoll. Es sieht genauso aus, wenn ich eine dieser Abstürze

erhalten
Exception Type:  EXC_BAD_ACCESS (SIGSEGV)
Exception Codes: KERN_INVALID_ADDRESS at 0x6e2e6181
Crashed Thread:  0

Thread 0 Crashed:
0   com.apple.CoreGraphics          0x30fe56d8 CGGStateGetRenderingIntent + 4
1   libRIP.A.dylib                  0x33c4a7d8 ripc_RenderImage + 104
2   libRIP.A.dylib                  0x33c51868 ripc_DrawImage + 3860
3   com.apple.CoreGraphics          0x30fecad4 CGContextDelegateDrawImage + 80
4   com.apple.CoreGraphics          0x30feca40 CGContextDrawImage + 368
5   UIKit                           0x30a6a708 -[UIImage drawInRect:blendMode:alpha:] + 1460
6   UIKit                           0x30a66904 -[UIImage drawInRect:] + 72
7   MyApp                           0x0003f8a8 -[UIImage(PNAdditions) borderedImageWithRect:radius:] (UIImage+PNAdditions.m:187)
War es hilfreich?

Lösung

Dies ist eine noch einfachere Methode, die in iPhone 3.0 oder höher verfügbar ist. Jedes View-basierte Objekt hat eine zugehörige Schicht. Jede Schicht einen Eckenradius Satz haben kann, dies wird Ihnen genau das, was Sie wollen:

UIImageView * roundedView = [[UIImageView alloc] initWithImage: [UIImage imageNamed:@"wood.jpg"]];
// Get the Layer of any view
CALayer * l = [roundedView layer];
[l setMasksToBounds:YES];
[l setCornerRadius:10.0];

// You can even add a border
[l setBorderWidth:4.0];
[l setBorderColor:[[UIColor blueColor] CGColor]];

Andere Tipps

Ich werde vorangehen hier und tatsächlich die Frage im Titel beantworten.

Versuchen Sie, diese Kategorie.

UIImage + additions.h

#import <UIKit/UIKit.h>

@interface UIImage (additions)
-(UIImage*)makeRoundCornersWithRadius:(const CGFloat)RADIUS;
@end

UIImage + additions.m

#import "UIImage+additions.h"

@implementation UIImage (additions)
-(UIImage*)makeRoundCornersWithRadius:(const CGFloat)RADIUS {
    UIImage *image = self;

    // Begin a new image that will be the new image with the rounded corners
    // (here with the size of an UIImageView)
    UIGraphicsBeginImageContextWithOptions(image.size, NO, image.scale);

    const CGRect RECT = CGRectMake(0, 0, image.size.width, image.size.height);
    // Add a clip before drawing anything, in the shape of an rounded rect
    [[UIBezierPath bezierPathWithRoundedRect:RECT cornerRadius:RADIUS] addClip];
    // Draw your image
    [image drawInRect:RECT];

    // Get the image, here setting the UIImageView image
    //imageView.image
    UIImage* imageNew = UIGraphicsGetImageFromCurrentImageContext();

    // Lets forget about that we were drawing
    UIGraphicsEndImageContext();

    return imageNew;
}
@end

Wenn appIconImage ein UIImageView, dann:

appIconImage.image = [UIImage imageWithContentsOfFile:@"image.png"]; 
appIconImage.layer.masksToBounds = YES;
appIconImage.layer.cornerRadius = 10.0;
appIconImage.layer.borderWidth = 1.0;
appIconImage.layer.borderColor = [[UIColor grayColor] CGColor];

Und auch nicht vergessen:

#import <QuartzCore/QuartzCore.h>

Ich kann nicht nur die Einsicht in den Absturz bieten, aber ich dachte, dass ich eine andere Möglichkeit bieten würde, die Ecken für die Rundung. Ich hatte ein ähnliches Problem in einer Anwendung auftritt i arbeitet. Anstatt einen Code schreiben Ich bin überlagert ein anderes Bild, das Masken aus den Ecken.

Wenn Sie Ihre Methode (borderedImageWithRect) in einem Hintergrund-Thread aufrufen, Abstürze auftreten könnten, da UIGraphics-Funktionen nicht Thread-sicher sind. In einem solchen Fall müssen Sie einen Kontext erstellen mit CGBitmapContextCreate () - siehe „Reflection“ Beispielcode aus dem SDK

.

Der einfachste Weg ist ein behindertes einzubetten [!] Round-rect [nicht Gewohnheit!] -Taste in der Ansicht (kann es auch alle im Interface Builder) und verknüpfen Sie Ihr Bild mit ihm. Die Bildaufbauinformation ist unterschiedlich für UIButton (im Vergleich zu UIImageView), aber die gesamten Flickschusterei wirkt wie ein Zauber. Verwenden Sie setImage: forState: Wenn Sie eine zentrierte Symbol oder setBackgroundImage wollen: forState: Wenn Sie das gesamte Bild mit Ecken schneiden möchten (wie Kontakte). Natürlich, wenn Sie viele dieser Bilder in Ihrem drawRect angezeigt werden sollen dies ist nicht der richtige Ansatz, sondern eher eine eingebettete Ansicht ist genau das, was Sie ohnehin benötigt ...

Ich möchte nochmals wiederholen, fjoachim Antwort : vorsichtig sein, wenn versucht wird, während zu ziehen läuft auf einem separaten Thread, oder Sie können EXC_BAD_ACCESS Fehler erhalten.

Meine Abhilfe ging etwas wie folgt aus:

UIImage *originalImage = [UIImage imageNamed:@"OriginalImage.png"] 
[self performSelectorOnMainThread:@selector(displayImageWithRoundedCorners:) withObject:originalImage waitUntilDone:YES];

(In meinem Fall war ich Ändern der Größe / Skalierung UIImages.)

Ich hatte eigentlich eine Chance darüber mit jemandem von Apple auf der iPhone Tech Talk in New York zu sprechen. Wenn wir darüber gesprochen, er war ziemlich sicher, dass es kein Einfädeln ausgestellt ist. Stattdessen dachte er, dass ich den Grafikkontext behalten erforderlich, die erzeugt wurde, als UIGraphicsBeginImageContext Aufruf. Dies scheint die allgemeinen Regeln zu verletzen, den Umgang mit Regeln halten und Namensschemata, aber dieser Kerl war ziemlich sicher, dass er das Problem gesehen hat zuvor.

Wenn der Speicher gekritzelt war immer, vielleicht von einem anderen Thread, das wäre sicherlich erklären, warum ich nur gelegentlich das Problem zu sehen.

Ich habe keine Zeit gehabt, um den Code zu überdenken und das Update zu testen, aber PCheese Bemerkung machte mir klar, ich nicht die Informationen hier gepostet hatte.

... es sei denn, ich, dass nach unten falsch und UIGraphicsBeginImageContext sollte habe geschrieben CGBitmapContextCreate ...

Wenn es nur einen Teil der Zeit abstürzt, herauszufinden, was die Crash-Fälle gemeinsam haben. Ist dstRect jedes Mal die gleiche? Sind die Bilder, die jemals eine andere Größe?

Außerdem müssen Sie CGPathRelease(borderPath), obwohl ich bezweifle, dass Leck Ihr Problem verursacht.

UIImage *originalImage = [UIImage imageNamed:@"OriginalImage.png"] 
[self performSelectorOnMainThread:@selector(displayImageWithRoundedCorners:) withObject:originalImage waitUntilDone:YES];

In Swift 4.2 und Xcode 10.1

let imgView = UIImageView()
imgView.frame = CGRect(x: 200, y: 200, width: 200, height: 200)
imgView.image = UIImage(named: "yourimagename")
imgView.imgViewCorners()
//If you want complete round shape
//imgView.imgViewCorners(width: imgView.frame.width)//Pass ImageView width
view.addSubview(imgView)

extension UIImageView {
//If you want only round corners
func imgViewCorners() {
    layer.cornerRadius = 10
    layer.borderWidth = 1.0
    layer.borderColor = UIColor.red.cgColor
    layer.masksToBounds = true
}
//If you want complete round shape
func imgViewCorners(width:CGFloat) {
    layer.cornerRadius = width/2
    layer.borderWidth = 1.0
    layer.borderColor = UIColor.red.cgColor
    layer.masksToBounds = true
}

Stellen Sie das Bild in xib oder Storyboard (Bildbreite und -höhe 41x41).

FirstViewController.h

@interface....

IBOutlet UIImageView *testImg;

@end

FirstViewController.m

-(void)viewDidLoad{
        testImg.layer.backgroundColor=[[UIColor clearColor] CGColor];
        testImg.layer.cornerRadius=20;
        testImg.layer.masksToBounds = YES;
    }
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top